Skip to content

ref(cloudflare)!: Use shared SentryTracerProvider for OpenTelemetry interop - #23300

Merged
JPeer264 merged 3 commits into
developfrom
jp/cloudflare-tracerprovider
Aug 25, 2026
Merged

ref(cloudflare)!: Use shared SentryTracerProvider for OpenTelemetry interop#23300
JPeer264 merged 3 commits into
developfrom
jp/cloudflare-tracerprovider

Conversation

@JPeer264

@JPeer264 JPeer264 commented Aug 11, 2026

Copy link
Copy Markdown
Member

This uses now the SentryTracerProvider and removes the previous kinda mocked provider. I added two integration tests that check if OTel traces are picked up by our provider—just to tripple check if the machinery is implemented correctly.

I made it breaking since the sentry.cloudflare_tracer attribute is being removed now (I added this as a fixup in the migration guide)

Also for Hydrogen aka the /request entrypoint, we no longer support the enableOpenTelemetrySetup option, as this would require node:async_hooks, which isn't available in Hydrogen. In case this would be needed in the future we can enable this and readd the previous OTel Tracer Provider. But for now it is better to keep it simple.

Keep an eye on this 👀

I had to adjust startActiveSpan in order to not mess with the root span: https://github.com/getsentry/sentry-javascript/actions/runs/31579946168/job/94061924393


Clanker machinery comment:

Replaces the bespoke Cloudflare tracer with SentryTracerProvider from @sentry/opentelemetry, and covers enableOpenTelemetrySetup end to end in workerd with two integration suites.

The enabled suite documents that startActiveSpan detaches into a root transaction of its own rather than nesting under the request span: it always resolves an explicit context, and Cloudflare installs no OTel context manager, so context.active() never carries the request span. startSpan passes no context and does nest, so both paths are asserted to pin the difference.

The two workers are kept identical apart from the option itself, so the disabled suite also proves the wider OTel surface stays inert when the provider is off.

@JPeer264 JPeer264 self-assigned this Aug 11, 2026
@JPeer264
JPeer264 requested a review from a team as a code owner August 11, 2026 14:34
@JPeer264
JPeer264 requested review from andreiborza, isaacs, mydea and s1gr1d and removed request for a team, isaacs and mydea August 11, 2026 14:34
@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 28.57 kB - -
@sentry/browser - with treeshaking flags 26.92 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 26.82 kB - -
@sentry/browser (incl. Tracing) 48.34 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 48.36 kB - -
@sentry/browser (incl. Tracing, Profiling) 51.25 kB - -
@sentry/browser (incl. Tracing, Replay) 87.74 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 77.2 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 92.45 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 105.13 kB - -
@sentry/browser (incl. Feedback) 45.81 kB - -
@sentry/browser (incl. sendFeedback) 33.36 kB - -
@sentry/browser (incl. FeedbackAsync) 38.47 kB - -
@sentry/browser (incl. Metrics) 29.52 kB - -
@sentry/browser (incl. Logs) 29.8 kB - -
@sentry/browser (incl. Metrics & Logs) 30.45 kB - -
@sentry/react 30.33 kB - -
@sentry/react (incl. Tracing) 50.52 kB - -
@sentry/vue 35.4 kB - -
@sentry/vue (incl. Tracing) 50.32 kB - -
@sentry/svelte 28.6 kB - -
CDN Bundle 30.32 kB - -
CDN Bundle (incl. Tracing) 48.87 kB - -
CDN Bundle (incl. Logs, Metrics) 32.54 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 50.74 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 72.91 kB - -
CDN Bundle (incl. Tracing, Replay) 86.33 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 88.16 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 92.07 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 94 kB - -
CDN Bundle - uncompressed 89.94 kB - -
CDN Bundle (incl. Tracing) - uncompressed 146.13 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 96.23 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 151.81 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 225.18 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 265.4 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 271.07 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 279.09 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 284.76 kB - -
@sentry/nextjs (client) 53.07 kB - -
@sentry/sveltekit (client) 48.76 kB - -
@sentry/core/server 64.95 kB - -
@sentry/core/browser 52.11 kB - -
@sentry/node 117.54 kB +0.07% +78 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 85.18 kB - -
@sentry/node - without tracing 82.08 kB +0.1% +75 B 🔺
@sentry/aws-serverless 91.51 kB +0.09% +75 B 🔺
@sentry/cloudflare (withSentry) - minified 196.3 kB +0.83% +1.61 kB 🔺
@sentry/cloudflare (withSentry) 485.91 kB +0.96% +4.62 kB 🔺

View base workflow run

