2

Why is OpenTelemetry .NET not adding a listener for my ActivitySource in a hosted service on generic host?

I have some configurations to pass into OpenTelemetry set-up, so I depend on a class MyClass. This means registering that class, and then configuring a callback action for TracerProviderBuilder which uses that class. However, when I later create an ActivitySource and start an Activity with ActivitySource.StartActivity(...) then it returns null because no listeners were attached to the source. By debugging and inspecting the ActivitySource, I could see the list of s_activeSources which included the OpenTelemetry.HttpRequest ActivitySource created by .AddHttpClientInstrumentation() so it's odd that no listener was added for that either.

Note: This is being run in a unit test and failing, whereas it is working in a long-running worker service program. Not sure if unit tests are too short-lived or are influenced by test environment e.g. Visual Studio

Below is a minimal version of my scenario:

Host.CreateDefaultBuilder()
.ConfigureServices((context, services) =>
{
    services
    .AddSingleton<MyClass>()
    .AddOpenTelemetryTracing(hostingBuilder =>
        hostingBuilder
        .Configure(
            (sp, builder) =>
            {
                var myClass = sp.GetRequiredService<MyClass>();
                
                // Do something with myClass on builder
                
                builder
                .AddAspNetInstrumentation()
                .AddHttpClientInstrumentation()
                .AddConsoleExporter()
                .AddSource("TestService*");
            }))
    .AddHostedService<TestService>();
})
.Build();

TestService.cs

internal class TestService : BackgroundService
{
    private static ActivitySource testActivitySource = new ActivitySource("TestService");

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await Task.Run(() =>
        {
            using (var activity = testActivitySource.StartActivity("TestService", ActivityKind.Server))
            {
                Console.WriteLine("I'm inside the activity using clause!");

                activity?.SetTag("foo", 1);

                Console.WriteLine($"activity.Tags: {activity.Tags}"); // This throws NullReferenceException since activity is null due to no listeners
            }

            Console.WriteLine("I'm outside the activity using clause!");
        });
    }
}

Package versions:

<package id="OpenTelemetry" version="1.3.0" />
<package id="OpenTelemetry.Api" version="1.3.0" />
<package id="OpenTelemetry.Exporter.Console" version="1.3.0" />
<package id="OpenTelemetry.Extensions.Hosting" version="1.0.0-rc9.5" />
<package id="OpenTelemetry.Instrumentation.AspNet" version="1.0.0-rc9.5" />
<package id="OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule" version="1.0.0-rc9.5" />
<package id="OpenTelemetry.Instrumentation.Http" version="1.0.0-rc9.5" />

I've also tried moving the .AddConsoleExporter() line out of the .Configure method and simply called straight away by hostingBuilder but still no listener attached to any ActivitySource.

Coal Chris
  • 21
  • 2

1 Answers1

1

In your unit test project, u have created the builder, but you haven't started the builder. Unless you don't start the Host it will not add the listener. Try using below code snippet.

var builder = Host.CreateDefaultBuilder()
            .ConfigureServices((context, services) =>
            {
                services
                .AddSingleton<MyClass>()
                .AddOpenTelemetryTracing(hostingBuilder =>
                    hostingBuilder
                    .Configure(
                        (sp, builder) =>
                        {
                            var myClass = sp.GetRequiredService<MyClass>();

                            // Do something with myClass on builder

                            builder
                            .AddAspNetInstrumentation()
                            .AddHttpClientInstrumentation()
                            .AddConsoleExporter()
                            .AddSource("TestService*");
                        }))
                .AddHostedService<TestService>();
            }).Build();

        var host = builder.Build();

        await host.StartAsync();

        await host.StopAsync();

        host.Dispose();
Amit Patil
  • 47
  • 3
  • I tried using both `await host.StartAsync(); await host.StopAsync();` and `host.RunAsync();` and both still have no listeners when debugging, causing `activity` to be null. – Coal Chris Sep 27 '22 at 02:21
  • Worked for me, thanks @Amit-Patil! – Aleksei Aug 17 '23 at 08:20