ASP.NET WebHost下OpenTelemetry跨服务父子Span关联异常排查
问题描述
基于ASP.NET搭建的微服务使用WebHost构建宿主,在Startup.cs配置OpenTelemetry链路追踪后,Jaeger可接收Span,但Telemetry服务调用Customer服务时,Customer的Span虽处于同一Trace中,却未作为Telemetry的子Span关联展示。同时Customer服务出现警告:
Open Telemetry spans are not properly gettings their parent's span ID. (invalid parent span IDs=; skipping clock skew adjustment)
已配置AddAspNetCoreInstrumentation和AddHttpClientInstrumentation,但跨服务Span传递未生效。
排查与修复步骤
1. 确保使用注入的HttpClient实例
Telemetry服务调用Customer服务时,必须使用依赖注入获取的HttpClient,而非手动new HttpClient()。手动创建的HttpClient不会被OpenTelemetry的AddHttpClientInstrumentation拦截,无法传递Trace上下文。
错误示例:
var client = new HttpClient(); await client.GetAsync("http://customer-service/api");
正确示例:
private readonly HttpClient _httpClient; public TelemetryService(HttpClient httpClient) { _httpClient = httpClient; } // 调用Customer服务 await _httpClient.GetAsync("http://customer-service/api");
2. 清理冗余的ResourceBuilder配置
配置中重复设置了ResourceBuilder,可能导致上下文传递异常,移除重复项:
修改Startup.cs中的OpenTelemetry配置:
public virtual IServiceProvider ConfigureServices(IServiceCollection services) { // configure Open Telemetry services.AddOpenTelemetry() .ConfigureResource(resource => resource .AddService( serviceName: $"{Configuration["SubscriptionClientName"]} Service", serviceVersion: "1.0.0")) .WithTracing(builder => builder .SetSampler(new AlwaysOnSampler()) .AddSource($"{Configuration["SubscriptionClientName"]} Service") // 移除重复的SetResourceBuilder调用 .AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddGrpcClientInstrumentation() .AddEntityFrameworkCoreInstrumentation() .AddOtlpExporter(options => { options.Endpoint = new Uri("http://jaeger-allinone-collector.jaeger-observability.svc.cluster.local:4317"); options.Protocol = OtlpExportProtocol.Grpc; })); ... }
3. 验证AspNetCoreInstrumentation的头提取逻辑
Customer服务的AddAspNetCoreInstrumentation默认会提取W3C标准的traceparent头,若存在自定义中间件拦截请求头,需确保Trace相关头未被丢弃。可显式配置头提取规则(可选):
.AddAspNetCoreInstrumentation(options => { options.EnrichWithHttpRequest = (activity, request) => { if (request.Headers.TryGetValue("traceparent", out var traceParent)) { activity.SetTag("traceparent", traceParent.ToString()); } }; })
4. 检查请求头传递情况
通过日志或抓包工具,确认Telemetry服务发送的请求中包含traceparent、tracestate等W3C Trace Context头,这些是父子Span关联的核心标识。
5. 统一OpenTelemetry包版本
所有微服务使用的OpenTelemetry相关NuGet包版本必须完全一致,版本不一致可能导致上下文序列化/反序列化异常。需统一的包包括:
OpenTelemetryOpenTelemetry.Extensions.HostingOpenTelemetry.Instrumentation.AspNetCoreOpenTelemetry.Instrumentation.HttpOpenTelemetry.Exporter.OpenTelemetryProtocol
内容的提问来源于stack exchange,提问作者Metalzero2