@JPeer264
JPeer264 marked this pull request as draft August 12, 2026 08:09
@JPeer264
JPeer264 force-pushed the jp/cloudflare-tracerprovider branch 5 times, most recently from ed6e9c1 to 359e1f3 Compare August 14, 2026 09:07
@JPeer264
JPeer264 marked this pull request as ready for review August 21, 2026 06:39
@JPeer264
JPeer264 requested review from andreiborza and isaacs August 21, 2026 06:39
Comment on lines 54 to 62
export function wrapRequestHandler(
wrapperOptions: RequestHandlerWrapperOptions,
wrapperOptions: Omit<RequestHandlerWrapperOptions, 'options'> & {
// `enableOpenTelemetrySetup` is only honored by `init` from `sdk.ts`; this entry point
// initializes the SDK via `initBaseSdk`, where setting it would have no effect.
options: Omit<CloudflareOptions, 'enableOpenTelemetrySetup'>;
},
handler: (...args: unknown[]) => Response | Promise<Response>,
): Promise<Response> {
return wrapRequestHandlerWithInit(wrapperOptions, handler, initBaseSdk);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bug: The wrapRequestHandler no longer accepts enableOpenTelemetrySetup, but the SvelteKit integration still passes it. This will silently disable SvelteKit's OpenTelemetry tracing on Cloudflare.
Severity: MEDIUM

Suggested Fix

Update the SvelteKit integration to handle this change. Either switch to using the main init function from sdk.ts which still honors enableOpenTelemetrySetup, or remove the enableOpenTelemetrySetup: true setting from the options passed to wrapRequestHandler.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: packages/cloudflare/src/request.ts#L54-L62

Potential issue: The `wrapRequestHandler` function's options type was changed to
`Omit<CloudflareOptions, 'enableOpenTelemetrySetup'>`, explicitly removing support for
this option from the `/request` entrypoint. However, the SvelteKit integration was not
updated and continues to pass `enableOpenTelemetrySetup: true` to this function. While
this is a TypeScript type error, at runtime the property is silently ignored. This
causes a functional regression where SvelteKit's own OpenTelemetry spans (for Kit
tracing) will no longer be captured by Sentry when deployed on Cloudflare, as the
necessary tracer setup is skipped.

Also affects:

  • packages/cloudflare/src/baseSdk.ts:18~23

Did we get this right? 👍 / 👎 to inform future reviews.

@JPeer264

Copy link
Copy Markdown
Member Author

bugbot run

@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 359e1f3. Configure here.

Comment thread packages/opentelemetry/src/tracer.ts
JPeer264 and others added 3 commits August 25, 2026 10:34
… interop

Replaces the bespoke Cloudflare tracer with `SentryTracerProvider` from
`@sentry/opentelemetry`, and covers `enableOpenTelemetrySetup` end to end in
workerd with two integration suites.

The enabled suite documents that `startActiveSpan` detaches into a root
transaction of its own rather than nesting under the request span: it always
resolves an explicit context, and Cloudflare installs no OTel context manager,
so `context.active()` never carries the request span. `startSpan` passes no
context and does nest, so both paths are asserted to pin the difference.

The two workers are kept identical apart from the option itself, so the disabled
suite also proves the wider OTel surface stays inert when the provider is off.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ager

Without a context manager (e.g. Cloudflare) `context.with` runs the callback directly, so the span set on the current scope leaked past the callback and later spans parented to it. Fork the scope in that case, and detect the parent of an ignored span through `getActiveSpan()` so it is not made active either.
@JPeer264
JPeer264 force-pushed the jp/cloudflare-tracerprovider branch from 359c804 to 1377b41 Compare August 25, 2026 07:34
Comment on lines +95 to 96
if (spanIsIgnored(span) && this._hasParentSpan(options, explicitCtx)) {
return context.with(withCapturedIsolationScope(ctx), () => callback(span)) as ReturnType<F>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bug: On runtimes without an OTel context manager (e.g., Cloudflare), the callback for an ignored span can mutate and pollute the parent scope because it doesn't fork the scope.
Severity: MEDIUM

Suggested Fix

Wrap the callback for the ignored span path in a withScope call, similar to how the non-ignored span path is handled. This will ensure a new scope is forked, isolating any scope mutations within the callback and preventing them from polluting the parent scope.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: packages/opentelemetry/src/tracer.ts#L95-L96

Potential issue: On runtimes without an OTel context manager, such as Cloudflare, the
code path for an ignored span within `startActiveSpan` does not fork the Sentry scope.
The `context.with` call runs the callback synchronously without creating a new scope. If
the callback mutates the scope (e.g., by calling `scope.addBreadcrumb()` or
`scope.setTag()`), these changes will leak and persist on the parent scope after the
callback completes. This is inconsistent with the non-ignored span path, which
explicitly uses `withScope` to prevent such pollution.

@JPeer264
JPeer264 merged commit f228ee4 into develop Aug 25, 2026
216 checks passed
@JPeer264
JPeer264 deleted the jp/cloudflare-tracerprovider branch August 25, 2026 08:36
JPeer264 added a commit that referenced this pull request Aug 25, 2026
… interop (#23300)

This uses now the `SentryTracerProvider` and removes the previous kinda
mocked provider. I added two integration tests that check if OTel traces
are picked up by our provider—just to tripple check if the machinery is
implemented correctly.

I made it breaking since the `sentry.cloudflare_tracer` attribute is
being removed now (I added this as a fixup in the migration guide)

Also for Hydrogen aka the `/request` entrypoint, we no longer support
the `enableOpenTelemetrySetup` option, as this would require
`node:async_hooks`, which isn't available in Hydrogen. In case this
would be needed in the future we can enable this and readd the previous
OTel Tracer Provider. But for now it is better to keep it simple.

### Keep an eye on this 👀 

I had to adjust `startActiveSpan` in order to not mess with the root
span:
https://github.com/getsentry/sentry-javascript/actions/runs/31579946168/job/94061924393

--- 

Clanker machinery comment:

Replaces the bespoke Cloudflare tracer with `SentryTracerProvider` from
`@sentry/opentelemetry`, and covers `enableOpenTelemetrySetup` end to
end in workerd with two integration suites.

The enabled suite documents that `startActiveSpan` detaches into a root
transaction of its own rather than nesting under the request span: it
always resolves an explicit context, and Cloudflare installs no OTel
context manager, so `context.active()` never carries the request span.
`startSpan` passes no context and does nest, so both paths are asserted
to pin the difference.

The two workers are kept identical apart from the option itself, so the
disabled suite also proves the wider OTel surface stays inert when the
provider is off.

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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