Application Insights端到端事务视图无法显示多个组件问题排查
问题分析与解决方案
你遇到的核心问题是分布式跟踪上下文未在Service Bus消息传递过程中完整传递:虽然所有日志和跟踪都带有正确的Operation Id(TraceId),但Application Insights的端到端事务时间线需要完整的调用链关联(包含Parent Id、TraceId的层级关系)才能展示多组件流程。仅靠相同的TraceId不足以构建可视化的时间线,必须确保消费端的遥测数据有正确的Parent Id指向发送端的原始请求。
1. 发送端:传递完整的分布式跟踪上下文
修改DemoModel的OnPost方法,不再只传递RootId,而是将当前Activity的完整跟踪上下文注入到Service Bus消息的自定义属性中:
public class DemoModel : PageModel { private readonly ServiceBusSender _sender; public DemoModel(ServiceBusClient busClient) { _sender = busClient.CreateSender("actions"); } public async Task OnPost() { var currentActivity = System.Diagnostics.Activity.Current; var message = new ServiceBusMessage($"Event: {currentActivity?.RootId}"); // 注入完整的跟踪上下文到消息属性 if (currentActivity != null) { message.ApplicationProperties["traceparent"] = currentActivity.Id; message.ApplicationProperties["tracestate"] = currentActivity.TraceStateString; } await _sender.SendMessageAsync(message); } }
2. 消费端:恢复跟踪上下文并关联原始请求
在MessageHandler方法开头,从消息属性中提取跟踪上下文,创建关联的Activity,确保后续所有遥测数据都能关联到原始请求的调用链:
private async Task MessageHandler(ProcessMessageEventArgs arg) { ServiceBusReceivedMessage message = arg.Message; _logger.LogInformation("Body:, {body}", message.Body.ToString()); Activity? consumerActivity = null; // 从消息中提取跟踪上下文并启动关联的Activity if (message.ApplicationProperties.TryGetValue("traceparent", out var traceparentObj) && traceparentObj is string traceparent) { consumerActivity = new Activity("ServiceBus.Consume") .SetParentId(traceparent); if (message.ApplicationProperties.TryGetValue("tracestate", out var tracestateObj) && tracestateObj is string tracestate) { consumerActivity.TraceStateString = tracestate; } consumerActivity.Start(); } try { using var scope = _serviceProvider.CreateScope(); var client = scope.ServiceProvider.GetRequiredService<WeatherClient>(); using (_telemetryClient.StartOperation<RequestTelemetry>("sub operation")) { var lisbon = client.GetWeatherAsync("lisbon"); var london = client.GetWeatherAsync("london"); await Task.WhenAll(lisbon, london); _logger.LogInformation("Weather, {body}", lisbon.Result?.Region); _logger.LogInformation("Weather, {body}", london.Result?.Region); } var paris = await client.GetWeatherAsync("paris"); _logger.LogInformation("Weather, {body}", paris?.Region); await arg.CompleteMessageAsync(arg.Message); } finally { consumerActivity?.Stop(); } }
额外优化:使用SDK内置分布式跟踪
如果你使用的是Azure.Messaging.ServiceBus SDK(版本7.11.0及以上),可以直接启用内置的分布式跟踪,无需手动处理上下文传递:
在创建ServiceBusClient时配置启用跟踪:
var client = new ServiceBusClient(connectionString, new ServiceBusClientOptions { EnableDistributedTracing = true });
SDK会自动在发送消息时注入跟踪上下文,消费时自动恢复关联,简化代码逻辑。
验证要点
修改后检查Application Insights:
- 消费端的
sub operation请求遥测的ParentId应指向发送端POST请求的Id - 所有相关遥测(日志、请求、依赖项)的
TraceId需与原始POST请求一致 - 端到端事务时间线会自动展示MVC请求、Service Bus消息传递、消费端处理的完整流程
内容的提问来源于stack exchange,提问作者UTurista
相关产品推荐
相关产品推荐

