.NET6.0 ASPCore应用向Grafana Tempo发送追踪数据的方案咨询
问题背景
我已经为这个问题折腾了两天,现有一个.NET 6.0 Web应用,需要将追踪数据发送到Grafana Tempo实例。目前应用已经配置了Jaeger作为追踪组件,现在要替换成Grafana Tempo,但尝试的所有方法都没成功,希望得到帮助。
已尝试的方案
- 调研实现方案
.NET有可与OpenTelemetry配合的库,但原本以为只需要OpenTracing即可,因为Tempo应该直接兼容Jaeger(Jaeger基于OpenTracing构建)。
- 尝试修改Jaeger端点
因为Jaeger支持OpenTracing,我尝试直接替换其端点,但未成功。代码如下:
services.AddOpenTracing(); // Adds the Jaeger Tracer. services.AddSingleton<ITracer>(sp => { var loggerFactory = sp.GetRequiredService<ILoggerFactory>(); var reporter = new RemoteReporter.Builder() .WithLoggerFactory(loggerFactory) .WithSender(new HttpSender("http://localhost:9411")) .Build(); var tracer = new Tracer.Builder(_serviceName) // The constant sampler reports every span. .WithSampler(new ConstSampler(true)) // LoggingReporter prints every reported span to the logging framework. .WithReporter(reporter) .Build(); return tracer; }); services.Configure<HttpHandlerDiagnosticOptions>(options => options.OperationNameResolver = request => $"{request.Method.Method}: {request?.RequestUri?.AbsoluteUri}");
业务代码中手动创建Span的逻辑:
using var scope = Tracer.BuildSpan(ControllerContext.ActionDescriptor.DisplayName) .StartActive(true); Console.WriteLine(scope.Span.Context.TraceId); scope.Span.Log("Requested all observation metadata");
- 尝试OpenTelemetry方案
我发现很多NuGet包只有预览版,文档显示需要用OTelCollector,但关于如何创建并连接到Tempo的说明很模糊。我跳过了Collector,尝试直接配置,但也没成功:
var serviceName = "Grafana.Tempo.POC.API"; var serviceVersion = "1.0.0"; // Configure important OpenTelemetry settings, the console exporter, and instrumentation library builder.Services.AddOpenTelemetryTracing( tracerProviderBuilder => { tracerProviderBuilder .AddConsoleExporter() .AddSource(serviceName) .SetResourceBuilder( ResourceBuilder.CreateDefault() .AddService(serviceName: serviceName, serviceVersion: serviceVersion) ) .AddHttpClientInstrumentation() .AddAspNetCoreInstrumentation() .AddSqlClientInstrumentation() .AddOtlpExporter( options => { options.Endpoint = new Uri("http://localhost:9411"); } ); } );
- Curl测试成功
查阅Grafana文档后测试了Curl示例,首次成功将追踪数据发送到Tempo,但手动调用API不适合实际开发:
curl -X POST http://localhost:9411 -H 'Content-Type: application/json' -d '[{ "id": "1234", "traceId": "0123456789abcdef", "timestamp": 1608239395286533, "duration": 100000, "name": "span from bash!", "tags": { "http.method": "GET", "http.path": "/api" }, "localEndpoint": { "serviceName": "shell script" } }]'
核心问题
- 从ASP.NET Core应用向Grafana Tempo发送追踪数据,最实用且简便的方案是什么?
- 是否可以直接使用Jaeger并仅修改配置重定向至Tempo?是否有其他配置选项可用?
- 是否必须使用OpenTelemetry Collector才能实现该功能?
补充环境:当前使用Win11、WSL2、Docker Desktop及.NET6.0测试,后续计划部署到Kubernetes环境。
解决方案
1. 最实用简便的方案:基于OpenTelemetry直接对接Tempo
推荐使用稳定版OpenTelemetry包对接Tempo,这是当前规范且长期维护的方案,步骤如下:
- 安装稳定NuGet包:无需使用预览版,安装以下正式版包:
OpenTelemetry.Extensions.HostingOpenTelemetry.Instrumentation.AspNetCoreOpenTelemetry.Instrumentation.HttpOpenTelemetry.Exporter.OpenTelemetryProtocol
- 修正OTLP配置:Tempo的OTLP HTTP默认端点为
http://localhost:4318/v1/traces(之前用的9411是Zipkin端口,属于关键错误),调整配置代码:
var serviceName = "Grafana.Tempo.POC.API"; var serviceVersion = "1.0.0"; builder.Services.AddOpenTelemetryTracing(builder => { builder .AddConsoleExporter() .AddSource(serviceName) .SetResourceBuilder( ResourceBuilder.CreateDefault() .AddService(serviceName, serviceVersion) ) .AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddSqlClientInstrumentation() .AddOtlpExporter(options => { options.Endpoint = new Uri("http://localhost:4318/v1/traces"); options.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.HttpProtobuf; }); });
- 手动创建Span的适配:推荐用
ActivitySource替代旧的OpenTracing方式,更符合OTel规范:
private static readonly ActivitySource _activitySource = new ActivitySource("Grafana.Tempo.POC.API"); // 在控制器方法中 using var activity = _activitySource.StartActivity(ControllerContext.ActionDescriptor.DisplayName); activity?.SetTag("http.method", HttpContext.Request.Method); activity?.AddEvent(new ActivityEvent("Requested all observation metadata"));
2. 可以直接用Jaeger重定向到Tempo,需修正端点与配置
Jaeger可直接对接Tempo,之前失败是因为用错了端点:
- 修正Jaeger端点:Tempo默认监听Jaeger HTTP协议的端口为
14268,修改HttpSender配置:
var reporter = new RemoteReporter.Builder() .WithLoggerFactory(loggerFactory) .WithSender(new HttpSender("http://localhost:14268/api/traces")) // 修正端点 .Build();
- 确保Tempo开启Jaeger接收器:Docker启动时需开启对应接收器,命令示例:
docker run -d -p 14268:14268 -p 4318:4318 grafana/tempo:latest --config.file=/etc/tempo-local.yaml
若用自定义配置文件,需明确启用Jaeger接收器:
receivers: jaeger: protocols: thrift_http: endpoint: 0.0.0.0:14268
3. 不需要必须使用OpenTelemetry Collector
直接从应用发送数据到Tempo完全可行,Collector仅在以下场景需要:
- 同时向多个后端发送追踪数据
- 需要对追踪数据进行预处理(采样、过滤、转换)
- 应用与Tempo存在网络隔离
你的场景下,不管用Jaeger直接对接还是OTel直接对接,都可以跳过Collector。
内容的提问来源于stack exchange,提问作者rutim
相关产品推荐
相关产品推荐

