.NET 6 Azure Function中Serilog结构化日志在Application Insights未正常显示
我有一个运行在.NET 6上的Azure Function App,原本使用Microsoft.Extension.Logging进行日志记录,一切运行正常。现在有新需求要支持结构化日志,因此选择使用Serilog,但完成所有配置后,结构化日志并未在Application Insights中按预期显示。
Startup.cs中的Serilog配置
public override void Configure(IFunctionsHostBuilder builder) { var telemetryConfiguration = TelemetryConfiguration.CreateDefault(); telemetryConfiguration.ConnectionString = Settings.ApplicationInsightsConnectionString; // Create and initialize the dependency tracking module var dependencyModule = new DependencyTrackingTelemetryModule(); dependencyModule.Initialize(telemetryConfiguration); // Create the custom telemetry processor var telemetryProcessorChainBuilder = telemetryConfiguration.DefaultTelemetrySink.TelemetryProcessorChainBuilder; var configuration = builder.Services.BuildServiceProvider().GetService<IConfiguration>(); telemetryProcessorChainBuilder.Use(next => new CustomTelemetryProcessor(next, configuration)); // Build the telemetry processor chain telemetryProcessorChainBuilder.Build(); Log.Logger = new LoggerConfiguration() .WriteTo.ApplicationInsights(telemetryConfiguration, TelemetryConverter.Traces) .CreateLogger(); builder.Services.AddSingleton(telemetryConfiguration); builder.Services.AddSingleton(typeof(IAppLogger<>), typeof(AppLogger<>)); // rest of the code... }
日志记录代码
_logger.LogInformation("Log message {@LogMessage}", new LogMessage { ApplicationName = ApplicationDetails.ApplicationName, MethodName = AzureFunctionNames.Function1, IngressEvent = inputMessage.Payload.EventBody });
日志在Application Insights中显示为LogMessage的序列化JSON,而非可对LogMessage类各实体进行查询的结构化日志格式。
项目依赖包
<PackageReference Include="Azure.Storage.Blobs" Version="12.19.1" /> <PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" /> <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" /> <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.EventHubs" Version="5.1.0" /> <PackageReference Include="Microsoft.Extensions.Logging.ApplicationInsights" Version="2.22.0" /> <PackageReference Include="Microsoft.Identity.Client" Version="4.60.3" /> <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.3" /> <PackageReference Include="Serilog" Version="3.1.0" /> <PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" /> <PackageReference Include="Serilog.Formatting.Compact" Version="2.0.0" /> <PackageReference Include="Serilog.Sinks.ApplicationInsights" Version="3.1.0" /> <PackageReference Include="StyleCop.Analyzers" Version="1.1.118"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> <PackageReference Include="System.Net.Http" Version="4.3.4" /> <PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
核心原因
TelemetryConverter选择错误
使用TelemetryConverter.Traces会将Serilog结构化日志直接序列化为字符串写入AI的Trace遥测,导致结构化数据被扁平化,无法单独查询属性。未将Serilog注册为日志提供者
仅初始化了Serilog的Logger,但未将其添加到Function的日志系统中,导致基于Microsoft.Extension.Logging的AppLogger仍使用默认日志管道,未通过Serilog处理结构化日志。日志管道冲突
项目同时引用Microsoft.Extensions.Logging.ApplicationInsights和Serilog.Sinks.ApplicationInsights,两者可能产生冲突,干扰结构化日志的处理流程。
修复步骤
1. 替换TelemetryConverter
将TelemetryConverter.Traces改为TelemetryConverter.Events,该转换器会将结构化日志的属性映射为AI Event遥测的自定义属性,支持单独查询:
Log.Logger = new LoggerConfiguration() .WriteTo.ApplicationInsights(telemetryConfiguration, TelemetryConverter.Events) .CreateLogger();
若需保留Trace类型遥测,可使用自定义转换器来保留结构化属性,或配置Serilog.Sinks.ApplicationInsights的高级选项。
2. 注册Serilog为日志提供者
在Startup的Configure方法中,将Serilog添加到Function的日志服务:
builder.Services.AddLogging(loggingBuilder => { loggingBuilder.ClearProviders(); // 清除默认日志提供者,避免冲突 loggingBuilder.AddSerilog(dispose: true); });
3. 调整依赖包(推荐)
移除Microsoft.Extensions.Logging.ApplicationInsights包,避免与Serilog的AI Sink冲突:
<!-- 移除该包 --> <!-- <PackageReference Include="Microsoft.Extensions.Logging.ApplicationInsights" Version="2.22.0" /> -->
确保Serilog.Sinks.ApplicationInsights版本与其他Serilog包兼容(当前3.1.0与Serilog 3.1.0匹配)。
4. 验证日志封装
确认AppLogger正确注入ILogger<T>,且日志调用中的结构化语法{@LogMessage}未被封装逻辑破坏,确保结构化数据能正确传递给Serilog。
验证修复
部署修改后的Function App后,在Application Insights的Logs中执行查询:
customEvents | where name == "Log message" | project ApplicationName = customDimensions.ApplicationName, MethodName = customDimensions.MethodName
若使用Trace类型自定义转换器,查询traces表的customDimensions字段即可看到结构化属性。
内容的提问来源于stack exchange,提问作者Shri

