Skip to content

feat(core): Apply ignoreSpans to streamed spans#19934

Open
Lms24 wants to merge 5 commits intolms/feat-span-firstfrom
lms/feat-core-ignorespans-streaming
Open

feat(core): Apply ignoreSpans to streamed spans#19934
Lms24 wants to merge 5 commits intolms/feat-span-firstfrom
lms/feat-core-ignorespans-streaming

Conversation

@Lms24
Copy link
Copy Markdown
Member

@Lms24 Lms24 commented Mar 23, 2026

This PR Implements applying the ignoreSpans option to streamed spans (previously this option had no effect). It covers both, our core/browser- as well as the OTel/Node-based implementation.

Behaviour on all implementations:

  • ignoring a segment span ignores the entire span tree
    • we record an ignored client outcome for each dropped span (segment + children)
  • ignoring a child span only ignores the child. Potential grandchildren are naturally parented to the dropped span's parent. No post-creation reparenting logic is used anymore.
    • we record an ignored client outcome for the dropped child
  • in both cases, for ignored spans, NonRecording spans are started instead of the filtered span so that a span in a callback can always be accessed as we do with sampling.
  • this PR also adds sample_rate client report outcomes for negatively sampled child spans. Meaning, when our sampling logic makes a negative decision, we record outcomes for the segment span + every created child span of the negatively sampled segment. This is additional logic to ignoreSpans but we need to differentiate between outcome reason (ignored vs. sample_rate), so I had to add this to this PR. This is expected behaviour and something we would have needed to do for span streaming anyway.

Implementation Node/OTel:

  • We use the SentrySampler to effectively make sampling decisions for ignoreSpans prior to applying our actual sampling options. So to be clear: There's no actual sampling logic applied but using the sampler allows us to modify the OTel context, which we can then later use to correctly either drop all spans of a segment or just one span (see above). We do this by adding flags to the traceState, which the context manager picks up and changes its context accordingly.

Implementation Core/Browser:

  • We apply ignoreSpans right on the start*span* APIs, prior to sampling.
  • We store a dropReason on the SentrySpan class that allows us to report the correct client outcome for dropped child spans, both for sampling as well as ignoreSpans

@Lms24 Lms24 changed the base branch from develop to lms/feat-span-first March 23, 2026 13:41
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 23, 2026

Semver Impact of This PR

🟡 Minor (new features)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

Core

  • Apply ignoreSpans to streamed spans by Lms24 in #19934
  • Support embedding APIs in google-genai by nicohrubec in #19797

Deps

  • Bump babel-loader from 10.0.0 to 10.1.1 by dependabot in #19997
  • Bump handlebars from 4.7.7 to 4.7.9 by dependabot in #20008

Nuxt

  • Add middleware instrumentation compatibility for Nuxt 5 by s1gr1d in #19968
  • Support parametrized SSR routes in Nuxt 5 by s1gr1d in #19977

Other

  • (browser) Replace element timing spans with metrics by logaretm in #19869
  • (bun) Add bunRuntimeMetricsIntegration by chargome in #19979
  • (node) Add nodeRuntimeMetricsIntegration by chargome in #19923
  • (node-core) Add OTLP integration for node-core/light by andreiborza in #19729
  • (solid) Add route parametrization for Solid Router by andreiborza in #20031
  • Span Streaming (WIP) by Lms24 in #19119

Bug Fixes 🐛

Ci

  • Update validate-pr action to remove draft enforcement by stephanie-anderson in #20037
  • Update validate-pr action to remove draft enforcement by stephanie-anderson in #20035

Other

  • (core) Guard nullish response in supabase PostgREST handler by antonis in #20033
  • (e2e) Pin @opentelemetry/api to 1.9.0 in ts3.8 test app by logaretm in #19992
  • (node) Ensure startNewTrace propagates traceId in OTel environments by logaretm in #19963
  • (nuxt) Use virtual module for Nuxt pages data (SSR route parametrization) by s1gr1d in #20020
  • (opentelemetry) Convert seconds timestamps in span.end() to milliseconds by logaretm in #19958

