Use of TraceHeaderPropagatingHandler in .NET Core 2.1
See original GitHub issueI am using Google.Cloud.Diagnostics.AspNetCore version 3.0.0-beta06. Due to the change of paradigm for creating HttpClient, the following code for tracing outgoing http requests via Stackdriver Trace does not align well with .NET Core 2.1 any longer:
/// <summary>
/// The <see cref="TraceHeaderPropagatingHandler"/> is populated by dependency injection.
/// </summary>
public async Task<HttpResponseMessage> TraceOutgoing(TraceHeaderPropagatingHandler traceHeaderHandler)
{
// Add a handler to trace outgoing requests and to propagate the trace header.
using (var httpClient = new HttpClient(traceHeaderHandler))
{
return await httpClient.GetAsync("https://weather.com/");
}
}
Instead, the HttpClient instance must be created via an injected IHttpClientFactory
(and “using” statement becomes unnecessary).
More importantly, the registration and “chaining” of HttpMessageHandler
into a handler pipeline is supposed to be configured at Startup.cs - ConfigureServices(), for example:
services.AddHttpClient("weather").AddHttpMessageHandler<TraceHeaderPropagatingHandler>();
The HttpClient infrastructure takes care of chaining the TraceHeaderPropagatingHandler
into the handler pipeline, but in return is asking that all handlers have a null InnerHandler
, otherwise an exception is thrown.
Unfortunately this is exactly what happens with TraceHeaderPropagatingHandler
System.InvalidOperationException: The 'InnerHandler' property must be null. 'DelegatingHandler' instances provided to 'HttpMessageHandlerBuilder' must not be reused or cached.
Handler: 'Google.Cloud.Diagnostics.Common.TraceHeaderPropagatingHandler'
at Microsoft.Extensions.Http.HttpMessageHandlerBuilder.CreateHandlerPipeline(HttpMessageHandler primaryHandler, IEnumerable`1 additionalHandlers)
at Microsoft.Extensions.Http.DefaultHttpClientFactory.CreateHandlerEntry(String name)
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Http.DefaultHttpClientFactory.CreateClient(String name)
at Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions.<>c__DisplayClass10_0`2.<AddTypedClient>b__0(IServiceProvider s)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitTransient(TransientCallSite transientCallSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
This is due to the fact that an InnerHandler
is always created by the TraceHeaderPropagatingHandler
constructor:
public TempTraceHeaderPropagatingHandler(
Func<IManagedTracer> managedTracerFactory, HttpMessageHandler innerHandler = null)
{
_managedTracerFactory = GaxPreconditions.CheckNotNull(managedTracerFactory, nameof(managedTracerFactory));
InnerHandler = innerHandler ?? new HttpClientHandler();
}
The implementation of the handler should be adjusted to support the new way of managing HttpClients in .NET Core.2.1.
Issue Analytics
- State:
- Created 5 years ago
- Comments:8 (6 by maintainers)
Using now the
AddOutgoingGoogleTraceHandler()
extension. Thanks for the fix. Cheers!Happy to help!