diff --git a/dev-packages/e2e-tests/test-applications/node-profiling/index.mjs b/dev-packages/e2e-tests/test-applications/node-profiling/index.mjs new file mode 100644 index 000000000000..6d8a4aae1087 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/node-profiling/index.mjs @@ -0,0 +1,21 @@ +import * as Sentry from '@sentry/node'; +import { nodeProfilingIntegration } from '@sentry/profiling-node'; + +const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); + +Sentry.init({ + dsn: 'https://7fa19397baaf433f919fbe02228d5470@o1137848.ingest.sentry.io/6625302', + integrations: [nodeProfilingIntegration()], + tracesSampleRate: 1.0, + profilesSampleRate: 1.0, +}); + +Sentry.startSpan({ name: 'Precompile test' }, async () => { + await wait(500); +}); + +// Test that globalThis.require is not defined by any side effects of the profiling +// https://github.com/getsentry/sentry-javascript/issues/13662 +if (globalThis.require !== undefined) { + throw new Error('globalThis.require should not be defined, check that profiling integration is not defining it'); +} diff --git a/dev-packages/e2e-tests/test-applications/node-profiling/package.json b/dev-packages/e2e-tests/test-applications/node-profiling/package.json index a4c4bf1284fe..9196286f6e35 100644 --- a/dev-packages/e2e-tests/test-applications/node-profiling/package.json +++ b/dev-packages/e2e-tests/test-applications/node-profiling/package.json @@ -5,7 +5,7 @@ "scripts": { "typecheck": "tsc --noEmit", "build": "node build.mjs && node build.shimmed.mjs", - "test": "node dist/index.js && node --experimental-require-module dist/index.js && node dist/index.shimmed.mjs", + "test": "node dist/index.js && node --experimental-require-module dist/index.js && node dist/index.shimmed.mjs && node index.mjs", "clean": "npx rimraf node_modules dist", "test:build": "npm run typecheck && npm run build", "test:assert": "npm run test" diff --git a/packages/profiling-node/rollup.npm.config.mjs b/packages/profiling-node/rollup.npm.config.mjs index 12492b7c83e8..4af468cf1ea1 100644 --- a/packages/profiling-node/rollup.npm.config.mjs +++ b/packages/profiling-node/rollup.npm.config.mjs @@ -1,29 +1,25 @@ import commonjs from '@rollup/plugin-commonjs'; import { makeBaseNPMConfig, makeNPMConfigVariants } from '@sentry-internal/rollup-utils'; -export const ESMShim = ` -import cjsUrl from 'node:url'; -import cjsPath from 'node:path'; -import cjsModule from 'node:module'; - -if(typeof __filename === 'undefined'){ - globalThis.__filename = cjsUrl.fileURLToPath(import.meta.url); -} - -if(typeof __dirname === 'undefined'){ - globalThis.__dirname = cjsPath.dirname(__filename); -} - -if(typeof require === 'undefined'){ - globalThis.require = cjsModule.createRequire(import.meta.url); -} +export const ESMImportShim = ` +import { createRequire } from 'node:module'; +import { fileURLToPath } from 'node:url'; +import { dirname } from 'node:path'; + +const __sentry_filename = fileURLToPath(import.meta.url); +const __sentry_dirname = dirname(__sentry_filename); +const __sentry_require = createRequire(import.meta.url); `; -function makeESMShimPlugin(shim) { +export const ESMRequireShim = ''; + +function makeESMShimPlugin() { return { transform(code) { const SHIM_REGEXP = /\/\/ #START_SENTRY_ESM_SHIM[\s\S]*?\/\/ #END_SENTRY_ESM_SHIM/; - return code.replace(SHIM_REGEXP, shim); + + const withImportShimmed = code.replace(SHIM_REGEXP, ESMImportShim); + return withImportShimmed; }, }; } @@ -39,10 +35,7 @@ const variants = makeNPMConfigVariants( for (const variant of variants) { if (variant.output.format === 'esm') { - variant.plugins.push(makeESMShimPlugin(ESMShim)); - } else { - // Remove the ESM shim comment - variant.plugins.push(makeESMShimPlugin('')); + variant.plugins.push(makeESMShimPlugin()); } } diff --git a/packages/profiling-node/src/cpu_profiler.ts b/packages/profiling-node/src/cpu_profiler.ts index fb739a939e77..9bfcfcf5e2e1 100644 --- a/packages/profiling-node/src/cpu_profiler.ts +++ b/packages/profiling-node/src/cpu_profiler.ts @@ -18,7 +18,9 @@ import type { ProfileFormat } from './types'; // #START_SENTRY_ESM_SHIM // When building for ESM, we shim require to use createRequire and __dirname. // We need to do this because .node extensions in esm are not supported. -// The comment below this line exists as a placeholder for where to insert the shim. +// The comment below this line exists as a placeholder for where to insert the shim +const __sentry_require = require; +const __sentry_dirname = __dirname; // #END_SENTRY_ESM_SHIM const stdlib = familySync(); @@ -27,55 +29,54 @@ const arch = process.env['BUILD_ARCH'] || _arch(); const abi = getAbi(versions.node, 'node'); const identifier = [platform, arch, stdlib, abi].filter(c => c !== undefined && c !== null).join('-'); -const built_from_source_path = resolve(__dirname, '..', `./sentry_cpu_profiler-${identifier}`); +const built_from_source_path = resolve(__sentry_dirname, '..', `./sentry_cpu_profiler-${identifier}`); /** * Imports cpp bindings based on the current platform and architecture. */ // eslint-disable-next-line complexity export function importCppBindingsModule(): PrivateV8CpuProfilerBindings { - // If a binary path is specified, use that. if (env['SENTRY_PROFILER_BINARY_PATH']) { const envPath = env['SENTRY_PROFILER_BINARY_PATH']; - return require(envPath); + return __sentry_require(envPath); } // If a user specifies a different binary dir, they are in control of the binaries being moved there if (env['SENTRY_PROFILER_BINARY_DIR']) { const binaryPath = join(resolve(env['SENTRY_PROFILER_BINARY_DIR']), `sentry_cpu_profiler-${identifier}`); - return require(`${binaryPath}.node`); + return __sentry_require(`${binaryPath}.node`); } - // We need the fallthrough so that in the end, we can fallback to the require dynamice require. + // We need the fallthrough so that in the end, we can fallback to the __sentry_require dynamice require. // This is for cases where precompiled binaries were not provided, but may have been compiled from source. if (platform === 'darwin') { if (arch === 'x64') { if (abi === '93') { - return require('../sentry_cpu_profiler-darwin-x64-93.node'); + return __sentry_require('../sentry_cpu_profiler-darwin-x64-93.node'); } if (abi === '108') { - return require('../sentry_cpu_profiler-darwin-x64-108.node'); + return __sentry_require('../sentry_cpu_profiler-darwin-x64-108.node'); } if (abi === '115') { - return require('../sentry_cpu_profiler-darwin-x64-115.node'); + return __sentry_require('../sentry_cpu_profiler-darwin-x64-115.node'); } if (abi === '127') { - return require('../sentry_cpu_profiler-darwin-x64-127.node'); + return __sentry_require('../sentry_cpu_profiler-darwin-x64-127.node'); } } if (arch === 'arm64') { if (abi === '93') { - return require('../sentry_cpu_profiler-darwin-arm64-93.node'); + return __sentry_require('../sentry_cpu_profiler-darwin-arm64-93.node'); } if (abi === '108') { - return require('../sentry_cpu_profiler-darwin-arm64-108.node'); + return __sentry_require('../sentry_cpu_profiler-darwin-arm64-108.node'); } if (abi === '115') { - return require('../sentry_cpu_profiler-darwin-arm64-115.node'); + return __sentry_require('../sentry_cpu_profiler-darwin-arm64-115.node'); } if (abi === '127') { - return require('../sentry_cpu_profiler-darwin-arm64-127.node'); + return __sentry_require('../sentry_cpu_profiler-darwin-arm64-127.node'); } } } @@ -83,16 +84,16 @@ export function importCppBindingsModule(): PrivateV8CpuProfilerBindings { if (platform === 'win32') { if (arch === 'x64') { if (abi === '93') { - return require('../sentry_cpu_profiler-win32-x64-93.node'); + return __sentry_require('../sentry_cpu_profiler-win32-x64-93.node'); } if (abi === '108') { - return require('../sentry_cpu_profiler-win32-x64-108.node'); + return __sentry_require('../sentry_cpu_profiler-win32-x64-108.node'); } if (abi === '115') { - return require('../sentry_cpu_profiler-win32-x64-115.node'); + return __sentry_require('../sentry_cpu_profiler-win32-x64-115.node'); } if (abi === '127') { - return require('../sentry_cpu_profiler-win32-x64-127.node'); + return __sentry_require('../sentry_cpu_profiler-win32-x64-127.node'); } } } @@ -101,65 +102,65 @@ export function importCppBindingsModule(): PrivateV8CpuProfilerBindings { if (arch === 'x64') { if (stdlib === 'musl') { if (abi === '93') { - return require('../sentry_cpu_profiler-linux-x64-musl-93.node'); + return __sentry_require('../sentry_cpu_profiler-linux-x64-musl-93.node'); } if (abi === '108') { - return require('../sentry_cpu_profiler-linux-x64-musl-108.node'); + return __sentry_require('../sentry_cpu_profiler-linux-x64-musl-108.node'); } if (abi === '115') { - return require('../sentry_cpu_profiler-linux-x64-musl-115.node'); + return __sentry_require('../sentry_cpu_profiler-linux-x64-musl-115.node'); } if (abi === '127') { - return require('../sentry_cpu_profiler-linux-x64-musl-127.node'); + return __sentry_require('../sentry_cpu_profiler-linux-x64-musl-127.node'); } } if (stdlib === 'glibc') { if (abi === '93') { - return require('../sentry_cpu_profiler-linux-x64-glibc-93.node'); + return __sentry_require('../sentry_cpu_profiler-linux-x64-glibc-93.node'); } if (abi === '108') { - return require('../sentry_cpu_profiler-linux-x64-glibc-108.node'); + return __sentry_require('../sentry_cpu_profiler-linux-x64-glibc-108.node'); } if (abi === '115') { - return require('../sentry_cpu_profiler-linux-x64-glibc-115.node'); + return __sentry_require('../sentry_cpu_profiler-linux-x64-glibc-115.node'); } if (abi === '127') { - return require('../sentry_cpu_profiler-linux-x64-glibc-127.node'); + return __sentry_require('../sentry_cpu_profiler-linux-x64-glibc-127.node'); } } } if (arch === 'arm64') { if (stdlib === 'musl') { if (abi === '93') { - return require('../sentry_cpu_profiler-linux-arm64-musl-93.node'); + return __sentry_require('../sentry_cpu_profiler-linux-arm64-musl-93.node'); } if (abi === '108') { - return require('../sentry_cpu_profiler-linux-arm64-musl-108.node'); + return __sentry_require('../sentry_cpu_profiler-linux-arm64-musl-108.node'); } if (abi === '115') { - return require('../sentry_cpu_profiler-linux-arm64-musl-115.node'); + return __sentry_require('../sentry_cpu_profiler-linux-arm64-musl-115.node'); } if (abi === '127') { - return require('../sentry_cpu_profiler-linux-arm64-musl-127.node'); + return __sentry_require('../sentry_cpu_profiler-linux-arm64-musl-127.node'); } } if (stdlib === 'glibc') { if (abi === '93') { - return require('../sentry_cpu_profiler-linux-arm64-glibc-93.node'); + return __sentry_require('../sentry_cpu_profiler-linux-arm64-glibc-93.node'); } if (abi === '108') { - return require('../sentry_cpu_profiler-linux-arm64-glibc-108.node'); + return __sentry_require('../sentry_cpu_profiler-linux-arm64-glibc-108.node'); } if (abi === '115') { - return require('../sentry_cpu_profiler-linux-arm64-glibc-115.node'); + return __sentry_require('../sentry_cpu_profiler-linux-arm64-glibc-115.node'); } if (abi === '127') { - return require('../sentry_cpu_profiler-linux-arm64-glibc-127.node'); + return __sentry_require('../sentry_cpu_profiler-linux-arm64-glibc-127.node'); } } } } - return require(`${built_from_source_path}.node`); + return __sentry_require(`${built_from_source_path}.node`); } const PrivateCpuProfilerBindings: PrivateV8CpuProfilerBindings = importCppBindingsModule();