Documentation 📚

  • (release) Update publishing-a-release.md by nicohrubec in #19982

Internal Changes 🔧

Core

  • Introduce instrumented method registry for AI integrations by nicohrubec in #19981
  • Consolidate getOperationName into one shared utility by nicohrubec in #19971

Deps

  • Bump amqplib from 0.10.7 to 0.10.9 by dependabot in #20000
  • Bump actions/upload-artifact from 6 to 7 by dependabot in #19569
  • Bump srvx from 0.11.12 to 0.11.13 by dependabot in #20001
  • Bump @apollo/server from 5.4.0 to 5.5.0 by dependabot in #20007

Deps Dev

  • Remove esbuild override in astro-5-cf-workers E2E test by isaacs in #20024
  • Bump node-forge from 1.3.2 to 1.4.0 by dependabot in #20012
  • Bump yaml from 2.8.2 to 2.8.3 by dependabot in #19985

Other

  • (browser) Reduce browser package bundle size by HazAT in #19856
  • (deno) Expand Deno E2E test coverage by chargome in #19957
  • (e2e) Add e2e tests for nodeRuntimeMetricsIntegration by chargome in #19989

🤖 This preview updates automatically when you update the PR.

@Lms24 Lms24 force-pushed the lms/feat-span-first branch from 5963170 to de2e194 Compare March 30, 2026 11:47
@Lms24 Lms24 force-pushed the lms/feat-core-ignorespans-streaming branch from e90d6d3 to 11cfe2b Compare March 30, 2026 11:48
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 30, 2026

size-limit report 📦

Path Size % Change Change
@sentry/browser 25.72 kB added added
@sentry/browser - with treeshaking flags 24.21 kB added added
@sentry/browser (incl. Tracing) 42.67 kB added added
@sentry/browser (incl. Tracing, Profiling) 47.29 kB added added
@sentry/browser (incl. Tracing, Replay) 81.48 kB added added
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 71.06 kB added added
@sentry/browser (incl. Tracing, Replay with Canvas) 86.19 kB added added
@sentry/browser (incl. Tracing, Replay, Feedback) 98.4 kB added added
@sentry/browser (incl. Feedback) 42.5 kB added added
@sentry/browser (incl. sendFeedback) 30.38 kB added added
@sentry/browser (incl. FeedbackAsync) 35.36 kB added added
@sentry/browser (incl. Metrics) 27.03 kB added added
@sentry/browser (incl. Logs) 27.17 kB added added
@sentry/browser (incl. Metrics & Logs) 27.85 kB added added
@sentry/react 27.48 kB added added
@sentry/react (incl. Tracing) 44.99 kB added added
@sentry/vue 30.52 kB added added
@sentry/vue (incl. Tracing) 44.52 kB added added
@sentry/svelte 25.74 kB added added
CDN Bundle 28.38 kB added added
CDN Bundle (incl. Tracing) 43.66 kB added added
CDN Bundle (incl. Logs, Metrics) 29.75 kB added added
CDN Bundle (incl. Tracing, Logs, Metrics) 44.74 kB added added
CDN Bundle (incl. Replay, Logs, Metrics) 68.56 kB added added
CDN Bundle (incl. Tracing, Replay) 80.55 kB added added
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 81.57 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback) 86.08 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 87.11 kB added added
CDN Bundle - uncompressed 82.86 kB added added
CDN Bundle (incl. Tracing) - uncompressed 129.51 kB added added
CDN Bundle (incl. Logs, Metrics) - uncompressed 87 kB added added
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 132.92 kB added added
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 209.99 kB added added
CDN Bundle (incl. Tracing, Replay) - uncompressed 246.38 kB added added
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 249.78 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 259.3 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 262.68 kB added added
@sentry/nextjs (client) 47.42 kB added added
@sentry/sveltekit (client) 43.13 kB added added
@sentry/node-core 58.79 kB added added
@sentry/node 176.1 kB added added
@sentry/node - without tracing 98.58 kB added added
@sentry/aws-serverless 116.02 kB added added

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 30, 2026

