Is there any reason why timeouts or requests cancelled by the caller are not reported as error with native HTTP instrumentation? I tested by cancelling the request, with the built-in timeout mechanism (HttpClient.Timeout) and Polly (Microsoft.Extensions.Http.Resilience).
With OpenTelemetry.Instrumentation.Http, Activity.StatusCode and error.type tag are set:
Activity.TraceId: 1bc0f5ddfe12988504745d22f8a57011
Activity.SpanId: 411e2d135daba899
Activity.TraceFlags: Recorded
Activity.DisplayName: GET
Activity.Kind: Client
Activity.StartTime: 2025-06-02T08:11:41.0366467Z
Activity.Duration: 00:00:00.9991566
Activity.Tags:
http.request.method: GET
server.address: httpstat.us
server.port: 443
url.full: https://httpstat.us/200?sleep=5000
error.type: System.Threading.Tasks.TaskCanceledException
StatusCode: Error
Activity.StatusDescription: Task Canceled
Instrumentation scope (ActivitySource):
Name: System.Net.Http
Resource associated with Activity:
service.name: basket-api
host.name: 2d2c402928e7
deployment.environment: Development
With native instrumentation (manually with ActivityListener or TracerProviderBuilder.AddSource("System.Net.Http")), the span is considered successful as Activity.StatusCode is not set:
Activity.TraceId: 3b94dc1bacb7925e2d06b0255c3a2d64
Activity.SpanId: 7404392518785446
Activity.TraceFlags: Recorded
Activity.DisplayName: GET
Activity.Kind: Client
Activity.StartTime: 2025-06-02T08:15:36.9133316Z
Activity.Duration: 00:00:01.0040950
Activity.Tags:
http.request.method: GET
server.address: httpstat.us
server.port: 443
url.full: https://httpstat.us/200?sleep=5000
Instrumentation scope (ActivitySource):
Name: System.Net.Http
Resource associated with Activity:
service.name: basket-api
host.name: e2e40c7ea562
deployment.environment: Development
Looks like this behavior is coming from:
|
catch (OperationCanceledException) |
|
{ |
|
taskStatus = TaskStatus.Canceled; |
|
|
|
// we'll report task status in HttpRequestOut.Stop |
|
throw; |
|
} |
where OperationCanceledException are treated differently and not captured. The finally block doesn't set the error in this case.
Is there any reason why timeouts or requests cancelled by the caller are not reported as error with native HTTP instrumentation? I tested by cancelling the request, with the built-in timeout mechanism (
HttpClient.Timeout) and Polly (Microsoft.Extensions.Http.Resilience).With
OpenTelemetry.Instrumentation.Http,Activity.StatusCodeanderror.typetag are set:With native instrumentation (manually with
ActivityListenerorTracerProviderBuilder.AddSource("System.Net.Http")), the span is considered successful asActivity.StatusCodeis not set:Looks like this behavior is coming from:
runtime/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandler.cs
Lines 168 to 174 in 50bf168
where
OperationCanceledExceptionare treated differently and not captured. Thefinallyblock doesn't set the error in this case.