Skip to content

Commit

Permalink
Flow the IMeterFactory to SocketsHttpHandler on Mobile (#90298)
Browse files Browse the repository at this point in the history
  • Loading branch information
MihaZupan committed Aug 10, 2023
1 parent f4d08e3 commit d5b4ab2
Showing 1 changed file with 63 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,52 @@ namespace System.Net.Http
{
public partial class HttpClientHandler : HttpMessageHandler
{
private readonly SocketsHttpHandler? _socketHandler;
private static readonly ConcurrentDictionary<string, MethodInfo?> s_cachedMethods = new();

private readonly HttpMessageHandler? _nativeHandler;
private MetricsHandler? _metricsHandler;
private IMeterFactory? _nativeMeterFactory;
private MetricsHandler? _nativeMetricsHandler;

private static readonly ConcurrentDictionary<string, MethodInfo?> s_cachedMethods =
new ConcurrentDictionary<string, MethodInfo?>();
private readonly SocketsHttpHandler? _socketHandler;

private IMeterFactory? _meterFactory;
private ClientCertificateOption _clientCertificateOptions;

private volatile bool _disposed;

private HttpMessageHandler Handler
{
get
{
if (IsNativeHandlerEnabled)
{
if (_nativeMetricsHandler is null)
{
// We only setup these handlers for the native handler. SocketsHttpHandler already does this internally.
HttpMessageHandler handler = _nativeHandler!;

if (DiagnosticsHandler.IsGloballyEnabled())
{
handler = new DiagnosticsHandler(handler, DistributedContextPropagator.Current);
}

MetricsHandler metricsHandler = new MetricsHandler(handler, _nativeMeterFactory, out _);

// Ensure a single handler is used for all requests.
if (Interlocked.CompareExchange(ref _nativeMetricsHandler, metricsHandler, null) != null)
{
handler.Dispose();
}
}

return _nativeMetricsHandler;
}
else
{
return _socketHandler!;
}
}
}

public HttpClientHandler()
{
if (IsNativeHandlerEnabled)
Expand Down Expand Up @@ -67,15 +101,34 @@ protected override void Dispose(bool disposing)
[CLSCompliant(false)]
public IMeterFactory? MeterFactory
{
get => _meterFactory;
get
{
if (IsNativeHandlerEnabled)
{
return _nativeMeterFactory;
}
else
{
return _socketHandler!.MeterFactory;
}
}
set
{
ObjectDisposedException.ThrowIf(_disposed, this);
if (_metricsHandler != null)

if (IsNativeHandlerEnabled)
{
throw new InvalidOperationException(SR.net_http_operation_started);
if (_nativeMetricsHandler is not null)
{
throw new InvalidOperationException(SR.net_http_operation_started);
}

_nativeMeterFactory = value;
}
else
{
_socketHandler!.MeterFactory = value;
}
_meterFactory = value;
}
}

Expand Down Expand Up @@ -720,8 +773,7 @@ public int MaxAutomaticRedirections
CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(request);
MetricsHandler handler = _metricsHandler ?? SetupHandlerChain();
return handler.SendAsync(request, cancellationToken);
return Handler.SendAsync(request, cancellationToken);
}

// lazy-load the validator func so it can be trimmed by the ILLinker if it isn't used.
Expand All @@ -737,23 +789,6 @@ public int MaxAutomaticRedirections
}
}

private MetricsHandler SetupHandlerChain()
{
HttpMessageHandler handler = IsNativeHandlerEnabled ? _nativeHandler! : _socketHandler!;
if (DiagnosticsHandler.IsGloballyEnabled())
{
handler = new DiagnosticsHandler(handler, DistributedContextPropagator.Current);
}
MetricsHandler metricsHandler = new MetricsHandler(handler, _meterFactory, out _);

// Ensure a single handler is used for all requests.
if (Interlocked.CompareExchange(ref _metricsHandler, metricsHandler, null) != null)
{
handler.Dispose();
}
return _metricsHandler;
}

private void ThrowForModifiedManagedSslOptionsIfStarted()
{
// Hack to trigger an InvalidOperationException if a property that's stored on
Expand Down

0 comments on commit d5b4ab2

Please sign in to comment.