Christa smith
Christa smith

Reputation: 21

.NET 6 Serilog with Application Insights Instrumentation key not being picked up

We have a .net6 web API and worker project that we are trying to leverage Serilog to log to app insights.

We have an extension method existing in a common class library that is used in both solutions:

    /// <summary>
    /// Extension IHostBuilder method for configuring logging in projects.
    /// </summary>
    /// <param name="hostBuilder">IHostbuilder.</param>
    /// <returns>IHostBuilder.</returns>
    public static IHostBuilder ConfigureLogging(this IHostBuilder hostBuilder)
    {
        hostBuilder.UseSerilog((hostingContext, loggerConfiguration) =>
        {
            loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration);
    });

        return hostBuilder;
        }

We use this in the program.cs file

var builder = WebApplication.CreateBuilder(args); builder.Host.ConfigureLogging();

The following packages are installed in the common library and in the api library

<ItemGroup><PackageReference Include="Serilog.AspNetCore" Version="5.0" /> <PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0" /> <PackageReference Include="Serilog.Sinks.ApplicationInsights" Version="3.1.0" /> </ItemGroup>

The above packages are also installed in the API project.

We have it picking up the instrumentation key when placed inside the serilog block.. however this is discouraged as per their guidance here:https://github.com/serilog-contrib/serilog-sinks-applicationinsights#configuring-with-readfromconfiguration - "As mentioned above you can also pass an instrumentation key but it's actively discouraged"

We have the following configuration in appsettings.json in the API project as an example and it works when we reference the instrumentation key inside as shown below:

{
  "Serilog": {
    "Using": [
      "Serilog.Sinks.ApplicationInsights"
    ],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "System": "Warning"
      }
    },
    "WriteTo": [
      {
        "Name": "ApplicationInsights",
        "Args": {
           "instrumentationkey: "<key goes here>", 
          "telemetryConverter": "Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights"
        }
      }
    ],
    "Enrich": [ "FromLogContext" ],
    "Properties": {
      "Application": "Solution.Api"
    }
  }
}

We can also get it working through using environment variables, by adding the following into launchsettings.json:

"Solution.Api": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "launchUrl": "swagger",
      "applicationUrl": "https://localhost:7194;http://localhost:5194",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "APPINSIGHTS_INSTRUMENTATIONKEY": "<Insert instrumentation key>"
      }
    },

Ultimately, neither of these approaches seem correct and we want to have the instrumentation key in appSettings decoupled from serilog config as per best practice It seems this is a known issue and may be to do with .net6 https://github.com/serilog-contrib/serilog-sinks-applicationinsights/issues/176 Wondering if anyone knows what the issue is/we are missing?

Upvotes: 2

Views: 5191

Answers (1)

Josh Gust
Josh Gust

Reputation: 4445

My understanding of this issue is that it is around the move of application insights to a standard service as opposed to part of the app builder pipeline.

Serilog, as part of the app builder pipeline, is then trying to configure the sink from appsettings.json before the service provider is built, and therefore doesn't (currently) know how to look for the instrumentation key in a config object it doesn't own.

Our work around of the issue you've spelled out with a link to the GitHub issue 176 is to configure the Application Insights sink using the fluent api

loggerConfiguration.ReadFrom.Configuration(context.Configuration)
                            .WriteTo.ApplicationInsights(
                                   provider.GetRequiredService<TelemetryConfiguration>(),
                                   TelemetryConverter.Traces);

This work-around allows us to use the instrumentation key (or connection string) as it is meant to be used according to the App Insights documentation.

This does limit configuration driven control over levels of trace data that makes it through Serilog to the provider, but using standard logging provider configuration allows additional restriction to be applied to traces after those logs have passed through Serilog. As this is an after-Serilog filter applied directly to the logging provider, it can only be used to add restriction. It cannot be used to add exceptions.

Apart from this approach, you have already detailed the other two options I've seen as working setup:

  1. include the instrumentation key in the Serilog sink config
  2. use instrumentation key as an environment variable

Upvotes: 1

Related Questions