fix(server-utils): Ensure all orchestrion instrumentation lazy registers#22518
fix(server-utils): Ensure all orchestrion instrumentation lazy registers#22518isaacs wants to merge 1 commit into
Conversation
size-limit report 📦
|
73c683a to
d752238
Compare
|
Going to port this atop #22443 once that lands, since there are some conflicts. UPDATE: this is now done. Single commit can base cleanly on |
6d6a126 to
464dc8f
Compare
…on Node (#22518) Co-Authored-By: isaacs <i@izs.me> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
464dc8f to
ae93c4e
Compare
…azy registers on Node (#22518)
…on Node (#22518) Co-Authored-By: isaacs <i@izs.me> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
38d60ec to
7edaad4
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7edaad4. Configure here.
| const marker = (GLOBAL_OBJ.__SENTRY_ORCHESTRION__ ??= {}); | ||
| marker.onInject ??= (moduleName: string): void => { | ||
| getClient()?.emit('orchestrion.module-runtime-injected', moduleName); | ||
| }; |
There was a problem hiding this comment.
Premature orchestrion marker breaks fallbacks
High Severity
registerDiagnosticsChannelInjection now creates globalThis.__SENTRY_ORCHESTRION__ (to install onInject) before hook registration succeeds. On the skip/failure returns, that marker is left behind, so isOrchestrionInjected() becomes true even though nothing will inject channels. Opt-in paths that choose channel vs OTel from that check (knex, dataloader, Nest) then take the channel path and lose spans with no OTel fallback.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 7edaad4. Configure here.
| const cleanup = client.on('orchestrion.module-runtime-injected', (moduleName: string) => { | ||
| if (hasBeenInstrumented(callback)) { | ||
| cleanup(); | ||
| return; | ||
| } | ||
| if (moduleNames.includes(moduleName)) { | ||
| run(); | ||
| cleanup(); | ||
| } | ||
| }); |
There was a problem hiding this comment.
Bug: In deferred instrumentation, the event listener is removed via cleanup() before the async waitForTracingChannelBinding retry completes, potentially causing permanent loss of instrumentation if the binding is unavailable.
Severity: MEDIUM
Suggested Fix
The cleanup() function should only be called after the instrumentation callback has successfully executed and been marked as instrumented. This can be achieved by moving the cleanup() call inside the callback that is passed to waitForTracingChannelBinding.
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/server-utils/src/orchestrion/instrumentation.ts#L85-L94
Potential issue: When instrumentation is deferred for a module that is not yet loaded,
an event listener is registered. If the async-context binding is not available when the
module injection event fires, `waitForTracingChannelBinding` schedules an asynchronous
retry. However, the event listener is immediately and synchronously removed via
`cleanup()`. If this retry also fails to find the binding, the instrumentation callback
is never executed, and the callback is not marked as instrumented. Because the listener
has been removed, the instrumentation for that module is permanently and silently lost.


This ports and refactors the intent of #22387, using the mechanisms landed on
developin #22094, rather than the mechanisms in #22386 which are similar in intent, but substantially different in implementation.The difference from #22387 is entirely in the plumbing underneath the helper. The way that "is my module injected?" and "tell me when it gets injected" are answered, both now use the machinery that already landed.
Beyond that, the actual registration, event emitting, double-wrap guard, and integration refactoring, should all look very familiar.