You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core 7 Web API集成OpenTelemetry报错:AspNetCoreInstrumentationOptions无Enrich定义

问题:OpenTelemetry AspNetCoreInstrumentationOptions 无 Enrich 定义,无法提取 TraceId/SpanId

已配置Jaeger/OpenTelemetry链路追踪且能正常生成数据,但尝试手动访问追踪上下文并赋值到自定义变量时,触发错误:

'AspNetCoreInstrumentationOptions' does not contain a definition for 'Enrich' and no accessible extension method 'Enrich' accepting a first argument of type 'AspNetCoreInstrumentationOptions' could be found (are you missing a using directive or an assembly reference?)

目标是从接口调用的追踪数据中提取Activity.TraceId和Activity.SpanId,赋值到以下自定义静态List:

namespace CustomerAPI.Helpers
{
    public static class CorrelationData
    {
        public static List<KeyValuePair<string, string>> Correlation { get; set; } = new List<KeyValuePair<string, string>>();
    }
}

尝试修改.AddAspNetCoreInstrumentation()配置时触发上述错误,代码如下:

using OpenTelemetry;
using OpenTelemetry.Trace;
using OpenTelemetry.Resources;
using OpenTelemetry.Metrics;
using OpenTelemetry.Instrumentation.Http;
using OpenTelemetry.Exporter.Jaeger;
using OpenTelemetry.Exporter;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

var appBuilder = WebApplication.CreateBuilder(args);

appBuilder.Services.AddOpenTelemetry()
    .ConfigureResource(builder => builder.AddService(serviceName: "CustomerAPI"))
    .WithTracing(builder => builder
        .AddAspNetCoreInstrumentation(options =>
        {
            options.Filter = httpContext => true;
            options.Enrich = activity =>
            {
                // Extract trace information
                var traceId = activity.TraceId;
                var spanId = activity.SpanId;

                // Add trace information to the Correlation list
                CorrelationData.Correlation.Add(new KeyValuePair<string, string>("Activity.TraceId", traceId.ToHexString()));
                CorrelationData.Correlation.Add(new KeyValuePair<string, string>("Activity.SpanId", spanId.ToHexString()));

                return;
            };
        })
        .AddHttpClientInstrumentation()
        .AddConsoleExporter()
        .AddJaegerExporter(o =>
        {
            o.AgentHost = "localhost";
            o.AgentPort = 6831;
            o.Endpoint = new Uri("localhost:14268");
            o.Protocol = JaegerExportProtocol.UdpCompactThrift;
        }))
    .WithMetrics(builder => builder.AddConsoleExporter());
    
appBuilder.Services.AddControllers();
appBuilder.Services.AddHttpClient();

appBuilder.Services.AddEndpointsApiExplorer();

解决方案

1. 补全缺失的依赖与命名空间

Enrich方法属于OpenTelemetry.Instrumentation.AspNetCore包的扩展功能,你需要:

  • 安装NuGet包:OpenTelemetry.Instrumentation.AspNetCore(确保版本与其他OpenTelemetry包一致)
  • 在代码顶部添加命名空间引用:
    using OpenTelemetry.Instrumentation.AspNetCore;
    

2. 修正Enrich的方法签名

AspNetCoreInstrumentationOptions的Enrich委托并非仅接收Activity参数,正确签名包含三个参数:Activity、事件名称string、原始对象object。修正后的配置代码如下:

.AddAspNetCoreInstrumentation(options =>
{
    options.Filter = httpContext => true;
    options.Enrich = (activity, eventName, rawObject) =>
    {
        // 建议只在Span启动时处理,避免重复添加
        if (eventName == "OnStartActivity")
        {
            var traceId = activity.TraceId.ToHexString();
            var spanId = activity.SpanId.ToHexString();
            
            // 注意:静态List存在线程安全问题,多请求并发会导致异常,建议改用AsyncLocal存储
            CorrelationData.Correlation.Add(new KeyValuePair<string, string>("Activity.TraceId", traceId));
            CorrelationData.Correlation.Add(new KeyValuePair<string, string>("Activity.SpanId", spanId));
        }
    };
})

3. 更直接的访问方式:使用Activity.Current

无需通过Enrich,在请求处理的任意阶段(控制器、中间件、服务中),都可以直接通过Activity.Current获取当前追踪上下文:

// 在控制器Action中示例
[ApiController]
[Route("api/customers")]
public class CustomerController : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        var traceId = Activity.Current?.TraceId.ToHexString();
        var spanId = Activity.Current?.SpanId.ToHexString();
        
        // 赋值到自定义变量
        if (traceId != null && spanId != null)
        {
            CorrelationData.Correlation.Add(new KeyValuePair<string, string>("Activity.TraceId", traceId));
            CorrelationData.Correlation.Add(new KeyValuePair<string, string>("Activity.SpanId", spanId));
        }
        
        return Ok();
    }
}

注意事项

  • 静态List<KeyValuePair<string, string>>存在严重线程安全问题,多请求并发时会引发InvalidOperationException,建议改用AsyncLocal<T>来存储请求级别的关联数据:
    namespace CustomerAPI.Helpers
    {
        public static class CorrelationData
        {
            private static readonly AsyncLocal<Dictionary<string, string>> _correlation = new();
            
            public static Dictionary<string, string> Correlation
            {
                get => _correlation.Value ??= new Dictionary<string, string>();
                set => _correlation.Value = value;
            }
        }
    }
    

内容的提问来源于stack exchange,提问作者Golide

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 01:37:20