Skip to content

feat(node)!: Default most SDKs to a no-tracer-provider setup - #22957

Draft
andreiborza wants to merge 17 commits into
developfrom
ab/default-no-tracer-provider
Draft

feat(node)!: Default most SDKs to a no-tracer-provider setup#22957
andreiborza wants to merge 17 commits into
developfrom
ab/default-no-tracer-provider

Conversation

@andreiborza

@andreiborza andreiborza commented Aug 3, 2026

Copy link
Copy Markdown
Member

What

Flip the default OpenTelemetry setup for server SDKs: @sentry/node (and inheritors) and @sentry/cloudflare now default to skipOpenTelemetrySetup: true (no tracer provider; scopes isolated via AsyncLocalStorage, spans still emitted via core startSpan), while @sentry/nextjs and @sentry/sveltekit default to false since they rely on OpenTelemetry span pickup.

Why

Most SDKs do not need a tracer provider to produce spans, so defaulting to none lets users run their own OpenTelemetry cleanly alongside Sentry without Sentry spans leaking into their pipeline.

Closes: #22486

Flip the default OpenTelemetry setup for server SDKs: most now run without a
Sentry tracer provider, using an AsyncLocalStorage context strategy for scope
isolation. Reuses the existing `skipOpenTelemetrySetup` option with a flipped
default (true for node/cloudflare, false for nextjs/sveltekit).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@andreiborza

andreiborza commented Aug 3, 2026

Copy link
Copy Markdown
Member Author

batman begin

…er-provider

# Conflicts:
#	packages/cloudflare/src/sdk.ts
Comment thread packages/node/src/sdk/index.ts
Comment thread packages/node/test/integration/transactions.test.ts
Comment thread packages/node/src/sdk/index.ts
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

⚠️ Warning: Base artifact is not the latest one, because the latest workflow run is not done yet. This may lead to incorrect results. Try to re-run all tests to get up to date results.

Path Size % Change Change
@sentry/browser 29.8 kB - -
@sentry/browser - with treeshaking flags 28.02 kB - -
@sentry/browser (incl. Tracing) 47.21 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 47.22 kB - -
@sentry/browser (incl. Tracing, Profiling) 51.95 kB - -
@sentry/browser (incl. Tracing, Replay) 86.54 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 75.98 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 91.26 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 103.89 kB - -
@sentry/browser (incl. Feedback) 47.1 kB - -
@sentry/browser (incl. sendFeedback) 34.64 kB - -
@sentry/browser (incl. FeedbackAsync) 39.75 kB - -
@sentry/browser (incl. Metrics) 30.87 kB - -
@sentry/browser (incl. Logs) 31.11 kB - -
@sentry/browser (incl. Metrics & Logs) 31.78 kB - -
@sentry/react 31.59 kB - -
@sentry/react (incl. Tracing) 49.46 kB - -
@sentry/vue 34.87 kB - -
@sentry/vue (incl. Tracing) 49.19 kB - -
@sentry/svelte 29.82 kB - -
CDN Bundle 31.87 kB - -
CDN Bundle (incl. Tracing) 47.54 kB - -
CDN Bundle (incl. Logs, Metrics) 33.41 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 48.94 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 72.75 kB - -
CDN Bundle (incl. Tracing, Replay) 85.18 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 86.5 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 91.01 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 92.31 kB - -
CDN Bundle - uncompressed 94.7 kB - -
CDN Bundle (incl. Tracing) - uncompressed 142.18 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 99.32 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 146.16 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 224.02 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 261.43 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 265.4 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 275.14 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 279.09 kB - -
@sentry/nextjs (client) 52.03 kB - -
@sentry/sveltekit (client) 47.65 kB - -
@sentry/core/server 65.5 kB - -
@sentry/core/browser 51.84 kB - -
@sentry/node 120.44 kB +0.22% +257 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 0 B added added
@sentry/node - without tracing 83.91 kB +0.33% +270 B 🔺
@sentry/aws-serverless 92.57 kB +0.3% +269 B 🔺
@sentry/cloudflare (withSentry) - minified 218.7 kB +0.03% +61 B 🔺
@sentry/cloudflare (withSentry) 538.95 kB +0.06% +300 B 🔺

View base workflow run

