Skip to content

OperationCanceledException not captured with HTTP native instrumentation #116205

Closed
@joegoldman2

Description

@joegoldman2

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions