Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(profiler): scope require to binding import call #13834

Open
wants to merge 18 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions dev-packages/e2e-tests/test-applications/node-profiling/index.mjs
Original file line number Diff line number Diff line change
@@ -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://[email protected]/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');
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
37 changes: 15 additions & 22 deletions packages/profiling-node/rollup.npm.config.mjs
Original file line number Diff line number Diff line change
@@ -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;
},
};
}
Expand All @@ -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());
}
}

Expand Down
71 changes: 36 additions & 35 deletions packages/profiling-node/src/cpu_profiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -27,72 +29,71 @@ 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');
}
}
}

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');
}
}
}
Expand All @@ -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();
Expand Down
Loading