OpenTelemetry .NET与Sentry.io异常捕获问题:Span状态未正确标记
你遇到的核心问题是:手动捕获并记录到OpenTelemetry Activity的异常,没有在Sentry中标记对应Span为错误;而抛出异常时又生成了未关联到追踪的独立条目。结合你的代码和配置,原因主要集中在集成顺序、兼容性、异常关联逻辑这几点,以下是具体解决步骤:
1. 调整Sentry与OpenTelemetry的配置顺序
Sentry的初始化需要优先于OpenTelemetry的追踪配置,否则AddSentry()无法正确关联Sentry的上下文到OpenTelemetry Span中。修改Program.cs的代码顺序:
// 先初始化Sentry builder.WebHost.UseSentry(options => { options.Dsn = "https://***removed"; options.TracesSampleRate = 1.0; options.EnableTracing = true; options.Debug = true; options.UseOpenTelemetry(); }); // 再配置OpenTelemetry追踪 builder.Services.AddOpenTelemetry() .WithTracing(tracerProviderBuilder => tracerProviderBuilder .AddSource(DiagnosticsConfig.ActivitySource.Name) .ConfigureResource(resource => resource .AddService(DiagnosticsConfig.ServiceName)) .AddAspNetCoreInstrumentation(option => option.RecordException = true) .AddHttpClientInstrumentation(option => option.RecordException = true) .AddSentry() // 确保这是最后添加的处理器 );
2. 升级NuGet包版本
你使用的OpenTelemetry 1.5.1和Sentry 3.34存在已知的兼容性问题,部分Span状态同步、异常关联的逻辑在后续版本中得到修复。建议升级到:
- OpenTelemetry ≥ 1.6.0
- Sentry ≥ 3.40.0
3. 修正Span异常关联逻辑
方案A:让异常向上抛出(推荐)
如果不需要在DoChecks中捕获异常,直接让异常冒泡到ASP.NET Core的请求管道,AspNetCoreInstrumentation会自动记录异常并关联到Span,Sentry会自动标记对应Span为错误:
public static class SecureOrderChecks { public static async Task DoChecks() { using var activity = DiagnosticsConfig.ActivitySource.StartActivity("Secure Order Checks"); await Task.Delay(5000); throw new Exception("Oops!"); // 移除try-catch,让异常向上传播 } }
此时需要确保你的控制器/端点没有捕获这个异常,或者捕获后重新抛出,保证ASP.NET Core的异常处理中间件能感知到异常。
方案B:手动关联异常到Span(适合必须捕获异常的场景)
如果必须在DoChecks中捕获异常,需要手动将Sentry事件关联到当前Activity的TraceId和SpanId,确保异常被纳入追踪:
public static class SecureOrderChecks { public static async Task DoChecks() { using var activity = DiagnosticsConfig.ActivitySource.StartActivity("Secure Order Checks"); try { await Task.Delay(5000); throw new Exception("Oops!"); } catch (Exception ex) { activity?.RecordException(ex); activity?.SetStatus(Status.Error.WithDescription(ex.Message)); // 手动关联Sentry事件到当前Span if (activity != null) { var scope = SentrySdk.GetCurrentScope(); scope.SetSpanId(activity.SpanId.ToString()); scope.SetTraceId(activity.TraceId.ToString()); SentrySdk.CaptureException(ex); } } } }
4. 验证Sentry Span状态
完成上述调整后,重新发起请求,在Sentry的Traces页面查看完整追踪,对应Secure Order Checks的Span应该会被标红;在Discover页面查看该Span的详情,状态会显示为error,且异常信息会关联到Span中。
内容的提问来源于stack exchange,提问作者Sulphy

