Skip to content

fix(core): Do not activate ignored spans in the tracing-channel binding - #22981

Merged
andreiborza merged 6 commits into
developfrom
ab/fix-ignored-span-active-binding
Aug 4, 2026
Merged

fix(core): Do not activate ignored spans in the tracing-channel binding#22981
andreiborza merged 6 commits into
developfrom
ab/fix-ignored-span-active-binding

Conversation

@andreiborza

@andreiborza andreiborza commented Aug 4, 2026

Copy link
Copy Markdown
Member

What

In the AsyncLocalStorage tracing-channel binding, do not set an ignored (ignoreSpans) child span as the active span.

  • Adds a spanIsIgnored guard in _INTERNAL_createTracingChannelBinding.
  • Unit test covers a normal span (active), an ignored child (parent stays active), and an ignored root (stays active).

Why

An ignored span emits nothing, so activating it broke propagation two ways. An ignored child left active makes its descendants parent to a span that never reaches Sentry, producing orphaned spans; keeping the parent active re-parents them onto the nearest emitted span. An ignored root must stay active so its whole subtree is dropped, otherwise its children escape as standalone spans. This applies the same spanIsIgnored(span) && getRootSpan(span) !== span check the OpenTelemetry context manager uses, so ignoreSpans behaves the same with or without a tracer provider.

const isIgnoredChild =
(spanIsIgnored(span) && getRootSpan(span) !== span) ||
span.spanContext().traceState?.get(SENTRY_TRACE_STATE_CHILD_IGNORED) === '1';
return isIgnoredChild ? activeContext : api.trace.setSpan(activeContext, span);

The AsyncLocalStorage tracing-channel binding planted every channel span as the
active span, including ignored (`ignoreSpans`) placeholders. Because no span is
emitted for an ignored span, its children and outgoing requests then propagated
from it instead of the nearest emitted parent, dropping the continued sampling
decision. Skip ignored spans so propagation falls back to that parent, matching
the OpenTelemetry context manager.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread packages/core/src/asyncContext/tracing-channel-binding.ts
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 29.81 kB - -
@sentry/browser - with treeshaking flags 28.03 kB - -
@sentry/browser (incl. Tracing) 47.28 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 47.29 kB - -
@sentry/browser (incl. Tracing, Profiling) 52.05 kB - -
@sentry/browser (incl. Tracing, Replay) 86.6 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 76.04 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 91.33 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 103.97 kB - -
@sentry/browser (incl. Feedback) 47.13 kB - -
@sentry/browser (incl. sendFeedback) 34.66 kB - -
@sentry/browser (incl. FeedbackAsync) 39.77 kB - -
@sentry/browser (incl. Metrics) 30.88 kB - -
@sentry/browser (incl. Logs) 31.12 kB - -
@sentry/browser (incl. Metrics & Logs) 31.79 kB - -
@sentry/react 31.61 kB - -
@sentry/react (incl. Tracing) 49.54 kB - -
@sentry/vue 34.88 kB - -
@sentry/vue (incl. Tracing) 49.27 kB - -
@sentry/svelte 29.83 kB - -
CDN Bundle 31.9 kB - -
CDN Bundle (incl. Tracing) 47.6 kB - -
CDN Bundle (incl. Logs, Metrics) 33.45 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 49.02 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 72.81 kB - -
CDN Bundle (incl. Tracing, Replay) 85.26 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 86.57 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 91.08 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 92.4 kB - -
CDN Bundle - uncompressed 94.8 kB - -
CDN Bundle (incl. Tracing) - uncompressed 142.47 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 99.51 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 146.44 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 224.26 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 261.72 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 265.69 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 275.43 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 279.38 kB - -
@sentry/nextjs (client) 52.1 kB - -
@sentry/sveltekit (client) 47.72 kB - -
@sentry/core/server 73.73 kB +0.02% +9 B 🔺
@sentry/core/browser 51.87 kB +0.02% +10 B 🔺
@sentry/node 121.15 kB - -
@sentry/node/import (ESM hook with diagnostics-channel injection) 0 B added added
@sentry/node - without tracing 84.03 kB - -
@sentry/aws-serverless 92.69 kB -0.01% -1 B 🔽
@sentry/cloudflare (withSentry) - minified 224.22 kB +0.01% +20 B 🔺
@sentry/cloudflare (withSentry) 551.42 kB +0.02% +74 B 🔺

View base workflow run

andreiborza and others added 2 commits August 4, 2026 11:44
An ignored root span must stay the active span so its whole subtree is dropped with
it; only ignored children should be skipped (so their siblings/parent stay the
propagation source). Match core startSpan and the OTel context manager with
`getRootSpan(span) === span`, and cover both the ignored-child and ignored-root cases.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7475bcb. Configure here.

Comment thread packages/core/test/lib/asyncContext/tracing-channel-binding.test.ts
The ignored-child test started from an empty scope and only checked the active span
was unset, which does not distinguish "parent dropped" from "parent preserved". Seed
the parent as the active span and assert it remains active, covering the actual
regression: nested spans and outgoing requests must keep propagating from the parent.
…r path

Explain why an ignored child keeps its parent active (avoids orphaned/misparented
downstream spans) while an ignored root stays active (drops its subtree), and note
this mirrors the OpenTelemetry `getStoreWithActiveSpan` check so ignoreSpans behaves
the same with or without a Sentry tracer provider.
Keep the code comment to the essential rule and move the longer justification and
tracer-provider comparison to the PR description.
@andreiborza
andreiborza marked this pull request as ready for review August 4, 2026 12:49
@andreiborza
andreiborza merged commit 04a89bd into develop Aug 4, 2026
518 of 519 checks passed
@andreiborza
andreiborza deleted the ab/fix-ignored-span-active-binding branch August 4, 2026 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants