ITelemetryInitializer.Initialize 在控制台应用程序中将 Serilog 与 ApplicationInsights 一起使用时从未被调用
ITelemetryInitializer.Initialize never being called when using Serilog with ApplicationInsights in Console application
我在我的 .NET Core 3.1 控制台应用程序中按如下方式配置 DI:
services.AddSingleton<ITelemetryInitializer, TelemetryInitializer>();
services.AddApplicationInsightsTelemetryWorkerService(instrumentationKey);
在 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" ]
}
Serilog配置如下:
Host.CreateDefaultBuilder(args)
.UseSerilog((hostingContext, loggerConfiguration) =>
loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration)
)
.UseConsoleLifetime()
.Build()
.Run()
我的初始化器class:
public class TelemetryInitializer : ITelemetryInitializer
{
public void Initialize(ITelemetry telemetry)
{
telemetry.Context.Cloud.RoleName = "something-something";
}
}
然而,当我使用 ILogger
登录时,Initialize
方法 而不是 被调用。如果我直接解析 TelemetryClient
并使用它登录,Initialize
是 调用。
我是否缺少 Serilog 的某些配置?
这似乎是 Serilog.Sinks.ApplicationInsights
的一个小故障。当从配置 (code reference) 初始化接收器时,它会创建一个新的 TelemetryClient
,在注册的 TelemetryInitializer
可以与之关联之前会导致活动 TelemetryConfiguration
。
要让 TelemetryInitilizer
注入 Active 配置,它需要在 Serilog 初始化 App Insights 接收器之前创建一次 TelemetryClient
实例。否则尊重它就太迟了,因为在内部 AddApplicationInsightsTelemetryWorkerService
注册 TelemetryClient
为单例。所以下面是我的工作代码,它只是在初始化 Serilog 的 loggerConfiguration 之前对 TelemetryClient
进行了虚拟解析。
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();
}
选项 2 是创建自定义 TelemetryConverter,它可以更新所需的上下文而不是使用 Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter
。这将消除对初始化程序的依赖。
选项 3 是切换到基于代码的设置而不是配置,这将允许您传递 TelemetryClient
或 TelemetryConfiguration
实例,例如 https://github.com/serilog/serilog-sinks-applicationinsights#configuring。但这可能不像基于配置的方法那样具有声明性。
我在我的 .NET Core 3.1 控制台应用程序中按如下方式配置 DI:
services.AddSingleton<ITelemetryInitializer, TelemetryInitializer>();
services.AddApplicationInsightsTelemetryWorkerService(instrumentationKey);
在 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" ]
}
Serilog配置如下:
Host.CreateDefaultBuilder(args)
.UseSerilog((hostingContext, loggerConfiguration) =>
loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration)
)
.UseConsoleLifetime()
.Build()
.Run()
我的初始化器class:
public class TelemetryInitializer : ITelemetryInitializer
{
public void Initialize(ITelemetry telemetry)
{
telemetry.Context.Cloud.RoleName = "something-something";
}
}
然而,当我使用 ILogger
登录时,Initialize
方法 而不是 被调用。如果我直接解析 TelemetryClient
并使用它登录,Initialize
是 调用。
我是否缺少 Serilog 的某些配置?
这似乎是 Serilog.Sinks.ApplicationInsights
的一个小故障。当从配置 (code reference) 初始化接收器时,它会创建一个新的 TelemetryClient
,在注册的 TelemetryInitializer
可以与之关联之前会导致活动 TelemetryConfiguration
。
要让 TelemetryInitilizer
注入 Active 配置,它需要在 Serilog 初始化 App Insights 接收器之前创建一次 TelemetryClient
实例。否则尊重它就太迟了,因为在内部 AddApplicationInsightsTelemetryWorkerService
注册 TelemetryClient
为单例。所以下面是我的工作代码,它只是在初始化 Serilog 的 loggerConfiguration 之前对 TelemetryClient
进行了虚拟解析。
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();
}
选项 2 是创建自定义 TelemetryConverter,它可以更新所需的上下文而不是使用 Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter
。这将消除对初始化程序的依赖。
选项 3 是切换到基于代码的设置而不是配置,这将允许您传递 TelemetryClient
或 TelemetryConfiguration
实例,例如 https://github.com/serilog/serilog-sinks-applicationinsights#configuring。但这可能不像基于配置的方法那样具有声明性。