-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: HttpClient/HttpMessageInvoker metrics #84978
Comments
Tagging subscribers to this area: @dotnet/ncl Issue DetailsBackground and motivationSystem.Net.Http has event counters. In .NET 8 we want to add metrics counters. These will sit side-by-side with event counters for backward compatibility. Metrics counters add new features (histograms, tags) that allow for richer data to be represented by fewer counters. For example, there are event counters in hosting for API ProposalThe proposal for this issue covers the meter name, counters name and description and tags. The IDs and names are a public API that can't easily change after shipping. System.Net.HttpNotes:
|
Name | Instrument Type | Unit | Description |
---|---|---|---|
current-requests |
UpDownCounter | {request} |
Number of outbound HTTP requests that are currently active on the client. |
Attribute | Type | Description | Examples | Presence |
---|---|---|---|---|
method |
string | HTTP request method. | GET ; POST ; HEAD |
Always |
scheme |
string | The URI scheme identifying the used protocol. | http ; https |
Always |
host |
string | Host identifier of the "URI origin" HTTP request is sent to. | localhost |
Always |
port |
int | Port identifier of the "URI origin" HTTP request is sent to. | 8080 |
Added if not default (80 for http or 443 for https) |
protocol |
string | HTTP request protocol. | HTTP/1.1 ; HTTP/2 ; HTTP/3 |
Always |
request-duration
Name | Instrument Type | Unit | Description |
---|---|---|---|
request-duration |
Histogram | s |
The duration of outbound HTTP requests. |
Attribute | Type | Description | Examples | Presence |
---|---|---|---|---|
scheme |
string | The URI scheme identifying the used protocol. | http ; https |
Always |
method |
string | HTTP request method. | GET ; POST ; HEAD |
Always |
status-code |
int | HTTP response status code. | 200 |
Always |
protocol |
string | HTTP request protocol. | HTTP/1.1 ; HTTP/2 ; HTTP/3 |
Always |
host |
string | Host identifier of the "URI origin" HTTP request is sent to. | localhost |
Always |
port |
int | Port identifier of the "URI origin" HTTP request is sent to. | 8080 |
Added if not default (80 for http or 443 for https) |
Custom tags | n/a | Custom tags added from TBD. | organization =contoso |
n/a |
failed-requests
Name | Instrument Type | Unit | Description |
---|---|---|---|
failed-requests |
Counter | {request} |
Number of outbound HTTP requests that have failed. |
Attribute | Type | Description | Examples | Presence |
---|---|---|---|---|
method |
string | HTTP request method. | GET ; POST ; HEAD |
Always |
scheme |
string | The URI scheme identifying the used protocol. | http ; https |
Always |
host |
string | Host identifier of the "URI origin" HTTP request is sent to. | localhost |
Always |
port |
int | Port identifier of the "URI origin" HTTP request is sent to. | 8080 |
Added if not default (80 for http or 443 for https) |
protocol |
string | HTTP request protocol. | HTTP/1.1 ; HTTP/2 ; HTTP/3 |
Always |
exception-name |
string | Name of the .NET exception thrown during the request. | System.OperationCanceledException |
If unhandled exception |
current-connections
Name | Instrument Type | Unit | Description |
---|---|---|---|
current-connections |
UpDownCounter | {connection} |
Number of outbound HTTP connections that are currently active on the client. |
Attribute | Type | Description | Examples | Presence |
---|---|---|---|---|
scheme |
string | The URI scheme identifying the used protocol. | http ; https |
Always |
host |
string | Host identifier of the "URI origin" HTTP request is sent to. | localhost |
Always |
port |
int | Port identifier of the "URI origin" HTTP request is sent to. | 8080 |
Added if not default (80 for http or 443 for https) |
protocol |
string | HTTP request protocol. | HTTP/1.1 ; HTTP/2 ; HTTP/3 |
Always |
current-idle-connections
Name | Instrument Type | Unit | Description |
---|---|---|---|
current-idle-connections |
UpDownCounter | {connection} |
Number of outbound HTTP connections that are currently idle on the client. |
Attribute | Type | Description | Examples | Presence |
---|---|---|---|---|
scheme |
string | The URI scheme identifying the used protocol. | http ; https |
Always |
host |
string | Host identifier of the "URI origin" HTTP request is sent to. | localhost |
Always |
port |
int | Port identifier of the "URI origin" HTTP request is sent to. | 8080 |
Added if not default (80 for http or 443 for https) |
protocol |
string | HTTP request protocol. | HTTP/1.1 ; HTTP/2 ; HTTP/3 |
Always |
connection-duration
Name | Instrument Type | Unit | Description |
---|---|---|---|
connection-duration |
Histogram | s |
The duration of outbound HTTP connections. |
Attribute | Type | Description | Examples | Presence |
---|---|---|---|---|
scheme |
string | The URI scheme identifying the used protocol. | http ; https |
Always |
host |
string | Host identifier of the "URI origin" HTTP request is sent to. | localhost |
Always |
port |
int | Port identifier of the "URI origin" HTTP request is sent to. | 8080 |
Added if not default (80 for http or 443 for https) |
protocol |
string | HTTP request protocol. | HTTP/1.1 ; HTTP/2 ; HTTP/3 |
Always |
reason |
string | Reason why the connection ended. | ??? | Always |
API Usage
Metrics are collected using libraries, tooling or MeterListener
https://learn.microsoft.com/en-us/dotnet/core/diagnostics/metrics-collection
Alternative Designs
No response
Risks
No response
Author: | JamesNK |
---|---|
Assignees: | - |
Labels: |
|
Milestone: | - |
For reference, here are the current event counters for System.Net.Http - https://learn.microsoft.com/en-us/dotnet/core/diagnostics/available-counters#systemnethttp-counters There probably should be another couple of metrics counters added to this issue for current queued requests and queue duration. I'm not familiar with the inner workings for client pooling and queuing in System.Net.Client. |
Issue that discusses desired metrics for the HTTP connection pool: Additional metrics for .NET Core and ASP.NET Core #79459 |
At what point will we be comfortable dropping the old ones?
I believe the duration we currently track is about the lifetime of the HttpClient's SendAsync call. That means it includes the receiving of the response content if HttpCompletionOptions.ResponseContentRead is specified (the default for most APIs), but if HttpCompletionOptions.ResponseHeadersRead is used, the duration would end prior to processing the response body. What is the intent here?
If a single metric for current-connections can be used to differentiate based on protocol (such that we don't need separate ones for http1/http2/etc.), why do current-connections and current-idle-connections each need their own rather than it just being a boolean tag on the single current-connections metric? |
Dropping event counters will be tough because there isn't a way to indicate they're obsolete (@noahfalk correct me if I'm wrong). Tooling will happily work up to the point where they're removed and then suddenly break.
IMO it's bad behavior. I'd like the Activity (aka span) and request duration to continue until the end of the response body. One way to ensure .NET HTTP client telemetry lines up with the general community would be to check how OpenTelemetry measures request time.
The "current-xxx" counters are Instead, you need something like:
Now that I've described it like that, the description for |
Correct, there is no programmatic obsoletion mechanic. I think we would treat their removal similar to a behavioral breaking change in an API. My hope is that leaving the existing EventCounters in place for a long time imposes very little burden on us. Any energy for fixes/improvements can be directed at the Meter scenario instead. Most tools either already support Meters or will do so in the near future. |
Now that we're using both, hopefully we're forced to come up with a way to deprecate the event counters. @noahfalk it would be good to write up a similar doc above for the runtime counters (I know they are much harder to implement) 😄 . |
I just realized something @JamesNK, for HttpClient there can be many instances in the application. What's the thought process around how we handle this with meters? I think these need to be "nameable" from the outside so that other consumers can determine the meter name for their APIs. |
There is an internal email thread discussing ideas for customizing the meter on One idea is a simple I don't think the meters for different The source of this idea was a way for ASP.NET Core to identify metrics when there are multiple hosts in one process. But it also works well for identifying metrics results from individual HttpClient instances. Update: An issue was created for it: Support for adding default tags to specific meter and/or instruments #84321 |
Really? I feel like it should default to adding a host dimension to all counters. At least then you could identify the target of the information. That might be enough to cover most basic cases no? (though not bullet proof). |
All the counters above have a host tag. |
Could that mitigate some of the problem? |
Maybe we should move the counters to another library(s) that can be optionally referenced - its the name that is used rather than a binary interface for the class right? The counter library would in-turn will listen to the metrics and fire the corresponding counters for them. |
No - you could have multiple HttpClient instances for the same host - it all depends on how |
AFAICR there is a counter for completed requests in ASP.NET Core, should there be one for HttpClient so you have a count of the number of requests that have been made? If we do that, should there be a RequestsFailed and RequestsCompleted, or a RequestsCompleted that includes the response code, and error message, replacing RequestsFailed? |
We don't currently provide information about connections and connection duration - for h2/h3 scenarios. Would it make sense to have a histogram for connection duration - the unusual thing being that longer is better? |
A connection duration counter is already in the issue: |
At this point I think the useful thing to do is update our messaging to encourage using Meters and work with tool partners to adopt the newer features (both of these things are already happening in a broad sense, not specific to metrics from any one .NET library). This should naturally migrate most common scenarios over time. I am not a fan of doing anything more drastic at this point such as actively advocating removing EventCounters code from .NET libraries that already have it. Doing anything that aggressive feels needlessly disruptive and its not clear it offers much value. If a library owner believes maintaining EventCounters code is too much overhead it is still their perogative to force breaking changes on all their users. For a 3rd party library with low back-compat concern that might be a fine move, but for a library that cares about back-compat IMO that wouldn't be a good tradeoff at this point. |
Background and motivation
System.Net.Http has event counters. In .NET 8 we want to add metrics counters. These will sit side-by-side with event counters for backward compatibility.
Metrics counters add new features (histograms, tags) that allow for richer data to be represented by fewer counters. For example, there are event counters in hosting for
total-requests
andfailed-requests
counters. One metrics counter can represent these with a tag to represent the status.API Proposal
The proposal for this issue covers the meter name, counters name and description and tags. The IDs and names are a public API that can't easily change after shipping.
System.Net.Http
Notes:
current-requests
andrequest-duration
follow OTel's lead: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/http-metrics.md#http-clienthttp-client-current-requests
http-client-current-requests
{request}
method
GET
;POST
;HEAD
scheme
http
;https
host
localhost
port
8080
protocol
HTTP/1.1
;HTTP/2
;HTTP/3
http-client-request-duration
http-client-request-duration
s
scheme
http
;https
method
GET
;POST
;HEAD
status-code
200
protocol
HTTP/1.1
;HTTP/2
;HTTP/3
host
localhost
port
8080
organization
=contoso
http-client-failed-requests
http-client-failed-requests
{request}
method
GET
;POST
;HEAD
scheme
http
;https
host
localhost
port
8080
protocol
HTTP/1.1
;HTTP/2
;HTTP/3
exception-name
System.OperationCanceledException
http-client-current-connections
http-client-current-connections
{connection}
scheme
http
;https
host
localhost
port
8080
protocol
HTTP/1.1
;HTTP/2
;HTTP/3
http-client-current-idle-connections
http-client-current-idle-connections
{connection}
scheme
http
;https
host
localhost
port
8080
protocol
HTTP/1.1
;HTTP/2
;HTTP/3
http-client-connection-duration
http-client-connection-duration
s
scheme
http
;https
host
localhost
port
8080
protocol
HTTP/1.1
;HTTP/2
;HTTP/3
reason
API Usage
Metrics are collected using libraries, tooling or
MeterListener
https://learn.microsoft.com/en-us/dotnet/core/diagnostics/metrics-collection
Alternative Designs
No response
Risks
No response
The text was updated successfully, but these errors were encountered: