1- import { debug } from '@sentry/core' ;
1+ import { debug , GLOBAL_OBJ } from '@sentry/core' ;
22import { createRequire } from 'node:module' ;
33import * as Module from 'node:module' ;
44import { pathToFileURL } from 'node:url' ;
55import { DEBUG_BUILD } from '../../debug-build' ;
66import { SENTRY_INSTRUMENTATIONS } from '../config' ;
7+ import type { InstrumentationConfig } from '@apm-js-collab/code-transformer' ;
8+ import type { register } from 'node:module' ;
9+
10+ type TracingHooksSync = {
11+ initialize : ( opts : { instrumentations : InstrumentationConfig [ ] } ) => void ;
12+ resolve : Function ;
13+ load : Function ;
14+ setDiagnosticsHook : ( callback : ( event : { url : string ; moduleName : string ; error : Error } ) => void ) => void ;
15+ } ;
16+
17+ type NodeModule = {
18+ registerHooks ?: ( options : unknown ) => { deregister : ( ) => void } ;
19+ register ?: typeof register ;
20+ } ;
721
822export interface RegisterDiagnosticsChannelInjectionOptions {
923 /**
@@ -17,11 +31,6 @@ export interface RegisterDiagnosticsChannelInjectionOptions {
1731 tracingHooksDir ?: string ;
1832}
1933
20- declare global {
21- // eslint-disable-next-line no-var
22- var __SENTRY_ORCHESTRION__ : { runtime ?: boolean ; bundler ?: boolean } | undefined ;
23- }
24-
2534/** `Module.registerHooks` only became stable in Node 24.13 / 25.1 and Deno 2.8. */
2635function hasStableSyncModuleHooks ( denoVersionString : string | undefined ) : boolean {
2736 const parseVersion = ( v : string ) : number [ ] => v . split ( '.' ) . map ( n => parseInt ( n , 10 ) ) ;
@@ -47,15 +56,9 @@ function hasStableSyncModuleHooks(denoVersionString: string | undefined): boolea
4756 *
4857 * Libraries imported *after* this call publish the `tracingChannel` events that
4958 * the channel-based integrations subscribe to.
50- *
51- * Idempotent via `globalThis.__SENTRY_ORCHESTRION__` — a no-op if the runtime
52- * `--import` hook or a bundler plugin already injected the channels.
5359 */
5460export function registerDiagnosticsChannelInjection ( options ?: RegisterDiagnosticsChannelInjectionOptions ) : void {
55- const g = ( globalThis . __SENTRY_ORCHESTRION__ ??= { } ) ;
56-
57- // Already injected (runtime --import hook or bundler plugin) — nothing to do.
58- if ( g . runtime || g . bundler ) {
61+ if ( GLOBAL_OBJ ?. __SENTRY_ORCHESTRION__ ?. runtime ) {
5962 return ;
6063 }
6164
@@ -89,10 +92,7 @@ export function registerDiagnosticsChannelInjection(options?: RegisterDiagnostic
8992
9093 // `Module.registerHooks` / `Module.register` are newer than the @types/node
9194 // we build against, hence the cast.
92- const mod = Module as unknown as {
93- registerHooks ?: ( hooks : unknown ) => void ;
94- register ?: ( specifier : string , options : unknown ) => void ;
95- } ;
95+ const mod = Module as NodeModule ;
9696
9797 // runs both at `--import` time and (synchronously) inside `Sentry.init()`,
9898 // so an unguarded throw would either abort startup or make `init()` throw.
@@ -105,15 +105,18 @@ export function registerDiagnosticsChannelInjection(options?: RegisterDiagnostic
105105 // We require() the module here so that we can synchronously load it,
106106 // including from a CommonJS Sentry build, without bundlers pulling in.
107107 // All versions in stableSyncHooks support this.
108- const { initialize, resolve, load } = (
108+ const { initialize, resolve, load, setDiagnosticsHook } = (
109109 requireFromHooksDir
110110 ? requireFromHooksDir ( `${ tracingHooksDir } /hook-sync.mjs` )
111111 : nodeRequire ( '@apm-js-collab/tracing-hooks/hook-sync.mjs' )
112- ) as {
113- initialize : ( opts : { instrumentations : unknown } ) => void ;
114- resolve : unknown ;
115- load : unknown ;
116- } ;
112+ ) as TracingHooksSync ;
113+
114+ setDiagnosticsHook ( event => {
115+ GLOBAL_OBJ . __SENTRY_ORCHESTRION__ = GLOBAL_OBJ . __SENTRY_ORCHESTRION__ || { } ;
116+ GLOBAL_OBJ . __SENTRY_ORCHESTRION__ . runtime = GLOBAL_OBJ . __SENTRY_ORCHESTRION__ . runtime || [ ] ;
117+ GLOBAL_OBJ . __SENTRY_ORCHESTRION__ . runtime . push ( event . moduleName ) ;
118+ } ) ;
119+
117120 initialize ( { instrumentations : SENTRY_INSTRUMENTATIONS } ) ;
118121 mod . registerHooks ( { resolve, load } ) ;
119122 DEBUG_BUILD && debug . log ( '[orchestrion] registered diagnostics-channel injection via Module.registerHooks()' ) ;
@@ -161,5 +164,6 @@ export function registerDiagnosticsChannelInjection(options?: RegisterDiagnostic
161164 return ;
162165 }
163166
164- g . runtime = true ;
167+ GLOBAL_OBJ . __SENTRY_ORCHESTRION__ = GLOBAL_OBJ . __SENTRY_ORCHESTRION__ || { } ;
168+ GLOBAL_OBJ . __SENTRY_ORCHESTRION__ . runtime = GLOBAL_OBJ . __SENTRY_ORCHESTRION__ . runtime || [ ] ;
165169}
0 commit comments