You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Optional follow-up to #130102 (configurable HTTP connection eviction), and depends on it. This proposal reuses the same ConnectionId concept and [Experimental] diagnostic.
That proposal exposes a long ConnectionId on the connect and eviction callback contexts, so callers can associate custom state with a connection at creation time and recover it when deciding on eviction. To drive those eviction decisions from per-response or per-error signals, however, the caller needs to correlate a response or exception with the connection that produced it. Today that requires consuming EventSource telemetry with a lot of ceremony.
One motivating scenario is called out in #130102 ("evict connections with many consecutive 502s"), where a custom handler counts bad responses per connection and the eviction callback acts on the count. That handler needs request.ConnectionId.
The id is the same value already surfaced via telemetry and via the #130102 contexts.
API Proposal
namespaceSystem.Net.Http;publicpartialclassHttpRequestMessage{[Experimental]// Same diagnostic as #130102publiclong?ConnectionId{get;set;}}
ConnectionId is an opaque identifier. The only guarantee is that it is unique within the current process; ids are not shared across handler instances (two handlers never hand out the same id). No ordering/format/stability across processes is guaranteed. This is the same id already exposed via telemetry and the #130102 contexts.
The ID is nullable because responses can be produced without a SocketsHttpHandler connection (custom HttpMessageHandlers, cached/synthesized responses, the browser handler, failures before a connection is established, ...).
The implementation may also choose not to convey the connection ID in all cases. E.g. if a request failed due to a timeout while waiting for a connection to be established, the ID won't be set. But if it timed out while waiting for a response on an existing connection it sent the request headers on, the ID would be set.
If a request was attempted on some connection, and then retried internally by SocketsHttpHandler before a response/exception is generated, the ID of that initial connection won't be reported.
The property on the request message would be cleared by SocketsHttpHandler right away if already set in order to lower the risk of failures being misattributed if the same request instance was reused (e.g. for retries).
Setting the value beforehand would have no impact on connection selection for that request (you can't use it to specify a preference).
Improve logs when request timeouts can be correlated to a bad connection:
varrequest=newHttpRequestMessage(HttpMethod.Get,uri);try{usingHttpResponseMessageresponse=awaitclient.SendAsync(request);}catch(TimeoutExceptionex){if(request.ConnectionIdislongconnectionId&&connectionIPs.TryGetValue(connectionId,outIPAddressip)){_logger.LogWarning(ex,"Request to {Uri} timed out on connection to {IP}",request.RequestUri.AbsoluteUri,ip);}}
Alternative Designs
We could expose the ID on HttpResponseMessage, HttpRequestException, and HttpIOException instead of the request. The main reason why I chose not to is that HttpClient may throw timeout/cancellation exceptions where we don't have a good place to expose the new info. Consumers would possibly have to look at many different places and also dig through inner exceptions. With the request there's just a single location to check.
We could use 0 as a sentinel value and avoid the need to have the property be nullable.
Background and motivation
Optional follow-up to #130102 (configurable HTTP connection eviction), and depends on it. This proposal reuses the same
ConnectionIdconcept and[Experimental]diagnostic.That proposal exposes a
long ConnectionIdon the connect and eviction callback contexts, so callers can associate custom state with a connection at creation time and recover it when deciding on eviction. To drive those eviction decisions from per-response or per-error signals, however, the caller needs to correlate a response or exception with the connection that produced it. Today that requires consuming EventSource telemetry with a lot of ceremony.One motivating scenario is called out in #130102 ("evict connections with many consecutive 502s"), where a custom handler counts bad responses per connection and the eviction callback acts on the count. That handler needs
request.ConnectionId.The id is the same value already surfaced via telemetry and via the #130102 contexts.
API Proposal
ConnectionIdis an opaque identifier. The only guarantee is that it is unique within the current process; ids are not shared across handler instances (two handlers never hand out the same id). No ordering/format/stability across processes is guaranteed. This is the same id already exposed via telemetry and the #130102 contexts.The ID is nullable because responses can be produced without a
SocketsHttpHandlerconnection (customHttpMessageHandlers, cached/synthesized responses, the browser handler, failures before a connection is established, ...).The implementation may also choose not to convey the connection ID in all cases. E.g. if a request failed due to a timeout while waiting for a connection to be established, the ID won't be set. But if it timed out while waiting for a response on an existing connection it sent the request headers on, the ID would be set.
If a request was attempted on some connection, and then retried internally by
SocketsHttpHandlerbefore a response/exception is generated, the ID of that initial connection won't be reported.The property on the request message would be cleared by
SocketsHttpHandlerright away if already set in order to lower the risk of failures being misattributed if the same request instance was reused (e.g. for retries).Setting the value beforehand would have no impact on connection selection for that request (you can't use it to specify a preference).
API Usage
Alternative Designs
HttpResponseMessage,HttpRequestException, andHttpIOExceptioninstead of the request. The main reason why I chose not to is thatHttpClientmay throw timeout/cancellation exceptions where we don't have a good place to expose the new info. Consumers would possibly have to look at many different places and also dig through inner exceptions. With the request there's just a single location to check.0as a sentinel value and avoid the need to have the property be nullable.Related to #63159