使用Microsoft.Extensions.Hosting与.NET472时Activity为Null的OpenTelemetry问题
问题
在使用Microsoft.Extensions.Hosting的.NET 4.7.2应用中集成OpenTelemetry时,按以下方式创建Host后,创建新Activity返回Null:
Host.CreateDefaultBuilder() .ConfigureServices((hostContext, services) => { services.AddOpenTelemetry().WithTracing(tracerProviderBuilder => { tracerProviderBuilder .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MySample")) .AddConsoleExporter() .AddSource(serviceName); }).StartWithHost(); }) .Build();
对应的Activity创建代码:
var activitySource = new ActivitySource(serviceName); using var activity = activitySource.StartActivity("Hello");
但直接使用Sdk.CreateTracerProviderBuilder方式注册则能正常运行:
using var tracerProvider = Sdk.CreateTracerProviderBuilder() .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MySample")) .AddSource(serviceName) .AddConsoleExporter() .Build();
请问如何在第一种Host创建方式下,获取带有已配置监听器的ActivitySource?
解决方案
核心问题是:通过Host注册的OpenTelemetry TracerProvider,需要Host实际启动后才会初始化生效。你在Host Build完成后直接创建Activity时,Host还未启动,TracerProvider尚未激活,导致ActivitySource没有被监听,StartActivity返回Null。
按以下步骤修改即可解决:
1. 确保Host完成启动
调用host.Run()或host.Start()启动Host,再执行创建Activity的逻辑。
2. 通过依赖注入管理ActivitySource
不要手动实例化ActivitySource,将其注册为DI容器中的单例,确保和OpenTelemetry配置的源完全匹配,之后通过构造函数注入使用。
修改后的完整代码示例
注册服务与启动Host
Host.CreateDefaultBuilder() .ConfigureServices((hostContext, services) => { // 将ActivitySource注册为单例服务 services.AddSingleton(new ActivitySource(serviceName)); services.AddOpenTelemetry().WithTracing(tracerProviderBuilder => { tracerProviderBuilder .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MySample")) .AddConsoleExporter() .AddSource(serviceName); }).StartWithHost(); // 添加后台服务用于测试Activity逻辑(或在Host启动后执行你的业务代码) services.AddHostedService<ActivityTestService>(); }) .Build() .Run(); // 启动Host,此时TracerProvider会被初始化
后台服务中使用ActivitySource
public class ActivityTestService : IHostedService { private readonly ActivitySource _activitySource; // 通过构造函数注入ActivitySource public ActivityTestService(ActivitySource activitySource) { _activitySource = activitySource; } public Task StartAsync(CancellationToken cancellationToken) { // 此时Host已启动,TracerProvider已激活,Activity可正常创建 using var activity = _activitySource.StartActivity("Hello"); activity?.SetTag("business-id", "12345"); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { return Task.CompletedTask; } }
额外注意事项
.StartWithHost()方法会将TracerProvider的生命周期与Host绑定,Host启动时初始化TracerProvider,停止时自动销毁。- 禁止在
Host.Build()之后、Run/Start()之前执行创建Activity的逻辑,此时TracerProvider还未完成初始化。
内容的提问来源于stack exchange,提问作者sergi
相关产品推荐
相关产品推荐

