在控制台应用程序中将 Serilog 与 ApplicationInsights 一起使用时,从不调用 ITelemetryInitializer.Initialize

ext*_*ndy 4 c# serilog azure-application-insights .net-core

我在我的 .NET Core 3.1 控制台应用程序中按如下方式配置 DI:

services.AddSingleton<ITelemetryInitializer, TelemetryInitializer>();
services.AddApplicationInsightsTelemetryWorkerService(instrumentationKey);
Run Code Online (Sandbox Code Playgroud)

appSettings.json我有:

"Serilog": {
  "Using": [
    "Serilog.Sinks.Console",
    "Serilog.Sinks.ApplicationInsights"
  ],
  "MinimumLevel": "Information",
  "WriteTo": [
    {
      "Name": "Console",
      "Args": {
        "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}",
        "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact"
      }
    },
    {
      "Name": "ApplicationInsights",
      "Args": {
        "restrictedToMinimumLevel": "Information",
        "InstrumentationKey": "...",
        "telemetryConverter": "Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights",
        "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}",
        "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact"
      }
    }
  ],
  "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
}
Run Code Online (Sandbox Code Playgroud)

Serilog 的配置如下:

Host.CreateDefaultBuilder(args)
    .UseSerilog((hostingContext, loggerConfiguration) =>
        loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration)
    )
    .UseConsoleLifetime()
    .Build()
    .Run()
Run Code Online (Sandbox Code Playgroud)

我的初始化类:

public class TelemetryInitializer : ITelemetryInitializer
{
    public void Initialize(ITelemetry telemetry)
    {
        telemetry.Context.Cloud.RoleName = "something-something";
    }
}
Run Code Online (Sandbox Code Playgroud)

Initialize方法不过是不是当我登录使用被称为ILogger。如果我TelemetryClient直接解析并使用它登录,Initialize 调用。

我是否缺少 Serilog 的一些配置?

kri*_*shg 5

这似乎是一个小故障Serilog.Sinks.ApplicationInsights。从配置(代码参考)初始化接收器时,它会创建一个新的TelemetryClient,在TelemetryConfiguration注册的TelemetryInitializer可以与其关联之前导致活动。

要获得TelemetryInitilizer注入的 Active 配置,它需要TelemetryClient在 Serilog 初始化 App Insights 接收器之前创建一次实例。否则,尊重它就太晚了,因为内部AddApplicationInsightsTelemetryWorkerService注册TelemetryClient为单例。所以下面是我的工作代码,它只是TelemetryClient在初始化 Serilog 的 loggerConfiguration 之前做一个虚拟解析。

public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddApplicationInsightsTelemetryWorkerService(instrumentationKey);
                    services.AddSingleton<ITelemetryInitializer, TelemetryInitializer>();
                    services.AddHostedService<Worker>();
                })
                .UseSerilog((hostingContext, serviceProvider, loggerConfiguration) => {
                    serviceProvider.GetRequiredService<TelemetryClient>(); // just a dummy resolve
                    loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration);
                })
                .UseConsoleLifetime();
    }
Run Code Online (Sandbox Code Playgroud)

选项 2 是创建一个自定义 TelemetryConverter,它可以更新所需的上下文而不是使用Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter. 这将消除对初始化程序的依赖。

选项 3 是切换到基于代码的设置而不是配置,这将允许您传递TelemetryClientTelemetryConfiguration实例,如https://github.com/serilog/serilog-sinks-applicationinsights#configuring。但这可能不像基于配置的方法那样具有声明性。