node-overhead report 🧳

Note: This is a synthetic benchmark with a minimal express app and does not necessarily reflect the real-world performance impact in an application.

Scenario Requests/s % of Baseline Prev. Requests/s Change %
GET Baseline 9,833 - - added
GET With Sentry 1,763 18% - added
GET With Sentry (error only) 6,127 62% - added
POST Baseline 1,227 - - added
POST With Sentry 603 49% - added
POST With Sentry (error only) 1,064 87% - added
MYSQL Baseline 3,307 - - added
MYSQL With Sentry 522 16% - added
MYSQL With Sentry (error only) 2,734 83% - added

@Lms24 Lms24 marked this pull request as ready for review March 31, 2026 11:31
{
category: 'transaction',
quantity: 4,
category: 'span',
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

a couple of pre-existing tests (like this one) needed adjustments because they previously reported the wrong telemetry type (for span streaming). Also the number of dropped spans increased because we now also count child spans.

dsn: 'https://public@dsn.ingest.sentry.io/1337',
integrations: [Sentry.spanStreamingIntegration()],
ignoreSpans: [/ignore/],
parentSpanIsAlwaysRootSpan: false,
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

worth noting: For this test, I enabled parentSpanIsAlwaysRootSpan which due to the lack of async context is our default behaviour in browser. I enabled it here to ensure that the parenting order in the test (see file below) works as expected in core/browser.

Copy link
Copy Markdown

@cursor cursor bot left a comment

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 prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Core path reads op from wrong property for ignore check
    • Fixed _shouldIgnoreStreamedSpan to check spanArguments.op before spanArguments.attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP], aligning with the OTel implementation and ensuring op-based ignoreSpans patterns work correctly in the core/browser streaming path.

Create PR

Or push these changes by commenting:

@cursor push 6b34ec41de
Preview (6b34ec41de)
diff --git a/packages/core/src/tracing/trace.ts b/packages/core/src/tracing/trace.ts
--- a/packages/core/src/tracing/trace.ts
+++ b/packages/core/src/tracing/trace.ts
@@ -594,7 +594,10 @@
   }
 
   return shouldIgnoreSpan(
-    { description: spanArguments.name || '', op: spanArguments.attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] },
+    {
+      description: spanArguments.name || '',
+      op: spanArguments.op || spanArguments.attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP],
+    },
     ignoreSpans,
   );
 }

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.


return shouldIgnoreSpan(
{ description: spanArguments.name || '', op: spanArguments.attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] },
ignoreSpans,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Core path reads op from wrong property for ignore check

Medium Severity

In _shouldIgnoreStreamedSpan, the op is read from spanArguments.attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP], but at this point in the flow the op lives on spanArguments.op (set by parseSentrySpanArguments which spreads StartSpanOptions). The SEMANTIC_ATTRIBUTE_SENTRY_OP attribute is only populated later when the SentrySpan constructor runs. This means any ignoreSpans pattern that filters by op (e.g. { op: 'http.server' }) will silently fail to match in the core/browser streaming path. The OTel path correctly handles this by checking both: options.op || options.attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP].

Fix in Cursor Fix in Web

Copy link
Copy Markdown
Member

@isaacs isaacs left a comment

Choose a reason for hiding this comment

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

AIUI, it looks like this dodges the issue of "don't have all the data to decide to ignore spans until they're already started, which is too late to ignore them" by making the decision limited to description and op? If so, lgtm, pending investigating/resolving the nit from cursor about reading from the attributes vs the settings object directly.

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