Skip to content

Commit aaf7d53

Browse files
authored
feat(node)!: Remove fine grained registerEsmLoaderHooks (#15002)
1 parent 2f302d7 commit aaf7d53

File tree

8 files changed

+11
-146
lines changed

8 files changed

+11
-146
lines changed

dev-packages/e2e-tests/test-applications/node-express-esm-loader/src/instrument.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,4 @@ Sentry.init({
55
dsn: process.env.E2E_TEST_DSN,
66
tunnel: `http://localhost:3031/`, // proxy server
77
tracesSampleRate: 1,
8-
registerEsmLoaderHooks: { onlyIncludeInstrumentedModules: true },
98
});

dev-packages/node-integration-tests/suites/esm/import-in-the-middle/app.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ Sentry.init({
1212
dsn: 'https://public@dsn.ingest.sentry.io/1337',
1313
release: '1.0',
1414
transport: loggingTransport,
15-
registerEsmLoaderHooks: { onlyIncludeInstrumentedModules: true },
1615
});
1716

1817
await import('./sub-module.mjs');

dev-packages/node-integration-tests/suites/esm/import-in-the-middle/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ afterAll(() => {
77
});
88

99
describe('import-in-the-middle', () => {
10-
test('onlyIncludeInstrumentedModules', () => {
10+
test('should only instrument modules that we have instrumentation for', () => {
1111
const result = spawnSync('node', [join(__dirname, 'app.mjs')], { encoding: 'utf-8' });
1212
expect(result.stderr).not.toMatch('should be the only hooked modules but we just hooked');
1313
});

packages/node/src/sdk/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ function _init(
131131
}
132132

133133
if (!isCjs() && options.registerEsmLoaderHooks !== false) {
134-
maybeInitializeEsmLoader(options.registerEsmLoaderHooks === true ? undefined : options.registerEsmLoaderHooks);
134+
maybeInitializeEsmLoader();
135135
}
136136

137137
setOpenTelemetryContextAsyncContextStrategy();

packages/node/src/sdk/initOtel.ts

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { createAddHookMessageChannel } from 'import-in-the-middle';
1414
import { DEBUG_BUILD } from '../debug-build';
1515
import { getOpenTelemetryInstrumentationToPreload } from '../integrations/tracing';
1616
import { SentryContextManager } from '../otel/contextManager';
17-
import type { EsmLoaderHookOptions } from '../types';
1817
import { isCjs } from '../utils/commonjs';
1918
import type { NodeClient } from './client';
2019

@@ -40,30 +39,8 @@ export function initOpenTelemetry(client: NodeClient, options: AdditionalOpenTel
4039
client.traceProvider = provider;
4140
}
4241

43-
type ImportInTheMiddleInitData = Pick<EsmLoaderHookOptions, 'include' | 'exclude'> & {
44-
addHookMessagePort?: unknown;
45-
};
46-
47-
interface RegisterOptions {
48-
data?: ImportInTheMiddleInitData;
49-
transferList?: unknown[];
50-
}
51-
52-
function getRegisterOptions(esmHookConfig?: EsmLoaderHookOptions): RegisterOptions {
53-
// TODO(v9): Make onlyIncludeInstrumentedModules: true the default behavior.
54-
if (esmHookConfig?.onlyIncludeInstrumentedModules) {
55-
const { addHookMessagePort } = createAddHookMessageChannel();
56-
// If the user supplied include, we need to use that as a starting point or use an empty array to ensure no modules
57-
// are wrapped if they are not hooked
58-
// eslint-disable-next-line deprecation/deprecation
59-
return { data: { addHookMessagePort, include: esmHookConfig.include || [] }, transferList: [addHookMessagePort] };
60-
}
61-
62-
return { data: esmHookConfig };
63-
}
64-
6542
/** Initialize the ESM loader. */
66-
export function maybeInitializeEsmLoader(esmHookConfig?: EsmLoaderHookOptions): void {
43+
export function maybeInitializeEsmLoader(): void {
6744
const [nodeMajor = 0, nodeMinor = 0] = process.versions.node.split('.').map(Number);
6845

6946
// Register hook was added in v20.6.0 and v18.19.0
@@ -74,9 +51,12 @@ export function maybeInitializeEsmLoader(esmHookConfig?: EsmLoaderHookOptions):
7451

7552
if (!GLOBAL_OBJ._sentryEsmLoaderHookRegistered && importMetaUrl) {
7653
try {
54+
const { addHookMessagePort } = createAddHookMessageChannel();
7755
// @ts-expect-error register is available in these versions
78-
moduleModule.register('import-in-the-middle/hook.mjs', importMetaUrl, getRegisterOptions(esmHookConfig));
79-
GLOBAL_OBJ._sentryEsmLoaderHookRegistered = true;
56+
moduleModule.register('import-in-the-middle/hook.mjs', importMetaUrl, {
57+
data: { addHookMessagePort, include: [] },
58+
transferList: [addHookMessagePort],
59+
});
8060
} catch (error) {
8161
logger.warn('Failed to register ESM hook', error);
8262
}
@@ -94,7 +74,6 @@ export function maybeInitializeEsmLoader(esmHookConfig?: EsmLoaderHookOptions):
9474
interface NodePreloadOptions {
9575
debug?: boolean;
9676
integrations?: string[];
97-
registerEsmLoaderHooks?: EsmLoaderHookOptions;
9877
}
9978

10079
/**
@@ -111,7 +90,7 @@ export function preloadOpenTelemetry(options: NodePreloadOptions = {}): void {
11190
}
11291

11392
if (!isCjs()) {
114-
maybeInitializeEsmLoader(options.registerEsmLoaderHooks);
93+
maybeInitializeEsmLoader();
11594
}
11695

11796
// These are all integrations that we need to pre-load to ensure they are set up before any other code runs

packages/node/src/types.ts

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -5,43 +5,6 @@ import type { ClientOptions, Options, SamplingContext, Scope, Span, TracePropaga
55

66
import type { NodeTransportOptions } from './transports';
77

8-
/**
9-
* Note: In the next major version of the Sentry SDK this interface will be removed and the SDK will by default only wrap
10-
* ESM modules that are required to be wrapped by OpenTelemetry Instrumentation.
11-
*/
12-
export interface EsmLoaderHookOptions {
13-
/**
14-
* Provide a list of modules to wrap with `import-in-the-middle`.
15-
*
16-
* @deprecated It is recommended to use `onlyIncludeInstrumentedModules: true` instead of manually defining modules to include and exclude.
17-
*/
18-
include?: Array<string | RegExp>;
19-
20-
/**
21-
* Provide a list of modules to prevent them from being wrapped with `import-in-the-middle`.
22-
*
23-
* @deprecated It is recommended to use `onlyIncludeInstrumentedModules: true` instead of manually defining modules to include and exclude.
24-
*/
25-
exclude?: Array<string | RegExp>;
26-
27-
/**
28-
* When set to `true`, `import-in-the-middle` will only wrap ESM modules that are specifically instrumented by
29-
* OpenTelemetry plugins. This is useful to avoid issues where `import-in-the-middle` is not compatible with some of
30-
* your dependencies.
31-
*
32-
* **Note**: This feature will only work if you `Sentry.init()` the SDK before the instrumented modules are loaded.
33-
* This can be achieved via the Node `--import` CLI flag or by loading your app via async `import()` after calling
34-
* `Sentry.init()`.
35-
*
36-
* Defaults to `false`.
37-
*
38-
* Note: In the next major version of the Sentry SDK this option will be removed and the SDK will by default only wrap
39-
* ESM modules that are required to be wrapped by OpenTelemetry Instrumentation.
40-
*/
41-
// TODO(v9): Make `onlyIncludeInstrumentedModules: true` the default behavior.
42-
onlyIncludeInstrumentedModules?: boolean;
43-
}
44-
458
export interface BaseNodeOptions {
469
/**
4710
* List of strings/regex controlling to which outgoing requests
@@ -143,22 +106,9 @@ export interface BaseNodeOptions {
143106
* with certain libraries. If you run into problems running your app with this enabled,
144107
* please raise an issue in https://github.com/getsentry/sentry-javascript.
145108
*
146-
* You can optionally exclude specific modules or only include specific modules from being instrumented by providing
147-
* an object with `include` or `exclude` properties.
148-
*
149-
* ```js
150-
* registerEsmLoaderHooks: {
151-
* exclude: ['openai'],
152-
* }
153-
* ```
154-
*
155109
* Defaults to `true`.
156-
*
157-
* Note: In the next major version of the SDK, the possibility to provide fine-grained control will be removed from this option.
158-
* This means that it will only be possible to pass `true` or `false`. The default value will continue to be `true`.
159110
*/
160-
// TODO(v9): Only accept true | false | undefined.
161-
registerEsmLoaderHooks?: boolean | EsmLoaderHookOptions;
111+
registerEsmLoaderHooks?: boolean;
162112

163113
/**
164114
* Configures in which interval client reports will be flushed. Defaults to `60_000` (milliseconds).

packages/nuxt/src/server/sdk.ts

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import type { SentryNuxtServerOptions } from '../common/types';
1818
export function init(options: SentryNuxtServerOptions): Client | undefined {
1919
const sentryOptions = {
2020
...options,
21-
registerEsmLoaderHooks: mergeRegisterEsmLoaderHooks(options),
2221
defaultIntegrations: getNuxtDefaultIntegrations(options),
2322
};
2423

@@ -92,28 +91,6 @@ function getNuxtDefaultIntegrations(options: NodeOptions): Integration[] {
9291
];
9392
}
9493

95-
/**
96-
* Adds /vue/ to the registerEsmLoaderHooks options and merges it with the old values in the array if one is defined.
97-
* If the registerEsmLoaderHooks option is already a boolean, nothing is changed.
98-
*
99-
* Only exported for Testing purposes.
100-
*/
101-
export function mergeRegisterEsmLoaderHooks(
102-
options: SentryNuxtServerOptions,
103-
): SentryNuxtServerOptions['registerEsmLoaderHooks'] {
104-
if (typeof options.registerEsmLoaderHooks === 'object' && options.registerEsmLoaderHooks !== null) {
105-
return {
106-
// eslint-disable-next-line deprecation/deprecation
107-
exclude: Array.isArray(options.registerEsmLoaderHooks.exclude)
108-
? // eslint-disable-next-line deprecation/deprecation
109-
[...options.registerEsmLoaderHooks.exclude, /vue/]
110-
: // eslint-disable-next-line deprecation/deprecation
111-
options.registerEsmLoaderHooks.exclude ?? [/vue/],
112-
};
113-
}
114-
return options.registerEsmLoaderHooks ?? { exclude: [/vue/] };
115-
}
116-
11794
/**
11895
* Flushes pending Sentry events with a 2-second timeout and in a way that cannot create unhandled promise rejections.
11996
*/

packages/nuxt/test/server/sdk.test.ts

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ import { Scope } from '@sentry/node';
55
import { getGlobalScope } from '@sentry/node';
66
import { SDK_VERSION } from '@sentry/node';
77
import { beforeEach, describe, expect, it, vi } from 'vitest';
8-
import type { SentryNuxtServerOptions } from '../../src/common/types';
98
import { init } from '../../src/server';
10-
import { clientSourceMapErrorFilter, mergeRegisterEsmLoaderHooks } from '../../src/server/sdk';
9+
import { clientSourceMapErrorFilter } from '../../src/server/sdk';
1110

1211
const nodeInit = vi.spyOn(SentryNode, 'init');
1312

@@ -163,42 +162,4 @@ describe('Nuxt Server SDK', () => {
163162
});
164163
});
165164
});
166-
167-
describe('mergeRegisterEsmLoaderHooks', () => {
168-
it('merges exclude array when registerEsmLoaderHooks is an object with an exclude array', () => {
169-
const options: SentryNuxtServerOptions = {
170-
registerEsmLoaderHooks: { exclude: [/test/] },
171-
};
172-
const result = mergeRegisterEsmLoaderHooks(options);
173-
expect(result).toEqual({ exclude: [/test/, /vue/] });
174-
});
175-
176-
it('sets exclude array when registerEsmLoaderHooks is an object without an exclude array', () => {
177-
const options: SentryNuxtServerOptions = {
178-
registerEsmLoaderHooks: {},
179-
};
180-
const result = mergeRegisterEsmLoaderHooks(options);
181-
expect(result).toEqual({ exclude: [/vue/] });
182-
});
183-
184-
it('returns boolean when registerEsmLoaderHooks is a boolean', () => {
185-
const options1: SentryNuxtServerOptions = {
186-
registerEsmLoaderHooks: true,
187-
};
188-
const result1 = mergeRegisterEsmLoaderHooks(options1);
189-
expect(result1).toBe(true);
190-
191-
const options2: SentryNuxtServerOptions = {
192-
registerEsmLoaderHooks: false,
193-
};
194-
const result2 = mergeRegisterEsmLoaderHooks(options2);
195-
expect(result2).toBe(false);
196-
});
197-
198-
it('sets exclude array when registerEsmLoaderHooks is undefined', () => {
199-
const options: SentryNuxtServerOptions = {};
200-
const result = mergeRegisterEsmLoaderHooks(options);
201-
expect(result).toEqual({ exclude: [/vue/] });
202-
});
203-
});
204165
});

0 commit comments

Comments
 (0)