Skip to content

fix(otel): treat sentry-trace without a sampling flag as sampled in SentryPropagator - #5907

Merged
jamescrosswell merged 2 commits into
version7from
fix/propagator-deferred-sampling
Nov 11, 2026
Merged

jamescrosswell merged 2 commits into
version7from
fix/propagator-deferred-sampling

Conversation

@jamescrosswell

@jamescrosswell jamescrosswell commented Nov 10, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

SentryPropagator.Extract mapped a sentry-trace header with no sampling flag (<trace>-<span>, the deferred form) to ActivityTraceFlags.None. OpenTelemetry's default ParentBasedSampler sends a remote parent without Recorded to AlwaysOff, so a service using the propagator dropped all spans for requests from upstream SDKs that hadn't made a sampling decision, and propagated -0 further downstream.

Now only an explicit -0 maps to unsampled; a missing flag becomes Recorded. This is option 1 from the issue and matches sentry-java's OpenTelemetryOtlpPropagator.

Notes for review

  • Trade-off called out in the issue: with the default ParentBasedSampler, deferred requests are now always recorded, so a ratio-based root sampler is not consulted for them. Option 2 (marking the deferred case and shipping a sampler that delegates to the root sampler) would respect it but adds public API; it can follow separately if we want it.
  • SentryPropagator.cs is also compiled into the obsolete Sentry.OpenTelemetry package, where AddSentry() registers it. There, SentrySpanProcessor passes a remote parent's Recorded flag to Hub.StartTransaction as the sampling decision, which takes precedence over TracesSampleRate (a TracesSampler still runs first). Deferred requests used to be dropped even at TracesSampleRate = 1.0; they now become transactions even at 0. sentry-java's span-processor mode runs its own sampler for a deferred parent instead.

Fixes #5903

🤖 Generated with Claude Code

SentryPropagator.Extract mapped a sentry-trace header without a sampling
flag to ActivityTraceFlags.None, so OpenTelemetry's ParentBasedSampler
dropped every span for requests from upstream services that had not made
a sampling decision. Only an explicit -0 is now unsampled, matching
sentry-java's OpenTelemetryOtlpPropagator.

Fixes #5903

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 76.98%. Comparing base (25b505e) to head (eb004d7).
⚠️ Report is 2 commits behind head on version7.

Additional details and impacted files
@@            Coverage Diff            @@
##           version7    #5907   +/-   ##
=========================================
  Coverage     76.98%   76.98%           
=========================================
  Files           538      538           
  Lines         19714    19714           
  Branches       3872     3872           
=========================================
+ Hits          15176    15177    +1     
- Misses         3666     3667    +1     
+ Partials        872      870    -2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jamescrosswell
jamescrosswell marked this pull request as ready for review November 10, 2026 23:41
@github-actions github-actions Bot added the risk: low PR risk score: low label Nov 10, 2026
@jamescrosswell jamescrosswell mentioned this pull request Nov 10, 2026
5 of 22 tasks
…From_Carrier

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ric-oliv

Copy link
Copy Markdown
Member

There's one case this PR doesn't cover, and I think it's fine to follow up on it separately. A service with SentryPropagator still drops its spans when a sentry-trace without a flag comes with a traceparent of 00-<trace>-<span>-00. That's what the .NET SDK sends when there's no active span and PropagateTraceparent is on, see W3CTraceparentHeader. The JS SDK sends -00 in the same situation, see generateTraceparentHeader.

ASP.NET Core starts the request activity from traceparent, and the default ParentBasedSampler drops it. OpenTelemetry's ASP.NET Core instrumentation only replaces that activity when the trace ID, span ID or tracestate differ, see HttpInListener. It doesn't compare the flags, so when the IDs match and there's no tracestate, it never uses what SentryPropagator returns.

@jamescrosswell
jamescrosswell merged commit 4c2f99f into version7 Nov 11, 2026
36 checks passed
@jamescrosswell
jamescrosswell deleted the fix/propagator-deferred-sampling branch November 11, 2026 02:13
@jamescrosswell

Copy link
Copy Markdown
Collaborator Author

Thanks, confirmed. Tracking it separately in #5910, with a few options for fixing it.

🤖 Addressed by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: low PR risk score: low

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SentryPropagator treats sentry-trace without a sampling flag as unsampled

2 participants