Previously I posted about using a Log4Net Appender to record Sitecore logs to Application Insights. That code will write Trace Messages to App Insights. I’m already filtering the messages to WARN or above using standard Log4Net <filter>
s – but what if I need to filter more particular messages. Well, I wrote a telemetry processor to do this, just like Requests and Dependencies.
public class TraceFilter : ITelemetryProcessor
{
private readonly ITelemetryProcessor _nextProcessor;
public string MessageRegex { get; set; }
public string Category { get; set; }
public string LoggerName { get; set; }
public string UserName { get; set; }
public string FilterIfAllMatch { get; set; }
private Regex _rgx = null;
private bool _rgxInited = false;
public TraceFilter (ITelemetryProcessor nextProcessor)
{
FilterIfAllMatch = "true"; //Default to all must match
_nextProcessor = nextProcessor;
}
public void Process(ITelemetry telemetry)
{
TraceTelemetry traceTelemetry = telemetry as TraceTelemetry;
if (traceTelemetry != null)
{
int rule = 0;
int pass = 0;
if(!string.IsNullOrEmpty(MessageRegex))
{
if (_rgx == null && !_rgxInited)
{
_rgxInited = true;
try
{
_rgx = new Regex(MessageRegex, RegexOptions.IgnoreCase | RegexOptions.Compiled);
}
catch (Exception ex)
{
Log.Warn(string.Format("Application Insights: {0} - {1}", ex.GetType().ToString(), ex.Message), this);
_rgx = null;
}
}
if (_rgx != null)
{
rule++;
if (!_rgx.IsMatch(traceTelemetry.Message))
{
pass++;
}
}
}
if (!string.IsNullOrEmpty(Category))
{
rule++;
if (!traceTelemetry.Properties["Category"].Equals(Category, System.StringComparison.OrdinalIgnoreCase))
{
pass++;
}
}
if (!string.IsNullOrEmpty(LoggerName))
{
rule++;
if (!traceTelemetry.Properties["LoggerName"].Equals(LoggerName, System.StringComparison.OrdinalIgnoreCase))
{
pass++;
}
}
if (!string.IsNullOrEmpty(UserName))
{
rule++;
if (!traceTelemetry.Properties["UserName"].Equals(UserName, System.StringComparison.OrdinalIgnoreCase))
{
pass++;
}
}
if (FilterIfAllMatch == null || FilterIfAllMatch.Equals("true", System.StringComparison.OrdinalIgnoreCase))
{
// If all rules match, then there are no passes.
if (pass == 0 && rule > 0) return;
} else
{
// Else if any rules match, then there are no passes
if (pass < rule) return;
}
}
_nextProcessor.Process(telemetry);
}
public override string ToString()
{
return string.Format("TraceFilter: {0} , {1}, {2}, {3}, {4}", MessageRegex, Category, LoggerName, UserName, FilterIfAllMatch);
}
}
It can filter by a message (by Regex) or Category (see the appender), or LoggerName (which seems to be the class that raised the log message, not the Log4Net <logger>), or UserName (which seems to be what the app pool is running as).