ASP.NET Core API中Application Insights缺失日志条目问题求助
问题现象
使用Application Insights监控ASP.NET Core Web API时,发现代码中按顺序执行的两条LogInformation日志,仅"edit order: ending handling request"条目被记录,"edit order: start handling request"条目缺失。
相关代码片段
命令处理类代码
public class EditOrderCommandHandler : IRequestHandler<EditOrderCommand, EditOrderResponseStatus> { readonly ILogger<EditOrderCommandHandler> _logger; readonly CqgHostService _cqgHostService; public EditOrderCommandHandler(ILogger<EditOrderCommandHandler> logger, CqgHostService cqgHostService) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _cqgHostService = cqgHostService; } public async Task<EditOrderResponseStatus> Handle(EditOrderCommand request, CancellationToken cancellationToken) { _logger.LogInformation($"edit order: start handling request: {request.SerializeObject()} -- at: {DateTime.UtcNow}"); await _cqgHostService.SendEditOrderAsync(request.AccountId, request.ClOrderId, request.Qty, request.LimitPrice, request.StopPrice, request.Duration, request.TenantId, request.OnBehalfOf); var editOrderResponseStatus = new EditOrderResponseStatus(); _logger.LogInformation($"edit order: ending handling request: {request.SerializeObject()} -- at: {DateTime.UtcNow}"); return await Task.FromResult(editOrderResponseStatus); } }
日志配置代码
builder.Logging .AddApplicationInsights(builder.Configuration.ApplicationInsightsInstrumentationKey()) .AddFilter<ApplicationInsightsLoggerProvider>(typeof(Program).FullName, LogLevel.Trace) .AddFilter<ApplicationInsightsLoggerProvider>(typeof(Startup).FullName, LogLevel.Trace) .AddFilter<ApplicationInsightsLoggerProvider>("", LogLevel.Information) .AddFilter<ApplicationInsightsLoggerProvider>("Microsoft", LogLevel.Information) .AddFilter<ApplicationInsightsLoggerProvider>("Default", LogLevel.Information);
查询语句与结果
初始Kusto查询
traces | where timestamp >= datetime('2023-10-12T17:24:00Z') and timestamp <= datetime('2023-10-12T17:26:00Z') | where message contains "edit order" | project timestamp, message, customDimensions, operation_Id | order by timestamp desc
查询结果
2023-10-12T17:25:50.8118518Z
edit order: ending handling request: {"ClOrderId":"OHPW-1745-00622_24582026746","Duration":2,"Qty":{"Significand":1,"HasSignificand":true,"Exponent":0,"HasExponent":true},"LimitPrice":5.2350,"StopPrice":0,"CreationDate":"2023-10-12T12:25:50.6475684-05:00","Instrument":"F.US.ZCEZ24","TenantId":"2347ef30-a972-4c99-ac2f-23e4c971adad","AccountId":1769007,"OnBehalfOf":"JBenson2"} -- at: 10/12/2023 5:25:50 PM
补充排查操作
执行采样率检查的Kusto查询:
union requests, dependencies, pageViews, browserTimings, exceptions, traces | where timestamp >= datetime('2023-10-12T17:24:00Z') and timestamp <= datetime('2023-10-12T17:26:00Z') | summarize RetainedPercentage = 100 / avg(itemCount) by bin(timestamp, 1h), itemType | order by itemType, timestamp asc
查询结果:
原因分析与解决方案
原因定位
从采样率查询结果可见,traces类型日志的保留率仅为10%,说明Application Insights启用了自适应采样。自适应采样会根据系统流量自动调整采样比例,流量高峰时部分Information级别日志会被随机丢弃,导致启动日志未被采集。
解决方案建议
- 全局禁用自适应采样
在appsettings.json中配置固定100%采样率:
{ "ApplicationInsights": { "Sampling": { "AdaptiveSamplingEnabled": false, "FixedRateSamplingPercentage": 100 } } }
- 针对特定日志保留采样
如果需要保留采样机制但确保关键日志不丢失,可添加自定义采样筛选器,强制保留EditOrderCommandHandler相关日志:
builder.Services.Configure<TelemetryConfiguration>(config => { var samplingProcessor = config.DefaultTelemetrySink.TelemetryProcessors .OfType<AdaptiveSamplingTelemetryProcessor>() .FirstOrDefault(); if (samplingProcessor != null) { // 自定义筛选逻辑:包含包含"edit order"的日志 config.TelemetryProcessors.Add(new CustomTraceSamplingProcessor(samplingProcessor)); } }); // 自定义采样处理器示例 public class CustomTraceSamplingProcessor : ITelemetryProcessor { private readonly ITelemetryProcessor _nextProcessor; public CustomTraceSamplingProcessor(ITelemetryProcessor nextProcessor) { _nextProcessor = nextProcessor; } public void Process(ITelemetry item) { if (item is TraceTelemetry trace && trace.Message.Contains("edit order")) { // 强制保留该日志 item.Context.SamplingPercentage = 100; } _nextProcessor.Process(item); } }
- 确保日志发送完成
日志异步发送时,若应用在日志发送前终止可能导致丢失,可在请求结束时等待日志发送完成:
app.Use(async (context, next) => { await next(); var telemetryClient = context.RequestServices.GetRequiredService<ITelemetryClient>(); await telemetryClient.FlushAsync(); await Task.Delay(500); // 给足够时间完成日志发送 });
内容的提问来源于stack exchange,提问作者nop

