Search code examples
azureasp.net-coreloggingazure-application-insightsserilog

Using outputTemplate argument in Serilog with Azure Application Insights


I'm currently implementing Azure Application Insights logging with Serilog which is working fine except for when I use an output template in my Serilog configuration. It seems like the template is ignored when passing the Serilog data to Application insights.

My serilog config in appsetting.json:

"Serilog": {
    "Using": [ "Serilog.Sinks.ApplicationInsights" ],
    "MinimumLevel": "Debug",
    "WriteTo": [
      { "Name": "Console" },
      {
        "Name": "RollingFile",
        "Args": {
          "pathFormat": "logs\\log-{Date}.txt",
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}"
        }
      },
      {
        "Name": "ApplicationInsights",
        "Args": {
          "restrictedToMinimumLevel": "Information",
          "telemetryConverter": "Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights",
          "outputTemplate": "Test Template - {Message}"
        }
      }
    ],
    "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
    "Properties": {
      "Application": "app"
    }
  },

The logging statement:

logger.Error("Test Serilog Error For AI - " + DateTime.Now);

The output within application insights:

enter image description here

Is this the correct approach to customising an error message for Application insights?


Solution

  • After checking the source code serilog-sinks-applicationinsights, you will find it did not read the outputTemplate from appsetting.json.

    For a workaround, you may implement custom TemplateTraceTelemetryConverter.

    1. TemplateTraceTelemetryConverter

      public class TemplateTraceTelemetryConverter : TraceTelemetryConverter
      {
          public override IEnumerable<ITelemetry> Convert(LogEvent logEvent, IFormatProvider formatProvider)
          {
              var templateParser = new MessageTemplateParser();
              var template = templateParser.Parse($"Test Template - {logEvent.MessageTemplate.Text}");
              LogEvent newLogEvent = new LogEvent(logEvent.Timestamp
                  , logEvent.Level
                  , logEvent.Exception
                  , template
                  , logEvent.Properties.Select(p => new LogEventProperty(p.Key, p.Value)));
              return base.Convert(newLogEvent, formatProvider);
          }
      }
      
    2. Use TemplateTraceTelemetryConverter

      "Serilog": {
          "Using": [
          "Serilog.Sinks.ApplicationInsights",
          ],
          "MinimumLevel": "Debug",
          "WriteTo": [
          {
              "Name": "Console",
              "Args": {
              "outputTemplate": "Test Template - {Message}"
              }
          },
          {
              "Name": "RollingFile",
              "Args": {
              "pathFormat": "logs\\log-{Date}.txt",
              "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}"
              }
          },
          {
              "Name": "ApplicationInsights",
              "Args": {
              "restrictedToMinimumLevel": "Error",          
              "telemetryConverter": "YourProjectNamespace.TemplateTraceTelemetryConverter, YourProjectNamespace"
              //"outputTemplate": "Test Template - {Message}"
              }
          }
          ],
          "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
          "Properties": {
          "Application": "app"
          }
      }