Reputation: 23214
I am trying to get Tracing using OpenTelemetry to work with HttpClient
in an integration test for an Asp.NET API.
Tracing works for everything else, we get traces from the API controllers and all other instrumented libraries.
Configuration looks like this:
webApplicationBuilder.Services.AddOpenTelemetryTracing(b =>
b.SetResourceBuilder(resourceBuilder)
.AddHttpClientInstrumentation()
.AddAspNetCoreInstrumentation()
.AddProtoActorInstrumentation()
.AddRedisInstrumentation()
.AddOtlpExporter(options =>
{
ConfigureOpenTelemetry(webApplicationBuilder, options);
})
);
But when calling the API using HttpClient. the current TraceId is not propagated.
The integration test uses a MyAppFactory : WebApplicationFactory<Program>
for the test.
And the HttpClient is constructed in the tests using the factory.CreateClient()
of the MyAppFactory.
If I check the Activity.Current.TraceId
inside my integration test. I get one value.
Then directly after, when I call the API using the HttpClient, the API controller reports a different TraceId.
There are also no w3c trace context headers in the Request
inside the controller method.
What am I missing here?
Upvotes: 3
Views: 3382
Reputation: 1899
I had a look into this and discovered that SocketsHttpHandler
has a code path to initialize a DiagnosticsHandler
that emits the HTTP request events, which other tools like OpenTelemetry listen for to trace requests.
However, as the HttpClient
used with WebApplicationFactory
doesn't need to send network requests (as the test application is loaded within the same process), it has a custom ClientHandler
that doesn't care about diagnostic events.
This sounds like an oversight in either WebApplicationFactory
or OpenTelemetry, but either way it doesn't seem to work.
I think the workaround would be to pass a custom handler into Factory.CreateClient
, and have that handler inject the traceparent
HTTP header manually based on Activity.Current
, following the behaviour of the code in TraceContextPropagator.cs as a template.
Upvotes: 3