From 1d3e2087c8ea64d0439c3d558b8284d046cdce66 Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Mon, 15 Jul 2024 17:21:43 +0200 Subject: [PATCH] feat: Expose `exclude` and `include` options for ESM loader (#12910) Closes #12878 I added this feature to `import-in-the-middle` which was released in v1.9.0: - https://github.com/nodejs/import-in-the-middle/pull/124 This PR changes the hook from `@opentelemetry/instrumentation/hook.mjs` to `import-in-the-middle/hook.mjs` as it was only pasing though anyway and the otel hook doesn't pass the `initialize` export. --- packages/node/src/sdk/index.ts | 2 +- packages/node/src/sdk/initOtel.ts | 5 +++-- packages/node/src/types.ts | 18 ++++++++++++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/node/src/sdk/index.ts b/packages/node/src/sdk/index.ts index 0fb7774827f9..7dd145854993 100644 --- a/packages/node/src/sdk/index.ts +++ b/packages/node/src/sdk/index.ts @@ -132,7 +132,7 @@ function _init( } if (!isCjs() && options.registerEsmLoaderHooks !== false) { - maybeInitializeEsmLoader(); + maybeInitializeEsmLoader(options.registerEsmLoaderHooks === true ? undefined : options.registerEsmLoaderHooks); } setOpenTelemetryContextAsyncContextStrategy(); diff --git a/packages/node/src/sdk/initOtel.ts b/packages/node/src/sdk/initOtel.ts index 47c8879ae3e9..947486ba26cb 100644 --- a/packages/node/src/sdk/initOtel.ts +++ b/packages/node/src/sdk/initOtel.ts @@ -13,6 +13,7 @@ import { GLOBAL_OBJ, consoleSandbox, logger } from '@sentry/utils'; import { getOpenTelemetryInstrumentationToPreload } from '../integrations/tracing'; import { SentryContextManager } from '../otel/contextManager'; +import type { EsmLoaderHookOptions } from '../types'; import { isCjs } from '../utils/commonjs'; import type { NodeClient } from './client'; @@ -31,7 +32,7 @@ export function initOpenTelemetry(client: NodeClient): void { } /** Initialize the ESM loader. */ -export function maybeInitializeEsmLoader(): void { +export function maybeInitializeEsmLoader(esmHookConfig?: EsmLoaderHookOptions): void { const [nodeMajor = 0, nodeMinor = 0] = process.versions.node.split('.').map(Number); // Register hook was added in v20.6.0 and v18.19.0 @@ -43,7 +44,7 @@ export function maybeInitializeEsmLoader(): void { if (!GLOBAL_OBJ._sentryEsmLoaderHookRegistered && importMetaUrl) { try { // @ts-expect-error register is available in these versions - moduleModule.register('@opentelemetry/instrumentation/hook.mjs', importMetaUrl); + moduleModule.register('import-in-the-middle/hook.mjs', importMetaUrl, { data: esmHookConfig }); GLOBAL_OBJ._sentryEsmLoaderHookRegistered = true; } catch (error) { logger.warn('Failed to register ESM hook', error); diff --git a/packages/node/src/types.ts b/packages/node/src/types.ts index 882114a013f9..9cf3047e6c0a 100644 --- a/packages/node/src/types.ts +++ b/packages/node/src/types.ts @@ -4,6 +4,11 @@ import type { ClientOptions, Options, SamplingContext, Scope, Span, TracePropaga import type { NodeTransportOptions } from './transports'; +export interface EsmLoaderHookOptions { + include?: string[]; + exclude?: string[]; +} + export interface BaseNodeOptions { /** * List of strings/regex controlling to which outgoing requests @@ -87,13 +92,22 @@ export interface BaseNodeOptions { /** * Whether to register ESM loader hooks to automatically instrument libraries. - * This is necessary to auto instrument libraries that are loaded via ESM imports, but might it can cause issues + * This is necessary to auto instrument libraries that are loaded via ESM imports, but it can cause issues * with certain libraries. If you run into problems running your app with this enabled, * please raise an issue in https://github.com/getsentry/sentry-javascript. * + * You can optionally exclude specific modules or only include specific modules from being instrumented by providing + * an object with `include` or `exclude` properties. + * + * ```js + * registerEsmLoaderHooks: { + * exclude: ['openai'], + * } + * ``` + * * Defaults to `true`. */ - registerEsmLoaderHooks?: boolean; + registerEsmLoaderHooks?: boolean | EsmLoaderHookOptions; /** Callback that is executed when a fatal global error occurs. */ onFatalError?(this: void, error: Error): void;