Appending Sitecore Logs into Application Insights

Sitecore uses log4net, which makes it relatively easy to set up new destinations for logs, etc.. One request we’d had was to log messages in the Sitecore logs into Application Insights.

I approached this by writing a custom appender, which would take our messages and write them to App Insights as Trace messages. This is what I came up with:

public class AppInsightsAppender : AppenderSkeleton
{
  private readonly TelemetryClient telemetryClient;

  public string Category
  {
    get;
    set;
  }

  public AppInsightsAppender()
  {
    this.telemetryClient = new TelemetryClient(TelemetryConfiguration.Active);
  }

  public override void OnClose()
  {
    this.telemetryClient.Flush();
    base.OnClose();
  }

  protected override void Append(LoggingEvent loggingEvent)
  {
    if (!string.IsNullOrEmpty(loggingEvent.RenderedMessage))
    {
      TraceTelemetry traceTelemetry = new TraceTelemetry(loggingEvent.RenderedMessage, AppInsightsAppender.GetSeverityLevel(loggingEvent.Level));
      this.AddCustomParameters(loggingEvent, traceTelemetry);
      this.telemetryClient.TrackTrace(traceTelemetry);
    }
  }

  private void AddCustomParameters(LoggingEvent loggingEvent, TraceTelemetry traceTelemetry)
  {
    traceTelemetry.Properties.Add("Domain", loggingEvent.Domain);
    traceTelemetry.Properties.Add("Identity", loggingEvent.Identity);
    traceTelemetry.Properties.Add("LoggerName", loggingEvent.LoggerName);
    traceTelemetry.Properties.Add("ThreadName", loggingEvent.ThreadName);
    traceTelemetry.Properties.Add("UserName", loggingEvent.UserName);
    traceTelemetry.Properties.Add("Category", this.Category);

    string exceptionRepresentation = loggingEvent.GetExceptionStrRep();
    if(!string.IsNullOrEmpty(exceptionRepresentation))
    {
      traceTelemetry.Properties.Add("StackTrace", exceptionRepresentation);
    }

    string[] keys = loggingEvent.Properties.GetKeys();
    foreach (string text in keys)
    {
      if (!traceTelemetry.Properties.ContainsKey(text) && text.StartsWith("log4net", StringComparison.InvariantCultureIgnoreCase))
      {
        traceTelemetry.Properties.Add(text, loggingEvent.Properties[text].ToString());
      }
    }
  }

  private static SeverityLevel GetSeverityLevel(Level loggingEventLevel)
  {
    if (!(loggingEventLevel == (Level)null) && loggingEventLevel.Value >= Level.INFO.Value)
    {
      if (loggingEventLevel.Value < Level.INFO.Value)
      {
        return SeverityLevel.Verbose;
      }
      if (loggingEventLevel.Value < Level.WARN.Value)
      {
        return SeverityLevel.Information;
      }
      if (loggingEventLevel.Value < Level.ERROR.Value)
      {
        return SeverityLevel.Warning;
      }
      if (loggingEventLevel.Value < Level.SEVERE.Value)
      {
        return SeverityLevel.Error;
      }
      return SeverityLevel.Critical;
    }
    return SeverityLevel.Verbose;
  }
}

Then, to configure this, I patched in the following:

<log4net>

	<root>
		<appender-ref ref="AppInsightsAppenderLog" desc="AppInsightsAppender" />
	</root>			
	<appender patch:after="root" name="AppInsightsAppenderLog" type="Sitecore.Foundation.AppInsights.Appenders.AppInsightsAppender, Sitecore.Foundation.AppInsights">
		<category value="Log" />
	</appender>
</log4net>

You can, of course, also use log4net filters to remove verbose messages, or only to record certain severity levels.

Appending Sitecore Logs into Application Insights

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.