-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Closed
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarea-System.Net.Http
Milestone
Description
Background and motivation
This is part of #84978. For testability, we need to enable passing a custom Meter
to SocketsHttpHandler
and HttpClientHandler
. Since IMeterFactory
lives in Microsoft.Extensions.Diagnostics.Abstractions
, we cannot use it in System.Net.Http
.
API Proposal
I'm proposing to expose a property to set the Meter
instance directly.
namespace System.Net.Http;
public class HttpClientHandler
{
public Meter Meter { get; set; } // = DefaultGlobalMeterForHttpClient;
}
public class SocketsHttpHandler
{
public Meter Meter { get; set; } // = DefaultGlobalMeterForHttpClient;
}
The downside of this API is that it makes SocketsHttpHandler
's and HttpClientHandler
's responsibility to enforce the correct meter name in the property setter:
Also, the ownership semantics are somewhat counterintuitive, since SocketsHttpHandler.Dispose()
should not dispose it's Meter
instance.
API Usage
using Meter meter = new Meter("System.Net.Http");
using HttpClient client = new(new HttpClientHandler()
{
Meter = meter
});
// Use the client with the custom meter
// Because the recorder has the meter instance we care about, only values from this meter are captured.
var instrumentRecorder = new InstrumentRecorder<double>(meter, "http-client-request-duration");
// There is another InstrumentRecorder constructor that takes the meter name. If the meter name was used, "System.Net.Http",
// then all counter values with that meter name would be collected.
// var globalInstrumentRecorder = new InstrumentRecorder<double>(System.Net.Http", "http-client-request-duration");
// Make HTTP request.
var response = await client.GetAsync("https://www.bing.com");
var data = await response.Content.ReadAsBytesAsync();
// Assert recorded "http-client-request-duration" value and check the "status-code" tag.
Assert.Collection(instrumentRecorder.GetMeasurement(),
m => Assert.Equals(200, (int)m.Tags.ToArray().Single(t => t.Name == "status-code"));
Alternative Designs
- Instead of exposing the
Meter
directly, exposeFunc<MeterOptions, Meter>?
instead. - Move
IMeterFactory
toSystem.Diagnostics.Metrics
and exposeIMeterFactory
instead of exposing theMeter
.
Metadata
Metadata
Assignees
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarea-System.Net.Http