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

.NET OpenTelemetry泛型主机托管服务未添加ActivitySource监听器问题

问题分析与解决方案

核心原因

  1. 单元测试主机生命周期未正确管理:你在单元测试中仅调用了Build()但未启动主机(StartAsync),导致OpenTelemetry的TracerProvider还未完成初始化,托管服务的ExecuteAsync就提前执行了,此时还没有监听器附加到ActivitySource。而长期运行的工作服务会完整启动主机,等待所有服务初始化完成后才执行托管服务逻辑,因此不会出现这个问题。

  2. 静态ActivitySource初始化时机过早:TestService中的ActivitySource是静态字段,会在类首次被访问时就创建,这个时间点可能早于OpenTelemetry注册监听器的时机,导致OpenTelemetry无法捕获到这个已存在的ActivitySource(旧版本OpenTelemetry对已存在的源支持有限)。

  3. 预发布版本潜在问题:你使用的OpenTelemetry.Extensions.Hosting是1.0.0-rc9.5预发布版本,存在一些生命周期管理的bug,可能导致TracerProvider无法正确绑定到ActivitySource。


解决方案

1. 正确管理单元测试中的主机生命周期

在单元测试中,必须启动主机并等待初始化完成后再执行测试逻辑,测试结束后停止主机:

var stoppingToken = new CancellationTokenSource().Token;
var host = Host.CreateDefaultBuilder()
    .ConfigureServices((context, services) =>
    {
        services
            .AddSingleton<MyClass>()
            .AddSingleton(new ActivitySource("TestService")) // 注入ActivitySource
            .AddOpenTelemetryTracing(hostingBuilder =>
                hostingBuilder
                    .Configure((sp, builder) =>
                    {
                        var myClass = sp.GetRequiredService<MyClass>();
                        builder
                            .AddAspNetInstrumentation()
                            .AddHttpClientInstrumentation()
                            .AddConsoleExporter()
                            .AddSource("TestService*");
                    }))
            .AddHostedService<TestService>();
    })
    .Build();

// 启动主机,确保TracerProvider完成初始化
await host.StartAsync(stoppingToken);
try
{
    // 这里可以添加测试验证逻辑,比如等待托管服务执行完成
    await Task.Delay(1000, stoppingToken); // 根据实际逻辑调整等待时间
}
finally
{
    await host.StopAsync(stoppingToken);
    host.Dispose();
}

2. 避免静态ActivitySource,改用依赖注入

将ActivitySource注册为单例服务并注入到TestService中,确保它在TracerProvider初始化后才被使用:

internal class TestService : BackgroundService
{
    private readonly ActivitySource _testActivitySource;

    // 通过构造函数注入ActivitySource
    public TestService(ActivitySource testActivitySource)
    {
        _testActivitySource = testActivitySource;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await Task.Run(() =>
        {
            using (var activity = _testActivitySource.StartActivity("TestService", ActivityKind.Server))
            {
                if (activity == null)
                {
                    Console.WriteLine("Activity未创建:无监听器附加");
                    return;
                }
                Console.WriteLine("进入Activity代码块");
                activity.SetTag("foo", 1);
                Console.WriteLine($"Activity标签:{string.Join(", ", activity.Tags.Select(t => $"{t.Key}={t.Value}"))}");
            }
            Console.WriteLine("退出Activity代码块");
        }, stoppingToken);
    }
}

3. 升级OpenTelemetry包到稳定版

将预发布版本的包升级到稳定版,确保版本兼容性:

<package id="OpenTelemetry" version="1.6.0" />
<package id="OpenTelemetry.Api" version="1.6.0" />
<package id="OpenTelemetry.Exporter.Console" version="1.6.0" />
<package id="OpenTelemetry.Extensions.Hosting" version="1.6.0" />
<package id="OpenTelemetry.Instrumentation.AspNet" version="1.6.0" />
<package id="OpenTelemetry.Instrumentation.Http" version="1.6.0" />

注:移除OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule,该模块已被整合到新版AspNet Instrumentation中


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 11:30:57