From 2c337d026bf6b7cf63f18f730115137c25d392e2 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 23 Sep 2026 13:32:18 +0200 Subject: [PATCH 1/3] docs: Point profiling and native READMEs to documentation Co-Authored-By: GPT-6 --- packages/node-native/README.md | 59 +------ packages/profiling-node/README.md | 277 +----------------------------- 2 files changed, 16 insertions(+), 320 deletions(-) diff --git a/packages/node-native/README.md b/packages/node-native/README.md index 4ff7b6fdab45..53ffb938e612 100644 --- a/packages/node-native/README.md +++ b/packages/node-native/README.md @@ -10,59 +10,14 @@ [![npm dm](https://img.shields.io/npm/dm/@sentry/node-native.svg)](https://www.npmjs.com/package/@sentry/node-native) [![npm dt](https://img.shields.io/npm/dt/@sentry/node-native.svg)](https://www.npmjs.com/package/@sentry/node-native) -## Installation +Native tools for the Sentry Node.js SDK. -```bash -# Using yarn -yarn add @sentry/node @sentry/node-native +## Documentation -# Using npm -npm install --save @sentry/node @sentry/node-native -``` +- [Event loop monitoring](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/event-loop-block/) +- [Configuration](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/event-loop-block/#configuration-options) -## `eventLoopBlockIntegration` +## Support -The `eventLoopBlockIntegration` can be used to monitor for blocked event loops in -all threads of a Node.js application. - -If you instrument your application via the Node.js `--import` flag, Sentry will -be started and this instrumentation will be automatically applied to all worker -threads. - -`instrument.mjs` - -```javascript -import * as Sentry from '@sentry/node'; -import { eventLoopBlockIntegration } from '@sentry/node-native'; - -Sentry.init({ - dsn: '__YOUR_DSN__', - // Capture stack traces when the event loop is blocked for more than 500ms - integrations: [eventLoopBlockIntegration({ threshold: 500 })], -}); -``` - -`app.mjs` - -```javascript -import { Worker } from 'worker_threads'; - -const worker = new Worker(new URL('./worker.mjs', import.meta.url)); - -// This main thread will be monitored for blocked event loops -``` - -`worker.mjs` - -```javascript -// This worker thread will also be monitored for blocked event loops too -``` - -Start your application: - -```bash -node --import instrument.mjs app.mjs -``` - -If a thread is blocked for more than the configured threshold, stack traces will -be captured for all threads and sent to Sentry. +- [Report a bug](https://github.com/getsentry/sentry-javascript/issues/new/choose) +- [Contributing](https://github.com/getsentry/sentry-javascript/blob/develop/CONTRIBUTING.md) diff --git a/packages/profiling-node/README.md b/packages/profiling-node/README.md index 3188d5b20b1f..a379060dd908 100644 --- a/packages/profiling-node/README.md +++ b/packages/profiling-node/README.md @@ -10,277 +10,18 @@ [![npm dm](https://img.shields.io/npm/dm/@sentry/profiling-node.svg)](https://www.npmjs.com/package/@sentry/profiling-node) [![npm dt](https://img.shields.io/npm/dt/@sentry/profiling-node.svg)](https://www.npmjs.com/package/@sentry/profiling-node) -## Installation +Profiling for Node.js applications. -Profiling works as an extension of tracing so you will need both @sentry/node and @sentry/profiling-node installed. +## Documentation -```bash -# Using yarn -yarn add @sentry/node @sentry/profiling-node +- [Getting started](https://docs.sentry.io/platforms/javascript/guides/node/profiling/) +- [Configuration](https://docs.sentry.io/platforms/javascript/guides/node/profiling/#enabling-profiling) -# Using npm -npm install --save @sentry/node @sentry/profiling-node -``` +## Building the package from source -## Usage +The native bindings are maintained in the [Node CPU profiler repository](https://github.com/getsentry/sentry-javascript-profiling-node-binaries). -```javascript -import * as Sentry from '@sentry/node'; -import { nodeProfilingIntegration } from '@sentry/profiling-node'; +## Support -Sentry.init({ - dsn: 'https://7fa19397baaf433f919fbe02228d5470@o1137848.ingest.sentry.io/6625302', - debug: true, - tracesSampleRate: 1, - profileSessionSampleRate: 1, - profileLifecycle: 'trace', - integrations: [nodeProfilingIntegration()], -}); -``` - -The Sentry SDK will now collect profile chunks while spans are active, including spans started by automatic instrumentation. - -```javascript -Sentry.startSpan({ name: 'some workflow' }, () => { - // The code in here will be profiled -}); -``` - -With `profileLifecycle: 'manual'` (the default), you can start and stop the profiler by calling `Sentry.profiler.startProfiler()` and `Sentry.profiler.stopProfiler()`. - -### Building the package from source - -Profiling uses native modules to interop with the v8 javascript engine which means that you may be required to build it -from source. The libraries required to successfully build the package from source are often the same libraries that are -already required to build any other package which uses native modules and if your codebase uses any of those modules, -there is a fairly good chance this will work out of the box. The required packages are python, make and g++. - -**Windows:** If you are building on windows, you may need to install windows-build-tools - -**_Python:_** Python 3.12 is not supported yet so you will need a version of python that is lower than 3.12 - -```bash - -# using yarn package manager -yarn global add windows-build-tools -# or npm package manager -npm i -g windows-build-tools -``` - -After you have installed the toolchain, you should be able to build the binaries from source - -```bash -# configure node-gyp using yarn -yarn build:bindings:configure -# or using npm -npm run build:bindings:configure - -# compile the binaries using yarn -yarn build:bindings -# or using npm -npm run build:bindings -``` - -After the binaries are built, you should see them inside the profiling-node/lib folder. - -### Prebuilt binaries - -We currently ship prebuilt binaries for a few of the most common platforms and node versions (v18-24). - -- macOS x64 -- Linux ARM64 (musl) -- Linux x64 (glibc) -- Windows x64 - -For a more detailed list, see job_compile_bindings_profiling_node job in our build.yml github action workflow. - -### Bundling - -If you are looking to squeeze some extra performance or improve cold start in your application (especially true for -serverless environments where modules are often evaluates on a per request basis), then we recommend you look into -bundling your code. Modern JS engines are much faster at parsing and compiling JS than following long module resolution -chains and reading file contents from disk. Because @sentry/profiling-node is a package that uses native node modules, -bundling it is slightly different than just bundling javascript. In other words, the bundler needs to recognize that a -.node file is node native binding and move it to the correct location so that it can later be used. Failing to do so -will result in a MODULE_NOT_FOUND error. - -The easiest way to make bundling work with @sentry/profiling-node and other modules which use native nodejs bindings is -to mark the package as external - this will prevent the code from the package from being bundled, but it means that you -will now need to rely on the package to be installed in your production environment. - -To mark the package as external, use the following configuration: - -[Next.js 13+](https://nextjs.org/docs/app/api-reference/next-config-js/serverComponentsExternalPackages) - -```js -const { withSentryConfig } = require('@sentry/nextjs'); - -/** @type {import('next').NextConfig} */ -const nextConfig = { - experimental: { - // Add the "@sentry/profiling-node" to serverComponentsExternalPackages. - serverComponentsExternalPackages: ['@sentry/profiling-node'], - }, -}; - -module.exports = withSentryConfig(nextConfig, {/* ... */}); -``` - -[webpack](https://webpack.js.org/configuration/externals/#externals) - -```js -externals: { - "@sentry/profiling-node": "commonjs @sentry/profiling-node", -}, -``` - -[esbuild](https://esbuild.github.io/api/#external) - -```js -{ - entryPoints: ['index.js'], - platform: 'node', - external: ['@sentry/profiling-node'], -} -``` - -[Rollup](https://rollupjs.org/configuration-options/#external) - -```js -{ - entry: 'index.js', - external: '@sentry/profiling-node' -} -``` - -[serverless-esbuild (serverless.yml)](https://www.serverless.com/plugins/serverless-esbuild#external-dependencies) - -```yml -custom: - esbuild: - external: - - @sentry/profiling-node - packagerOptions: - scripts: - - npm install @sentry/profiling-node -``` - -[vercel-ncc](https://github.com/vercel/ncc#programmatically-from-nodejs) - -```js -{ - externals: ["@sentry/profiling-node"], -} -``` - -[vite](https://vitejs.dev/config/ssr-options.html#ssr-external) - -```js -ssr: { - external: ['@sentry/profiling-node']; -} -``` - -Marking the package as external is the simplest and most future proof way of ensuring it will work, however if you want -to bundle it, it is possible to do so as well. Bundling has the benefit of improving your script startup time as all of -the code is (usually) inside a single executable .js file, which saves time on module resolution. - -In general, when attempting to bundle .node native file extensions, you will need to tell your bundler how to treat -these, as by default it does not know how to handle them. The required approach varies between build tools and you will -need to find which one will work for you. - -The result of bundling .node files correctly is that they are placed into your bundle output directory with their -require paths updated to reflect their final location. - -Example of bundling @sentry/profiling-node with esbuild and .copy loader - -```json -// package.json -{ - "scripts": "node esbuild.serverless.js" -} -``` - -```js -// esbuild.serverless.js -const { sentryEsbuildPlugin } = require('@sentry/esbuild-plugin'); - -require('esbuild').build({ - entryPoints: ['./index.js'], - outfile: './dist', - platform: 'node', - bundle: true, - minify: true, - sourcemap: true, - // This is no longer necessary - // external: ["@sentry/profiling-node"], - loader: { - // ensures .node binaries are copied to ./dist - '.node': 'copy', - }, - plugins: [ - // See https://docs.sentry.io/platforms/javascript/sourcemaps/uploading/esbuild/ - sentryEsbuildPlugin({ - project: '', - org: '', - authToken: '', - release: '', - sourcemaps: { - // Specify the directory containing build artifacts - assets: './dist/**', - }, - }), - ], -}); -``` - -Once you run `node esbuild.serverless.js` esbuild wil bundle and output the files to ./dist folder, but note that all of -the binaries will be copied. This is wasteful as you will likely only need one of these libraries to be available during -runtime. Since the binaries follow the `sentry_cpu_profiler----.node` naming scheme, you can -delete the ones that do not match your target runtime as part of your build step to reduce the deployment size. - -### Environment flags - -The default mode of the v8 CpuProfiler is kEagerLoggin which enables the profiler even when no profiles are active - -this is good because it makes calls to startProfiling fast at the tradeoff for constant CPU overhead. The behavior can -be controlled via the `SENTRY_PROFILER_LOGGING_MODE` environment variable with values of `eager|lazy`. If you opt to use -the lazy logging mode, calls to startProfiling may be slow (depending on environment and node version, it can be in the -order of a few hundred ms). - -Example of starting a server with lazy logging mode. - -```javascript -SENTRY_PROFILER_LOGGING_MODE=lazy node server.js -``` - -## FAQ 💭 - -### Can the profiler leak PII to Sentry? - -The profiler does not collect function arguments so leaking any PII is unlikely. We only collect a subset of the values -which may identify the device and os that the profiler is running on (if you are already using tracing, it is likely -that these values are already being collected by the SDK). - -There is one way a profiler could leak pii information, but this is unlikely and would only happen for cases where you -might be creating or naming functions which might contain pii information such as - -```js -eval('function scriptFor${PII_DATA}....'); -``` - -In that case it is possible that the function name may end up being reported to Sentry. - -### Are worker threads supported? - -No. All instances of the profiler are scoped per thread In practice, this means that starting a transaction on thread A -and delegating work to thread B will only result in sample stacks being collected from thread A. That said, nothing -should prevent you from starting a transaction on thread B concurrently which will result in two independent profiles -being sent to the Sentry backend. We currently do not do any correlation between such transactions, but we would be open -to exploring the possibilities. Please file an issue if you have suggestions or specific use-cases in mind. - -### How much overhead will this profiler add? - -The profiler uses the kEagerLogging option by default which trades off fast calls to startProfiling for a small amount -of constant CPU overhead. If you are using kEagerLogging then the tradeoff is reversed and there will be a small CPU -overhead while the profiler is not running, but calls to startProfiling could be slow (in our tests, this varies by -environments and node versions, but could be in the order of a couple 100ms). +- [Report a bug](https://github.com/getsentry/sentry-javascript/issues/new/choose) +- [Contributing](https://github.com/getsentry/sentry-javascript/blob/develop/CONTRIBUTING.md) From 0e2e3ff4a30e96e71b5f83b8f8f5e3dbbfeb9834 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 23 Sep 2026 14:10:17 +0200 Subject: [PATCH 2/3] docs: Preserve profiling native build guidance in the README Co-Authored-By: GPT-6 --- packages/profiling-node/README.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/profiling-node/README.md b/packages/profiling-node/README.md index a379060dd908..6fc1c146208e 100644 --- a/packages/profiling-node/README.md +++ b/packages/profiling-node/README.md @@ -19,7 +19,31 @@ Profiling for Node.js applications. ## Building the package from source -The native bindings are maintained in the [Node CPU profiler repository](https://github.com/getsentry/sentry-javascript-profiling-node-binaries). +Profiling uses native bindings to interact with V8. These are provided by `@sentry/node-cpu-profiler`, which attempts +to build from source during installation if a compatible prebuilt binary cannot be loaded. + +Building requires Python and a C/C++ toolchain: `make` and a compiler on Linux, Xcode Command Line Tools on macOS, +or Visual Studio's C++ build tools on Windows. See the [node-gyp prerequisites](https://github.com/nodejs/node-gyp#installation) +for platform-specific requirements. + +To build the native package yourself, clone the [Node CPU profiler repository](https://github.com/getsentry/sentry-javascript-profiling-node-binaries) +and run the following commands from its root: + +```sh +yarn install --ignore-scripts +yarn build:lib +yarn build:bindings:configure +yarn build:bindings +``` + +The compiled native binary and JavaScript files are placed in that repository's `lib/` directory. +The native build scripts live in that repository, not in `packages/profiling-node`. + +## Prebuilt binaries + +Prebuilt binaries are distributed with `@sentry/node-cpu-profiler`. The +[native build workflow](https://github.com/getsentry/sentry-javascript-profiling-node-binaries/blob/main/.github/workflows/build.yml) +lists the platforms, architectures, and Node.js versions built by its CI. ## Support From 93b1b40012a00fb94c7d89025b4f09af98f62c01 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 23 Sep 2026 16:39:05 +0200 Subject: [PATCH 3/3] docs: Minimize changes to profiling build instructions Co-Authored-By: GPT-6 --- packages/profiling-node/README.md | 49 ++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/packages/profiling-node/README.md b/packages/profiling-node/README.md index 6fc1c146208e..f517467dd913 100644 --- a/packages/profiling-node/README.md +++ b/packages/profiling-node/README.md @@ -17,33 +17,48 @@ Profiling for Node.js applications. - [Getting started](https://docs.sentry.io/platforms/javascript/guides/node/profiling/) - [Configuration](https://docs.sentry.io/platforms/javascript/guides/node/profiling/#enabling-profiling) -## Building the package from source +### Building the package from source -Profiling uses native bindings to interact with V8. These are provided by `@sentry/node-cpu-profiler`, which attempts -to build from source during installation if a compatible prebuilt binary cannot be loaded. +Profiling uses native modules to interop with the v8 javascript engine which means that you may be required to build it +from source. The libraries required to successfully build the package from source are often the same libraries that are +already required to build any other package which uses native modules and if your codebase uses any of those modules, +there is a fairly good chance this will work out of the box. The required packages are python, make and g++. -Building requires Python and a C/C++ toolchain: `make` and a compiler on Linux, Xcode Command Line Tools on macOS, -or Visual Studio's C++ build tools on Windows. See the [node-gyp prerequisites](https://github.com/nodejs/node-gyp#installation) -for platform-specific requirements. +**Windows:** If you are building on windows, you may need to install Visual Studio's C++ build tools. -To build the native package yourself, clone the [Node CPU profiler repository](https://github.com/getsentry/sentry-javascript-profiling-node-binaries) -and run the following commands from its root: +**macOS:** Install Xcode Command Line Tools for the compiler and make. -```sh -yarn install --ignore-scripts -yarn build:lib +See the [node-gyp prerequisites](https://github.com/nodejs/node-gyp#installation) for supported Python versions and +platform-specific requirements. + +After you have installed the toolchain, you should be able to build the binaries from source. +The native bindings are maintained in the [Node CPU profiler repository](https://github.com/getsentry/sentry-javascript-profiling-node-binaries). +Clone that repository, install its dependencies with `yarn install --ignore-scripts`, and run the following from its root: + +```bash +# configure node-gyp using yarn yarn build:bindings:configure +# or using npm +npm run build:bindings:configure + +# compile the binaries using yarn yarn build:bindings +# or using npm +npm run build:bindings ``` -The compiled native binary and JavaScript files are placed in that repository's `lib/` directory. -The native build scripts live in that repository, not in `packages/profiling-node`. +After the binaries are built, you should see them inside that repository's lib folder. + +### Prebuilt binaries + +We currently ship prebuilt binaries for a few of the most common platforms and node versions. -## Prebuilt binaries +- macOS x64 +- Linux ARM64 (musl) +- Linux x64 (glibc) +- Windows x64 -Prebuilt binaries are distributed with `@sentry/node-cpu-profiler`. The -[native build workflow](https://github.com/getsentry/sentry-javascript-profiling-node-binaries/blob/main/.github/workflows/build.yml) -lists the platforms, architectures, and Node.js versions built by its CI. +For a more detailed list, see the `job_compile` job in the [native build workflow](https://github.com/getsentry/sentry-javascript-profiling-node-binaries/blob/main/.github/workflows/build.yml). ## Support