fix(core): Improve waiting for tracing channel bindings#21815
Conversation
size-limit report 📦
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 113ee44. Configure here.
| setOpenTelemetryContextAsyncContextStrategy(); | ||
| // We force skipOpenTelemetrySetup: true here, because this triggers the custom lookup for the AsyncLocalStorage instance | ||
| // Since we use a custom Context Manager here (because AsyncLocalStorage is looked up differently than in Node), we need to do this | ||
| setOpenTelemetryContextAsyncContextStrategy({ skipOpenTelemetrySetup: true }); |
There was a problem hiding this comment.
Bug: The vercel-edge SDK calls setOpenTelemetryContextAsyncContextStrategy with skipOpenTelemetrySetup: true, but the browser bundle now exports a version that silently ignores this option, breaking async context setup.
Severity: HIGH
Suggested Fix
The vercel-edge SDK needs to be updated to work with the new async context strategy. Instead of relying on the skipOpenTelemetrySetup option, it should be adapted to the new mechanism for setting up the async local storage instance, possibly by directly providing a getTracingChannelBinding function. Alternatively, ensure the vercel-edge package always resolves the Node.js bundle of @sentry/opentelemetry if that is the intended behavior.
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/vercel-edge/src/sdk.ts#L68
Potential issue: The `vercel-edge` SDK calls
`setOpenTelemetryContextAsyncContextStrategy({ skipOpenTelemetrySetup: true })` to
enable a custom context manager. However, recent changes mean that when the browser
bundle of `@sentry/opentelemetry` is used, this function resolves to a generic version
that no longer accepts the `skipOpenTelemetrySetup` option. The option is silently
ignored, which prevents the custom `getTracingChannelBinding` from being configured.
This breaks the async context strategy for the Vercel Edge environment, as it relies on
this specific setup path for proper tracing.
Also affects:
packages/opentelemetry/src/index.browser.ts:15~17
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
I guess this is fine either way, as DC stuff does not work in vercel-edge anyhow so this is fine if it noops? cc @logaretm
There was a problem hiding this comment.
As long as we guard in the instrumentations, that should be fine. The bind function doesn't import tracing channels in runtime, so the integrations should noop.

We rely on the async local storage instance for the tracing channel bindings.
Previously, this was picked up from the otel context manager (in otel-mode). However, this is only setup after the integrations run, leading to a race condition where this was not available yet.
The "fix" for this we used so far was to setup the channel-based listeners in the next tick via
Promise.resolve(). Apart from being a bit hacky, this also has a concrete problem: If code runs synchrounsly after Sentry.init(), this could be unhandled by our integration (this was surfaced when moving vercel ai v6 to use orchestrion, where this failed in CJS).So this PR changes this a bit, so that in the happy path where we use our own context manager, we can use a consistent instance of async local storage even before the manager is setup. In this case, we can setup the integrations in a sync way and everything just works.
If users use a custom context manager, this will/may not work though. So in this case we continue to use the lookup from the context manager (this can be removed in v11). Since this means we have the same problems as before, I added a small utility
waitForTracingChannelBindingto abstract this away - this will try to see if this is setup and if so, exectute the provided callback synchronously. Else, it will wait a tick and try again (mirroring what we had before).While at this, I also cleaned up internal exports from core a bit - one of them can be reproduced with more public APIs already, we just never exported
getAsyncContextStrategyfrom core but this is fine to export IMHO.