In the no-provider default, setupEventContextTrace read the OpenTelemetry active
span before scope data was applied, so a user's own OTel span could override the
Sentry trace on error events. Only set up this hook when Sentry owns the provider.
Assert the actual user-visible effect: a foreign OpenTelemetry active span must
not override the Sentry trace on error events in the no-provider default, and is
adopted when the tracer provider is enabled. Verified to fail without the gating.
Channel-based instrumentation stamps OTel semantic attributes on native spans but
leaves the Sentry-convention fields (e.g. sentry.op) to be inferred by the provider
pipeline. Without a tracer provider that inference never ran, so outgoing http/fetch
and other channel spans were half-formed. Run the same applyOtelSpanData /
backfillStreamedSpanDataFromOtel hooks via the client in no-provider mode.
tracer-start-active-span-error drives the raw OpenTelemetry tracer, and
http-otel-double-instrumentation exercises coexistence with a user-owned OTel
HttpInstrumentation whose spans reach Sentry via the tracer provider. Both require
the provider, so they opt into it explicitly under the new no-provider default.
A trace continued without incoming baggage freezes an empty DSC. Reading it back
short-circuited before sample_rand was added, so downstream requests in no-provider
mode propagated baggage without sentry-sample_rand. Backfill it from the captured
scope's propagation context, matching what the OTel span sampler writes to trace state.
In no-provider mode the AsyncLocalStorage tracing-channel binding planted every
channel span as the active span, including ignored ones. Children and outgoing
requests then propagated from the ignored span, dropping the continued positive
sampling decision. Skip ignored spans so propagation falls back to the nearest
emitted parent, matching the OTel context manager.
Comment thread packages/core/src/asyncContext/tracing-channel-binding.ts
The previous approach backfilled sample_rand in getDynamicSamplingContextFromSpan,
which also ran in OTel mode and wrongly added sample_rand to remote-parent DSCs
(breaking opentelemetry unit tests). Move the backfill to the root-span freeze site
and gate it on a genuinely empty DSC, so only continued traces without incoming
baggage get sample_rand and populated frozen DSCs are left untouched.

Also opt the Cloudflare Vercel AI v6 integration test into the tracer provider: the
AI SDK emits spans via @opentelemetry/api, which need the provider to be captured.
The `otel` transaction context carries the OpenTelemetry SDK resource attributes,
which are only set when Sentry owns the tracer provider. Under the no-provider
default these Astro server SDKs no longer emit it, so the assertion is removed.
The event-loop-block watchdog reads the active scope out of the client's
`asyncLocalStorageLookup`, which was only populated when the OpenTelemetry context
strategy was set up. Without a tracer provider it was undefined, so ANR events fell
back to the global scope and dropped per-isolation-scope user data and breadcrumbs.

Return the AsyncLocalStorage from `setAsyncLocalStorageAsyncContextStrategy` and set
`asyncLocalStorageLookup` in the no-provider branch. The lookup now carries a generic
`stateLookup` key path (empty for the ALS store, which already is the scopes object;
`['_currentContext', ...]` for the OTel context) instead of an OTel-specific symbol.
Continuing a trace without an incoming Sentry DSC now folds the scope's sample_rand
into the propagated (otherwise empty) DSC so downstream sampling stays consistent.
Update the sveltekit handle and browser tracing tests that asserted a strictly empty
DSC in that case.
The server middleware index counter was stored on the OpenTelemetry context, so it
reset to 0 on every middleware under the no-provider default (no context propagation
without a tracer provider), producing indices like [0,0,0]. Key it by the incoming
Request in a WeakMap instead, mirroring the client instrumentation, so it works in
both modes.
Keying the per-request middleware counter by the incoming Request did not increment
in the real server (each middleware hook sees a distinct request object), so indices
stayed [0,0,0]. Key by the request's root span instead, which is the single stable
transaction all of a request's middlewares run under, in both provider modes.
…er-provider

# Conflicts:
#	packages/browser/test/tracing/browserTracingIntegration.test.ts
#	packages/core/src/asyncContext/tracing-channel-binding.ts
#	packages/sveltekit/test/server-common/handle.test.ts
Channel-based spans need the Sentry-convention backfill in every mode, so run it
unconditionally in _init instead of only in the no-provider branch. This also covers
the case where the provider fails to register (setupOtel early-returns), which
previously skipped backfill. setupOtel no longer needs the client argument.

@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 8f5fb88. Configure here.

Comment thread packages/sveltekit/src/server/sdk.ts
initCloudflareSentryHandle inherited Cloudflare's new no-provider default, so
Kit-emitted OpenTelemetry spans (and svelteKitSpansIntegration) were no longer
captured on Cloudflare. Default skipOpenTelemetrySetup to false here, matching the
Node SvelteKit SDK.
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.

Default most SDKs to a no-tracer-provider setup; opt-in flag to enable it

1 participant