-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
Meterdirectly, exposeFunc<MeterOptions, Meter>?instead. - Move
IMeterFactorytoSystem.Diagnostics.Metricsand exposeIMeterFactoryinstead of exposing theMeter.
Reactions are currently unavailable
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