feat(web): enable Sentry node and browser profiling - #1431

Merged
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling
Jul 10, 2026
Merged

feat(web): enable Sentry node and browser profiling#1431
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Enables Sentry profiling in the web app, on both the server and the browser.

Changes

  • Added @sentry/profiling-node to packages/web.
  • sentry.server.config.ts: registered nodeProfilingIntegration().
  • instrumentation-client.ts: registered Sentry.browserProfilingIntegration().
  • Both set profileSessionSampleRate: 1.0 and profileLifecycle: 'trace', so a profiler runs only while a sampled root span is active rather than continuously.
  • next.config.mjs: added a Document-Policy: js-profiling response header, which browser profiling requires in order to opt the document into the JS Self-Profiling API.

Notes

Version pinning.@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs, rather than the latest 10.64.0. It depends on @sentry/core and @sentry/node at exact versions, so a newer minor would install a second copy of the SDK alongside the one @sentry/nextjs pulls in, and the profiler would register against a different global carrier and silently emit nothing. Verified the tree still resolves to a single @sentry/core@10.40.0. Moving to 10.64.0 would need a coordinated bump of @sentry/nextjs (web) and @sentry/node + @sentry/profiling-node (backend) together.

No serverExternalPackages entry needed.@sentry/profiling-node loads a native .node addon through a require() whose path is computed at runtime, which normally means it has to be marked external. Next.js already ships it in its built-in external list (next/dist/lib/server-external-packages.jsonc), so no config is required. Confirmed by building with and without an explicit entry: instrumentation.js hashed identically and the file trace was unchanged.

browserTracingIntegration is not listed explicitly.@sentry/nextjs pushes its own App Router-aware version into the default integrations, and passing integrations as an array merges with the defaults rather than replacing them. Listing the generic one would shadow it.

Verification

  • Ran the node profiler against a capturing transport: emits ["profile_chunk", "transaction"] for a sampled span, confirming the native addon loads and profileLifecycle: 'trace' behaves as configured. With the option omitted (SDK default 'manual') only ["transaction"] is emitted.
  • next build passes, and .next/standalone traces the profiler plus all 28 prebuilt binaries, including the two linux-*-musl-137 ones the node:24-alpine runtime image needs.
  • Typecheck and lint clean on the touched files.

Follow-up worth considering

Server-side profileSessionSampleRate: 1.0 profiles every process. app.sourcebot.dev runs a single web replica whose event loop already saturates under /browse render bursts, so it may be worth dialing this down on the server. Browser profiling is client-side and costs nothing there.

🤖 Generated with Claude Code


Note

Medium Risk
Server profiling uses a native addon at 100% session sampling alongside full trace sampling, which can add CPU/overhead on hot paths; changes are observability-only, not auth or data handling.

Overview
Turns on Sentry performance profiling for the Next.js web app on both the server and client, tied to sampled traces instead of always-on profiling.

Server init registers nodeProfilingIntegration() (new @sentry/profiling-node, version-matched to @sentry/nextjs) with profileSessionSampleRate: 1.0 and profileLifecycle: 'trace'. Client init adds browserProfilingIntegration() with the same profiling options. debug: false is dropped from both inits.

next.config.mjs adds a global Document-Policy: js-profiling header so browser profiling can use the JS Self-Profiling API.

Reviewed by Cursor Bugbot for commit a992a80. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Added enhanced performance monitoring for web sessions.
    • Enabled browser and server-side profiling to provide deeper insight into application performance.
    • Expanded monitoring coverage across all application routes for more consistent diagnostics.

Adds @sentry/profiling-node and wires up profiling on both the server
(nodeProfilingIntegration) and the browser (browserProfilingIntegration).
Both use profileLifecycle: 'trace', so a profiler only runs while a sampled
root span is active rather than continuously.
Browser profiling additionally requires the document to opt into the JS
Self-Profiling API, so a `Document-Policy: js-profiling` response header is
added alongside the existing security headers.
@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs. It
depends on @sentry/core and @sentry/node at exact versions, so a newer minor
would pull a second copy of the SDK into the tree and the profiler would
register against a different global.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

This comment has been minimized.

brendan-kellamand others added 2 commits July 9, 2026 21:59
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0e44652e-025e-4883-b6c2-8a62f7475d65

📥 Commits

Reviewing files that changed from the base of the PR and between 139b238 and a992a80.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (4)
  • packages/web/next.config.mjs
  • packages/web/package.json
  • packages/web/src/instrumentation-client.ts
  • packages/web/src/sentry.server.config.ts

Walkthrough

Changes

Sentry profiling

Layer / File(s)Summary
Configure client and server profiling
packages/web/package.json, packages/web/src/instrumentation-client.ts, packages/web/src/sentry.server.config.ts, packages/web/next.config.mjs
Adds browser and Node Sentry profiling integrations, profiling sampling and lifecycle settings, the Node profiling dependency, and the Document-Policy: js-profiling header for all routes.

Estimated code review effort: 2 (Simple) | ~10 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan-kellam/sentry-profiling

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@brendan-kellam
brendan-kellam merged commit 4aec5d9 into mainJul 10, 2026
10 checks passed
@brendan-kellam
brendan-kellam deleted the brendan-kellam/sentry-profiling branch July 10, 2026 05:01
@github-actionsgithub-actionsBot mentioned this pull request Jul 10, 2026
@github-actions

github-actionsBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

License Audit

⚠️Status: PASS

MetricCount
Total packages2222
Resolved (non-standard)17
Unresolved0
Strong copyleft0
Weak copyleft38

Weak Copyleft Packages (informational)

PackageVersionLicense
@img/sharp-libvips-darwin-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.0.5LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-ppc641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-riscv641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.2.4LGPL-3.0-or-later
@img/sharp-wasm320.33.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-wasm320.34.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-win32-arm640.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.34.5Apache-2.0 AND LGPL-3.0-or-later
axe-core4.10.3MPL-2.0
lightningcss1.32.0MPL-2.0
lightningcss-android-arm641.32.0MPL-2.0
lightningcss-darwin-arm641.32.0MPL-2.0
lightningcss-darwin-x641.32.0MPL-2.0
lightningcss-freebsd-x641.32.0MPL-2.0
lightningcss-linux-arm-gnueabihf1.32.0MPL-2.0
lightningcss-linux-arm64-gnu1.32.0MPL-2.0
lightningcss-linux-arm64-musl1.32.0MPL-2.0
lightningcss-linux-x64-gnu1.32.0MPL-2.0
lightningcss-linux-x64-musl1.32.0MPL-2.0
lightningcss-win32-arm64-msvc1.32.0MPL-2.0
lightningcss-win32-x64-msvc1.32.0MPL-2.0
Resolved Packages (17)
PackageVersionOriginalResolvedSource
codemirror-lang-elixir4.0.0UNKNOWNApache-2.0GitHub repo (livebook-dev/codemirror-lang-elixir) LICENSE via GitHub license API
khroma2.1.0UNKNOWNMITGitHub repo (fabiospampinato/khroma) LICENSE via GitHub license API
lezer-elixir1.1.2UNKNOWNApache-2.0GitHub repo (livebook-dev/lezer-elixir) LICENSE via GitHub license API
map-stream0.1.0UNKNOWNMITGitHub repo (dominictarr/map-stream) LICENSE via GitHub license API
memorystream0.3.1UNKNOWNMITextracted from 'licenses' object [{type:MIT}] in npm registry metadata; confirmed via GitHub repo LICENSE
valid-url1.0.9UNKNOWNMITGitHub repo (ogt/valid-url) LICENSE file text (MIT license)
posthog-js1.369.0SEE LICENSE IN LICENSEApache-2.0GitHub repo (PostHog/posthog-js) LICENSE file text (Apache License 2.0)
pause-stream0.0.11["MIT","Apache2"]MIT OR Apache-2.0GitHub repo (dominictarr/pause-stream) LICENSE file (dual licensed MIT and Apache 2)
@sentry/cli2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-darwin2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brendan-kellam
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(web): enable Sentry node and browser profiling - #1431

Merged
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling
Jul 10, 2026
Merged

feat(web): enable Sentry node and browser profiling#1431
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Enables Sentry profiling in the web app, on both the server and the browser.

Changes

  • Added @sentry/profiling-node to packages/web.
  • sentry.server.config.ts: registered nodeProfilingIntegration().
  • instrumentation-client.ts: registered Sentry.browserProfilingIntegration().
  • Both set profileSessionSampleRate: 1.0 and profileLifecycle: 'trace', so a profiler runs only while a sampled root span is active rather than continuously.
  • next.config.mjs: added a Document-Policy: js-profiling response header, which browser profiling requires in order to opt the document into the JS Self-Profiling API.

Notes

Version pinning.@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs, rather than the latest 10.64.0. It depends on @sentry/core and @sentry/node at exact versions, so a newer minor would install a second copy of the SDK alongside the one @sentry/nextjs pulls in, and the profiler would register against a different global carrier and silently emit nothing. Verified the tree still resolves to a single @sentry/core@10.40.0. Moving to 10.64.0 would need a coordinated bump of @sentry/nextjs (web) and @sentry/node + @sentry/profiling-node (backend) together.

No serverExternalPackages entry needed.@sentry/profiling-node loads a native .node addon through a require() whose path is computed at runtime, which normally means it has to be marked external. Next.js already ships it in its built-in external list (next/dist/lib/server-external-packages.jsonc), so no config is required. Confirmed by building with and without an explicit entry: instrumentation.js hashed identically and the file trace was unchanged.

browserTracingIntegration is not listed explicitly.@sentry/nextjs pushes its own App Router-aware version into the default integrations, and passing integrations as an array merges with the defaults rather than replacing them. Listing the generic one would shadow it.

Verification

  • Ran the node profiler against a capturing transport: emits ["profile_chunk", "transaction"] for a sampled span, confirming the native addon loads and profileLifecycle: 'trace' behaves as configured. With the option omitted (SDK default 'manual') only ["transaction"] is emitted.
  • next build passes, and .next/standalone traces the profiler plus all 28 prebuilt binaries, including the two linux-*-musl-137 ones the node:24-alpine runtime image needs.
  • Typecheck and lint clean on the touched files.

Follow-up worth considering

Server-side profileSessionSampleRate: 1.0 profiles every process. app.sourcebot.dev runs a single web replica whose event loop already saturates under /browse render bursts, so it may be worth dialing this down on the server. Browser profiling is client-side and costs nothing there.

🤖 Generated with Claude Code


Note

Medium Risk
Server profiling uses a native addon at 100% session sampling alongside full trace sampling, which can add CPU/overhead on hot paths; changes are observability-only, not auth or data handling.

Overview
Turns on Sentry performance profiling for the Next.js web app on both the server and client, tied to sampled traces instead of always-on profiling.

Server init registers nodeProfilingIntegration() (new @sentry/profiling-node, version-matched to @sentry/nextjs) with profileSessionSampleRate: 1.0 and profileLifecycle: 'trace'. Client init adds browserProfilingIntegration() with the same profiling options. debug: false is dropped from both inits.

next.config.mjs adds a global Document-Policy: js-profiling header so browser profiling can use the JS Self-Profiling API.

Reviewed by Cursor Bugbot for commit a992a80. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Added enhanced performance monitoring for web sessions.
    • Enabled browser and server-side profiling to provide deeper insight into application performance.
    • Expanded monitoring coverage across all application routes for more consistent diagnostics.

Adds @sentry/profiling-node and wires up profiling on both the server
(nodeProfilingIntegration) and the browser (browserProfilingIntegration).
Both use profileLifecycle: 'trace', so a profiler only runs while a sampled
root span is active rather than continuously.
Browser profiling additionally requires the document to opt into the JS
Self-Profiling API, so a `Document-Policy: js-profiling` response header is
added alongside the existing security headers.
@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs. It
depends on @sentry/core and @sentry/node at exact versions, so a newer minor
would pull a second copy of the SDK into the tree and the profiler would
register against a different global.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

This comment has been minimized.

brendan-kellamand others added 2 commits July 9, 2026 21:59
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0e44652e-025e-4883-b6c2-8a62f7475d65

📥 Commits

Reviewing files that changed from the base of the PR and between 139b238 and a992a80.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (4)
  • packages/web/next.config.mjs
  • packages/web/package.json
  • packages/web/src/instrumentation-client.ts
  • packages/web/src/sentry.server.config.ts

Walkthrough

Changes

Sentry profiling

Layer / File(s)Summary
Configure client and server profiling
packages/web/package.json, packages/web/src/instrumentation-client.ts, packages/web/src/sentry.server.config.ts, packages/web/next.config.mjs
Adds browser and Node Sentry profiling integrations, profiling sampling and lifecycle settings, the Node profiling dependency, and the Document-Policy: js-profiling header for all routes.

Estimated code review effort: 2 (Simple) | ~10 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan-kellam/sentry-profiling

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@brendan-kellam
brendan-kellam merged commit 4aec5d9 into mainJul 10, 2026
10 checks passed
@brendan-kellam
brendan-kellam deleted the brendan-kellam/sentry-profiling branch July 10, 2026 05:01
@github-actionsgithub-actionsBot mentioned this pull request Jul 10, 2026
@github-actions

github-actionsBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

License Audit

⚠️Status: PASS

MetricCount
Total packages2222
Resolved (non-standard)17
Unresolved0
Strong copyleft0
Weak copyleft38

Weak Copyleft Packages (informational)

PackageVersionLicense
@img/sharp-libvips-darwin-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.0.5LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-ppc641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-riscv641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.2.4LGPL-3.0-or-later
@img/sharp-wasm320.33.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-wasm320.34.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-win32-arm640.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.34.5Apache-2.0 AND LGPL-3.0-or-later
axe-core4.10.3MPL-2.0
lightningcss1.32.0MPL-2.0
lightningcss-android-arm641.32.0MPL-2.0
lightningcss-darwin-arm641.32.0MPL-2.0
lightningcss-darwin-x641.32.0MPL-2.0
lightningcss-freebsd-x641.32.0MPL-2.0
lightningcss-linux-arm-gnueabihf1.32.0MPL-2.0
lightningcss-linux-arm64-gnu1.32.0MPL-2.0
lightningcss-linux-arm64-musl1.32.0MPL-2.0
lightningcss-linux-x64-gnu1.32.0MPL-2.0
lightningcss-linux-x64-musl1.32.0MPL-2.0
lightningcss-win32-arm64-msvc1.32.0MPL-2.0
lightningcss-win32-x64-msvc1.32.0MPL-2.0
Resolved Packages (17)
PackageVersionOriginalResolvedSource
codemirror-lang-elixir4.0.0UNKNOWNApache-2.0GitHub repo (livebook-dev/codemirror-lang-elixir) LICENSE via GitHub license API
khroma2.1.0UNKNOWNMITGitHub repo (fabiospampinato/khroma) LICENSE via GitHub license API
lezer-elixir1.1.2UNKNOWNApache-2.0GitHub repo (livebook-dev/lezer-elixir) LICENSE via GitHub license API
map-stream0.1.0UNKNOWNMITGitHub repo (dominictarr/map-stream) LICENSE via GitHub license API
memorystream0.3.1UNKNOWNMITextracted from 'licenses' object [{type:MIT}] in npm registry metadata; confirmed via GitHub repo LICENSE
valid-url1.0.9UNKNOWNMITGitHub repo (ogt/valid-url) LICENSE file text (MIT license)
posthog-js1.369.0SEE LICENSE IN LICENSEApache-2.0GitHub repo (PostHog/posthog-js) LICENSE file text (Apache License 2.0)
pause-stream0.0.11["MIT","Apache2"]MIT OR Apache-2.0GitHub repo (dominictarr/pause-stream) LICENSE file (dual licensed MIT and Apache 2)
@sentry/cli2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-darwin2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brendan-kellam
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(web): enable Sentry node and browser profiling - #1431

Merged
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling
Jul 10, 2026
Merged

feat(web): enable Sentry node and browser profiling#1431
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Enables Sentry profiling in the web app, on both the server and the browser.

Changes

  • Added @sentry/profiling-node to packages/web.
  • sentry.server.config.ts: registered nodeProfilingIntegration().
  • instrumentation-client.ts: registered Sentry.browserProfilingIntegration().
  • Both set profileSessionSampleRate: 1.0 and profileLifecycle: 'trace', so a profiler runs only while a sampled root span is active rather than continuously.
  • next.config.mjs: added a Document-Policy: js-profiling response header, which browser profiling requires in order to opt the document into the JS Self-Profiling API.

Notes

Version pinning.@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs, rather than the latest 10.64.0. It depends on @sentry/core and @sentry/node at exact versions, so a newer minor would install a second copy of the SDK alongside the one @sentry/nextjs pulls in, and the profiler would register against a different global carrier and silently emit nothing. Verified the tree still resolves to a single @sentry/core@10.40.0. Moving to 10.64.0 would need a coordinated bump of @sentry/nextjs (web) and @sentry/node + @sentry/profiling-node (backend) together.

No serverExternalPackages entry needed.@sentry/profiling-node loads a native .node addon through a require() whose path is computed at runtime, which normally means it has to be marked external. Next.js already ships it in its built-in external list (next/dist/lib/server-external-packages.jsonc), so no config is required. Confirmed by building with and without an explicit entry: instrumentation.js hashed identically and the file trace was unchanged.

browserTracingIntegration is not listed explicitly.@sentry/nextjs pushes its own App Router-aware version into the default integrations, and passing integrations as an array merges with the defaults rather than replacing them. Listing the generic one would shadow it.

Verification

  • Ran the node profiler against a capturing transport: emits ["profile_chunk", "transaction"] for a sampled span, confirming the native addon loads and profileLifecycle: 'trace' behaves as configured. With the option omitted (SDK default 'manual') only ["transaction"] is emitted.
  • next build passes, and .next/standalone traces the profiler plus all 28 prebuilt binaries, including the two linux-*-musl-137 ones the node:24-alpine runtime image needs.
  • Typecheck and lint clean on the touched files.

Follow-up worth considering

Server-side profileSessionSampleRate: 1.0 profiles every process. app.sourcebot.dev runs a single web replica whose event loop already saturates under /browse render bursts, so it may be worth dialing this down on the server. Browser profiling is client-side and costs nothing there.

🤖 Generated with Claude Code


Note

Medium Risk
Server profiling uses a native addon at 100% session sampling alongside full trace sampling, which can add CPU/overhead on hot paths; changes are observability-only, not auth or data handling.

Overview
Turns on Sentry performance profiling for the Next.js web app on both the server and client, tied to sampled traces instead of always-on profiling.

Server init registers nodeProfilingIntegration() (new @sentry/profiling-node, version-matched to @sentry/nextjs) with profileSessionSampleRate: 1.0 and profileLifecycle: 'trace'. Client init adds browserProfilingIntegration() with the same profiling options. debug: false is dropped from both inits.

next.config.mjs adds a global Document-Policy: js-profiling header so browser profiling can use the JS Self-Profiling API.

Reviewed by Cursor Bugbot for commit a992a80. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Added enhanced performance monitoring for web sessions.
    • Enabled browser and server-side profiling to provide deeper insight into application performance.
    • Expanded monitoring coverage across all application routes for more consistent diagnostics.

Adds @sentry/profiling-node and wires up profiling on both the server
(nodeProfilingIntegration) and the browser (browserProfilingIntegration).
Both use profileLifecycle: 'trace', so a profiler only runs while a sampled
root span is active rather than continuously.
Browser profiling additionally requires the document to opt into the JS
Self-Profiling API, so a `Document-Policy: js-profiling` response header is
added alongside the existing security headers.
@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs. It
depends on @sentry/core and @sentry/node at exact versions, so a newer minor
would pull a second copy of the SDK into the tree and the profiler would
register against a different global.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

This comment has been minimized.

brendan-kellamand others added 2 commits July 9, 2026 21:59
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0e44652e-025e-4883-b6c2-8a62f7475d65

📥 Commits

Reviewing files that changed from the base of the PR and between 139b238 and a992a80.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (4)
  • packages/web/next.config.mjs
  • packages/web/package.json
  • packages/web/src/instrumentation-client.ts
  • packages/web/src/sentry.server.config.ts

Walkthrough

Changes

Sentry profiling

Layer / File(s)Summary
Configure client and server profiling
packages/web/package.json, packages/web/src/instrumentation-client.ts, packages/web/src/sentry.server.config.ts, packages/web/next.config.mjs
Adds browser and Node Sentry profiling integrations, profiling sampling and lifecycle settings, the Node profiling dependency, and the Document-Policy: js-profiling header for all routes.

Estimated code review effort: 2 (Simple) | ~10 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan-kellam/sentry-profiling

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@brendan-kellam
brendan-kellam merged commit 4aec5d9 into mainJul 10, 2026
10 checks passed
@brendan-kellam
brendan-kellam deleted the brendan-kellam/sentry-profiling branch July 10, 2026 05:01
@github-actionsgithub-actionsBot mentioned this pull request Jul 10, 2026
@github-actions

github-actionsBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

License Audit

⚠️Status: PASS

MetricCount
Total packages2222
Resolved (non-standard)17
Unresolved0
Strong copyleft0
Weak copyleft38

Weak Copyleft Packages (informational)

PackageVersionLicense
@img/sharp-libvips-darwin-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.0.5LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-ppc641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-riscv641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.2.4LGPL-3.0-or-later
@img/sharp-wasm320.33.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-wasm320.34.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-win32-arm640.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.34.5Apache-2.0 AND LGPL-3.0-or-later
axe-core4.10.3MPL-2.0
lightningcss1.32.0MPL-2.0
lightningcss-android-arm641.32.0MPL-2.0
lightningcss-darwin-arm641.32.0MPL-2.0
lightningcss-darwin-x641.32.0MPL-2.0
lightningcss-freebsd-x641.32.0MPL-2.0
lightningcss-linux-arm-gnueabihf1.32.0MPL-2.0
lightningcss-linux-arm64-gnu1.32.0MPL-2.0
lightningcss-linux-arm64-musl1.32.0MPL-2.0
lightningcss-linux-x64-gnu1.32.0MPL-2.0
lightningcss-linux-x64-musl1.32.0MPL-2.0
lightningcss-win32-arm64-msvc1.32.0MPL-2.0
lightningcss-win32-x64-msvc1.32.0MPL-2.0
Resolved Packages (17)
PackageVersionOriginalResolvedSource
codemirror-lang-elixir4.0.0UNKNOWNApache-2.0GitHub repo (livebook-dev/codemirror-lang-elixir) LICENSE via GitHub license API
khroma2.1.0UNKNOWNMITGitHub repo (fabiospampinato/khroma) LICENSE via GitHub license API
lezer-elixir1.1.2UNKNOWNApache-2.0GitHub repo (livebook-dev/lezer-elixir) LICENSE via GitHub license API
map-stream0.1.0UNKNOWNMITGitHub repo (dominictarr/map-stream) LICENSE via GitHub license API
memorystream0.3.1UNKNOWNMITextracted from 'licenses' object [{type:MIT}] in npm registry metadata; confirmed via GitHub repo LICENSE
valid-url1.0.9UNKNOWNMITGitHub repo (ogt/valid-url) LICENSE file text (MIT license)
posthog-js1.369.0SEE LICENSE IN LICENSEApache-2.0GitHub repo (PostHog/posthog-js) LICENSE file text (Apache License 2.0)
pause-stream0.0.11["MIT","Apache2"]MIT OR Apache-2.0GitHub repo (dominictarr/pause-stream) LICENSE file (dual licensed MIT and Apache 2)
@sentry/cli2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-darwin2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brendan-kellam
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(web): enable Sentry node and browser profiling - #1431

Merged
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling
Jul 10, 2026
Merged

feat(web): enable Sentry node and browser profiling#1431
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Enables Sentry profiling in the web app, on both the server and the browser.

Changes

  • Added @sentry/profiling-node to packages/web.
  • sentry.server.config.ts: registered nodeProfilingIntegration().
  • instrumentation-client.ts: registered Sentry.browserProfilingIntegration().
  • Both set profileSessionSampleRate: 1.0 and profileLifecycle: 'trace', so a profiler runs only while a sampled root span is active rather than continuously.
  • next.config.mjs: added a Document-Policy: js-profiling response header, which browser profiling requires in order to opt the document into the JS Self-Profiling API.

Notes

Version pinning.@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs, rather than the latest 10.64.0. It depends on @sentry/core and @sentry/node at exact versions, so a newer minor would install a second copy of the SDK alongside the one @sentry/nextjs pulls in, and the profiler would register against a different global carrier and silently emit nothing. Verified the tree still resolves to a single @sentry/core@10.40.0. Moving to 10.64.0 would need a coordinated bump of @sentry/nextjs (web) and @sentry/node + @sentry/profiling-node (backend) together.

No serverExternalPackages entry needed.@sentry/profiling-node loads a native .node addon through a require() whose path is computed at runtime, which normally means it has to be marked external. Next.js already ships it in its built-in external list (next/dist/lib/server-external-packages.jsonc), so no config is required. Confirmed by building with and without an explicit entry: instrumentation.js hashed identically and the file trace was unchanged.

browserTracingIntegration is not listed explicitly.@sentry/nextjs pushes its own App Router-aware version into the default integrations, and passing integrations as an array merges with the defaults rather than replacing them. Listing the generic one would shadow it.

Verification

  • Ran the node profiler against a capturing transport: emits ["profile_chunk", "transaction"] for a sampled span, confirming the native addon loads and profileLifecycle: 'trace' behaves as configured. With the option omitted (SDK default 'manual') only ["transaction"] is emitted.
  • next build passes, and .next/standalone traces the profiler plus all 28 prebuilt binaries, including the two linux-*-musl-137 ones the node:24-alpine runtime image needs.
  • Typecheck and lint clean on the touched files.

Follow-up worth considering

Server-side profileSessionSampleRate: 1.0 profiles every process. app.sourcebot.dev runs a single web replica whose event loop already saturates under /browse render bursts, so it may be worth dialing this down on the server. Browser profiling is client-side and costs nothing there.

🤖 Generated with Claude Code


Note

Medium Risk
Server profiling uses a native addon at 100% session sampling alongside full trace sampling, which can add CPU/overhead on hot paths; changes are observability-only, not auth or data handling.

Overview
Turns on Sentry performance profiling for the Next.js web app on both the server and client, tied to sampled traces instead of always-on profiling.

Server init registers nodeProfilingIntegration() (new @sentry/profiling-node, version-matched to @sentry/nextjs) with profileSessionSampleRate: 1.0 and profileLifecycle: 'trace'. Client init adds browserProfilingIntegration() with the same profiling options. debug: false is dropped from both inits.

next.config.mjs adds a global Document-Policy: js-profiling header so browser profiling can use the JS Self-Profiling API.

Reviewed by Cursor Bugbot for commit a992a80. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Added enhanced performance monitoring for web sessions.
    • Enabled browser and server-side profiling to provide deeper insight into application performance.
    • Expanded monitoring coverage across all application routes for more consistent diagnostics.

Adds @sentry/profiling-node and wires up profiling on both the server
(nodeProfilingIntegration) and the browser (browserProfilingIntegration).
Both use profileLifecycle: 'trace', so a profiler only runs while a sampled
root span is active rather than continuously.
Browser profiling additionally requires the document to opt into the JS
Self-Profiling API, so a `Document-Policy: js-profiling` response header is
added alongside the existing security headers.
@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs. It
depends on @sentry/core and @sentry/node at exact versions, so a newer minor
would pull a second copy of the SDK into the tree and the profiler would
register against a different global.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

This comment has been minimized.

brendan-kellamand others added 2 commits July 9, 2026 21:59
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0e44652e-025e-4883-b6c2-8a62f7475d65

📥 Commits

Reviewing files that changed from the base of the PR and between 139b238 and a992a80.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (4)
  • packages/web/next.config.mjs
  • packages/web/package.json
  • packages/web/src/instrumentation-client.ts
  • packages/web/src/sentry.server.config.ts

Walkthrough

Changes

Sentry profiling

Layer / File(s)Summary
Configure client and server profiling
packages/web/package.json, packages/web/src/instrumentation-client.ts, packages/web/src/sentry.server.config.ts, packages/web/next.config.mjs
Adds browser and Node Sentry profiling integrations, profiling sampling and lifecycle settings, the Node profiling dependency, and the Document-Policy: js-profiling header for all routes.

Estimated code review effort: 2 (Simple) | ~10 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan-kellam/sentry-profiling

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@brendan-kellam
brendan-kellam merged commit 4aec5d9 into mainJul 10, 2026
10 checks passed
@brendan-kellam
brendan-kellam deleted the brendan-kellam/sentry-profiling branch July 10, 2026 05:01
@github-actionsgithub-actionsBot mentioned this pull request Jul 10, 2026
@github-actions

github-actionsBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

License Audit

⚠️Status: PASS

MetricCount
Total packages2222
Resolved (non-standard)17
Unresolved0
Strong copyleft0
Weak copyleft38

Weak Copyleft Packages (informational)

PackageVersionLicense
@img/sharp-libvips-darwin-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.0.5LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-ppc641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-riscv641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.2.4LGPL-3.0-or-later
@img/sharp-wasm320.33.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-wasm320.34.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-win32-arm640.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.34.5Apache-2.0 AND LGPL-3.0-or-later
axe-core4.10.3MPL-2.0
lightningcss1.32.0MPL-2.0
lightningcss-android-arm641.32.0MPL-2.0
lightningcss-darwin-arm641.32.0MPL-2.0
lightningcss-darwin-x641.32.0MPL-2.0
lightningcss-freebsd-x641.32.0MPL-2.0
lightningcss-linux-arm-gnueabihf1.32.0MPL-2.0
lightningcss-linux-arm64-gnu1.32.0MPL-2.0
lightningcss-linux-arm64-musl1.32.0MPL-2.0
lightningcss-linux-x64-gnu1.32.0MPL-2.0
lightningcss-linux-x64-musl1.32.0MPL-2.0
lightningcss-win32-arm64-msvc1.32.0MPL-2.0
lightningcss-win32-x64-msvc1.32.0MPL-2.0
Resolved Packages (17)
PackageVersionOriginalResolvedSource
codemirror-lang-elixir4.0.0UNKNOWNApache-2.0GitHub repo (livebook-dev/codemirror-lang-elixir) LICENSE via GitHub license API
khroma2.1.0UNKNOWNMITGitHub repo (fabiospampinato/khroma) LICENSE via GitHub license API
lezer-elixir1.1.2UNKNOWNApache-2.0GitHub repo (livebook-dev/lezer-elixir) LICENSE via GitHub license API
map-stream0.1.0UNKNOWNMITGitHub repo (dominictarr/map-stream) LICENSE via GitHub license API
memorystream0.3.1UNKNOWNMITextracted from 'licenses' object [{type:MIT}] in npm registry metadata; confirmed via GitHub repo LICENSE
valid-url1.0.9UNKNOWNMITGitHub repo (ogt/valid-url) LICENSE file text (MIT license)
posthog-js1.369.0SEE LICENSE IN LICENSEApache-2.0GitHub repo (PostHog/posthog-js) LICENSE file text (Apache License 2.0)
pause-stream0.0.11["MIT","Apache2"]MIT OR Apache-2.0GitHub repo (dominictarr/pause-stream) LICENSE file (dual licensed MIT and Apache 2)
@sentry/cli2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-darwin2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brendan-kellam
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(web): enable Sentry node and browser profiling - #1431

Merged
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling
Jul 10, 2026
Merged

feat(web): enable Sentry node and browser profiling#1431
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Enables Sentry profiling in the web app, on both the server and the browser.

Changes

  • Added @sentry/profiling-node to packages/web.
  • sentry.server.config.ts: registered nodeProfilingIntegration().
  • instrumentation-client.ts: registered Sentry.browserProfilingIntegration().
  • Both set profileSessionSampleRate: 1.0 and profileLifecycle: 'trace', so a profiler runs only while a sampled root span is active rather than continuously.
  • next.config.mjs: added a Document-Policy: js-profiling response header, which browser profiling requires in order to opt the document into the JS Self-Profiling API.

Notes

Version pinning.@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs, rather than the latest 10.64.0. It depends on @sentry/core and @sentry/node at exact versions, so a newer minor would install a second copy of the SDK alongside the one @sentry/nextjs pulls in, and the profiler would register against a different global carrier and silently emit nothing. Verified the tree still resolves to a single @sentry/core@10.40.0. Moving to 10.64.0 would need a coordinated bump of @sentry/nextjs (web) and @sentry/node + @sentry/profiling-node (backend) together.

No serverExternalPackages entry needed.@sentry/profiling-node loads a native .node addon through a require() whose path is computed at runtime, which normally means it has to be marked external. Next.js already ships it in its built-in external list (next/dist/lib/server-external-packages.jsonc), so no config is required. Confirmed by building with and without an explicit entry: instrumentation.js hashed identically and the file trace was unchanged.

browserTracingIntegration is not listed explicitly.@sentry/nextjs pushes its own App Router-aware version into the default integrations, and passing integrations as an array merges with the defaults rather than replacing them. Listing the generic one would shadow it.

Verification

  • Ran the node profiler against a capturing transport: emits ["profile_chunk", "transaction"] for a sampled span, confirming the native addon loads and profileLifecycle: 'trace' behaves as configured. With the option omitted (SDK default 'manual') only ["transaction"] is emitted.
  • next build passes, and .next/standalone traces the profiler plus all 28 prebuilt binaries, including the two linux-*-musl-137 ones the node:24-alpine runtime image needs.
  • Typecheck and lint clean on the touched files.

Follow-up worth considering

Server-side profileSessionSampleRate: 1.0 profiles every process. app.sourcebot.dev runs a single web replica whose event loop already saturates under /browse render bursts, so it may be worth dialing this down on the server. Browser profiling is client-side and costs nothing there.

🤖 Generated with Claude Code


Note

Medium Risk
Server profiling uses a native addon at 100% session sampling alongside full trace sampling, which can add CPU/overhead on hot paths; changes are observability-only, not auth or data handling.

Overview
Turns on Sentry performance profiling for the Next.js web app on both the server and client, tied to sampled traces instead of always-on profiling.

Server init registers nodeProfilingIntegration() (new @sentry/profiling-node, version-matched to @sentry/nextjs) with profileSessionSampleRate: 1.0 and profileLifecycle: 'trace'. Client init adds browserProfilingIntegration() with the same profiling options. debug: false is dropped from both inits.

next.config.mjs adds a global Document-Policy: js-profiling header so browser profiling can use the JS Self-Profiling API.

Reviewed by Cursor Bugbot for commit a992a80. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Added enhanced performance monitoring for web sessions.
    • Enabled browser and server-side profiling to provide deeper insight into application performance.
    • Expanded monitoring coverage across all application routes for more consistent diagnostics.

Adds @sentry/profiling-node and wires up profiling on both the server
(nodeProfilingIntegration) and the browser (browserProfilingIntegration).
Both use profileLifecycle: 'trace', so a profiler only runs while a sampled
root span is active rather than continuously.
Browser profiling additionally requires the document to opt into the JS
Self-Profiling API, so a `Document-Policy: js-profiling` response header is
added alongside the existing security headers.
@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs. It
depends on @sentry/core and @sentry/node at exact versions, so a newer minor
would pull a second copy of the SDK into the tree and the profiler would
register against a different global.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

This comment has been minimized.

brendan-kellamand others added 2 commits July 9, 2026 21:59
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0e44652e-025e-4883-b6c2-8a62f7475d65

📥 Commits

Reviewing files that changed from the base of the PR and between 139b238 and a992a80.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (4)
  • packages/web/next.config.mjs
  • packages/web/package.json
  • packages/web/src/instrumentation-client.ts
  • packages/web/src/sentry.server.config.ts

Walkthrough

Changes

Sentry profiling

Layer / File(s)Summary
Configure client and server profiling
packages/web/package.json, packages/web/src/instrumentation-client.ts, packages/web/src/sentry.server.config.ts, packages/web/next.config.mjs
Adds browser and Node Sentry profiling integrations, profiling sampling and lifecycle settings, the Node profiling dependency, and the Document-Policy: js-profiling header for all routes.

Estimated code review effort: 2 (Simple) | ~10 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan-kellam/sentry-profiling

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@brendan-kellam
brendan-kellam merged commit 4aec5d9 into mainJul 10, 2026
10 checks passed
@brendan-kellam
brendan-kellam deleted the brendan-kellam/sentry-profiling branch July 10, 2026 05:01
@github-actionsgithub-actionsBot mentioned this pull request Jul 10, 2026
@github-actions

github-actionsBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

License Audit

⚠️Status: PASS

MetricCount
Total packages2222
Resolved (non-standard)17
Unresolved0
Strong copyleft0
Weak copyleft38

Weak Copyleft Packages (informational)

PackageVersionLicense
@img/sharp-libvips-darwin-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.0.5LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-ppc641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-riscv641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.2.4LGPL-3.0-or-later
@img/sharp-wasm320.33.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-wasm320.34.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-win32-arm640.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.34.5Apache-2.0 AND LGPL-3.0-or-later
axe-core4.10.3MPL-2.0
lightningcss1.32.0MPL-2.0
lightningcss-android-arm641.32.0MPL-2.0
lightningcss-darwin-arm641.32.0MPL-2.0
lightningcss-darwin-x641.32.0MPL-2.0
lightningcss-freebsd-x641.32.0MPL-2.0
lightningcss-linux-arm-gnueabihf1.32.0MPL-2.0
lightningcss-linux-arm64-gnu1.32.0MPL-2.0
lightningcss-linux-arm64-musl1.32.0MPL-2.0
lightningcss-linux-x64-gnu1.32.0MPL-2.0
lightningcss-linux-x64-musl1.32.0MPL-2.0
lightningcss-win32-arm64-msvc1.32.0MPL-2.0
lightningcss-win32-x64-msvc1.32.0MPL-2.0
Resolved Packages (17)
PackageVersionOriginalResolvedSource
codemirror-lang-elixir4.0.0UNKNOWNApache-2.0GitHub repo (livebook-dev/codemirror-lang-elixir) LICENSE via GitHub license API
khroma2.1.0UNKNOWNMITGitHub repo (fabiospampinato/khroma) LICENSE via GitHub license API
lezer-elixir1.1.2UNKNOWNApache-2.0GitHub repo (livebook-dev/lezer-elixir) LICENSE via GitHub license API
map-stream0.1.0UNKNOWNMITGitHub repo (dominictarr/map-stream) LICENSE via GitHub license API
memorystream0.3.1UNKNOWNMITextracted from 'licenses' object [{type:MIT}] in npm registry metadata; confirmed via GitHub repo LICENSE
valid-url1.0.9UNKNOWNMITGitHub repo (ogt/valid-url) LICENSE file text (MIT license)
posthog-js1.369.0SEE LICENSE IN LICENSEApache-2.0GitHub repo (PostHog/posthog-js) LICENSE file text (Apache License 2.0)
pause-stream0.0.11["MIT","Apache2"]MIT OR Apache-2.0GitHub repo (dominictarr/pause-stream) LICENSE file (dual licensed MIT and Apache 2)
@sentry/cli2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-darwin2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brendan-kellam
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(web): enable Sentry node and browser profiling - #1431

Merged
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling
Jul 10, 2026
Merged

feat(web): enable Sentry node and browser profiling#1431
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Enables Sentry profiling in the web app, on both the server and the browser.

Changes

  • Added @sentry/profiling-node to packages/web.
  • sentry.server.config.ts: registered nodeProfilingIntegration().
  • instrumentation-client.ts: registered Sentry.browserProfilingIntegration().
  • Both set profileSessionSampleRate: 1.0 and profileLifecycle: 'trace', so a profiler runs only while a sampled root span is active rather than continuously.
  • next.config.mjs: added a Document-Policy: js-profiling response header, which browser profiling requires in order to opt the document into the JS Self-Profiling API.

Notes

Version pinning.@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs, rather than the latest 10.64.0. It depends on @sentry/core and @sentry/node at exact versions, so a newer minor would install a second copy of the SDK alongside the one @sentry/nextjs pulls in, and the profiler would register against a different global carrier and silently emit nothing. Verified the tree still resolves to a single @sentry/core@10.40.0. Moving to 10.64.0 would need a coordinated bump of @sentry/nextjs (web) and @sentry/node + @sentry/profiling-node (backend) together.

No serverExternalPackages entry needed.@sentry/profiling-node loads a native .node addon through a require() whose path is computed at runtime, which normally means it has to be marked external. Next.js already ships it in its built-in external list (next/dist/lib/server-external-packages.jsonc), so no config is required. Confirmed by building with and without an explicit entry: instrumentation.js hashed identically and the file trace was unchanged.

browserTracingIntegration is not listed explicitly.@sentry/nextjs pushes its own App Router-aware version into the default integrations, and passing integrations as an array merges with the defaults rather than replacing them. Listing the generic one would shadow it.

Verification

  • Ran the node profiler against a capturing transport: emits ["profile_chunk", "transaction"] for a sampled span, confirming the native addon loads and profileLifecycle: 'trace' behaves as configured. With the option omitted (SDK default 'manual') only ["transaction"] is emitted.
  • next build passes, and .next/standalone traces the profiler plus all 28 prebuilt binaries, including the two linux-*-musl-137 ones the node:24-alpine runtime image needs.
  • Typecheck and lint clean on the touched files.

Follow-up worth considering

Server-side profileSessionSampleRate: 1.0 profiles every process. app.sourcebot.dev runs a single web replica whose event loop already saturates under /browse render bursts, so it may be worth dialing this down on the server. Browser profiling is client-side and costs nothing there.

🤖 Generated with Claude Code


Note

Medium Risk
Server profiling uses a native addon at 100% session sampling alongside full trace sampling, which can add CPU/overhead on hot paths; changes are observability-only, not auth or data handling.

Overview
Turns on Sentry performance profiling for the Next.js web app on both the server and client, tied to sampled traces instead of always-on profiling.

Server init registers nodeProfilingIntegration() (new @sentry/profiling-node, version-matched to @sentry/nextjs) with profileSessionSampleRate: 1.0 and profileLifecycle: 'trace'. Client init adds browserProfilingIntegration() with the same profiling options. debug: false is dropped from both inits.

next.config.mjs adds a global Document-Policy: js-profiling header so browser profiling can use the JS Self-Profiling API.

Reviewed by Cursor Bugbot for commit a992a80. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Added enhanced performance monitoring for web sessions.
    • Enabled browser and server-side profiling to provide deeper insight into application performance.
    • Expanded monitoring coverage across all application routes for more consistent diagnostics.

Adds @sentry/profiling-node and wires up profiling on both the server
(nodeProfilingIntegration) and the browser (browserProfilingIntegration).
Both use profileLifecycle: 'trace', so a profiler only runs while a sampled
root span is active rather than continuously.
Browser profiling additionally requires the document to opt into the JS
Self-Profiling API, so a `Document-Policy: js-profiling` response header is
added alongside the existing security headers.
@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs. It
depends on @sentry/core and @sentry/node at exact versions, so a newer minor
would pull a second copy of the SDK into the tree and the profiler would
register against a different global.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

This comment has been minimized.

brendan-kellamand others added 2 commits July 9, 2026 21:59
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0e44652e-025e-4883-b6c2-8a62f7475d65

📥 Commits

Reviewing files that changed from the base of the PR and between 139b238 and a992a80.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (4)
  • packages/web/next.config.mjs
  • packages/web/package.json
  • packages/web/src/instrumentation-client.ts
  • packages/web/src/sentry.server.config.ts

Walkthrough

Changes

Sentry profiling

Layer / File(s)Summary
Configure client and server profiling
packages/web/package.json, packages/web/src/instrumentation-client.ts, packages/web/src/sentry.server.config.ts, packages/web/next.config.mjs
Adds browser and Node Sentry profiling integrations, profiling sampling and lifecycle settings, the Node profiling dependency, and the Document-Policy: js-profiling header for all routes.

Estimated code review effort: 2 (Simple) | ~10 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan-kellam/sentry-profiling

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@brendan-kellam
brendan-kellam merged commit 4aec5d9 into mainJul 10, 2026
10 checks passed
@brendan-kellam
brendan-kellam deleted the brendan-kellam/sentry-profiling branch July 10, 2026 05:01
@github-actionsgithub-actionsBot mentioned this pull request Jul 10, 2026
@github-actions

github-actionsBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

License Audit

⚠️Status: PASS

MetricCount
Total packages2222
Resolved (non-standard)17
Unresolved0
Strong copyleft0
Weak copyleft38

Weak Copyleft Packages (informational)

PackageVersionLicense
@img/sharp-libvips-darwin-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.0.5LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-ppc641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-riscv641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.2.4LGPL-3.0-or-later
@img/sharp-wasm320.33.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-wasm320.34.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-win32-arm640.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.34.5Apache-2.0 AND LGPL-3.0-or-later
axe-core4.10.3MPL-2.0
lightningcss1.32.0MPL-2.0
lightningcss-android-arm641.32.0MPL-2.0
lightningcss-darwin-arm641.32.0MPL-2.0
lightningcss-darwin-x641.32.0MPL-2.0
lightningcss-freebsd-x641.32.0MPL-2.0
lightningcss-linux-arm-gnueabihf1.32.0MPL-2.0
lightningcss-linux-arm64-gnu1.32.0MPL-2.0
lightningcss-linux-arm64-musl1.32.0MPL-2.0
lightningcss-linux-x64-gnu1.32.0MPL-2.0
lightningcss-linux-x64-musl1.32.0MPL-2.0
lightningcss-win32-arm64-msvc1.32.0MPL-2.0
lightningcss-win32-x64-msvc1.32.0MPL-2.0
Resolved Packages (17)
PackageVersionOriginalResolvedSource
codemirror-lang-elixir4.0.0UNKNOWNApache-2.0GitHub repo (livebook-dev/codemirror-lang-elixir) LICENSE via GitHub license API
khroma2.1.0UNKNOWNMITGitHub repo (fabiospampinato/khroma) LICENSE via GitHub license API
lezer-elixir1.1.2UNKNOWNApache-2.0GitHub repo (livebook-dev/lezer-elixir) LICENSE via GitHub license API
map-stream0.1.0UNKNOWNMITGitHub repo (dominictarr/map-stream) LICENSE via GitHub license API
memorystream0.3.1UNKNOWNMITextracted from 'licenses' object [{type:MIT}] in npm registry metadata; confirmed via GitHub repo LICENSE
valid-url1.0.9UNKNOWNMITGitHub repo (ogt/valid-url) LICENSE file text (MIT license)
posthog-js1.369.0SEE LICENSE IN LICENSEApache-2.0GitHub repo (PostHog/posthog-js) LICENSE file text (Apache License 2.0)
pause-stream0.0.11["MIT","Apache2"]MIT OR Apache-2.0GitHub repo (dominictarr/pause-stream) LICENSE file (dual licensed MIT and Apache 2)
@sentry/cli2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-darwin2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brendan-kellam
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(web): enable Sentry node and browser profiling - #1431

Merged
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling
Jul 10, 2026
Merged

feat(web): enable Sentry node and browser profiling#1431
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Enables Sentry profiling in the web app, on both the server and the browser.

Changes

  • Added @sentry/profiling-node to packages/web.
  • sentry.server.config.ts: registered nodeProfilingIntegration().
  • instrumentation-client.ts: registered Sentry.browserProfilingIntegration().
  • Both set profileSessionSampleRate: 1.0 and profileLifecycle: 'trace', so a profiler runs only while a sampled root span is active rather than continuously.
  • next.config.mjs: added a Document-Policy: js-profiling response header, which browser profiling requires in order to opt the document into the JS Self-Profiling API.

Notes

Version pinning.@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs, rather than the latest 10.64.0. It depends on @sentry/core and @sentry/node at exact versions, so a newer minor would install a second copy of the SDK alongside the one @sentry/nextjs pulls in, and the profiler would register against a different global carrier and silently emit nothing. Verified the tree still resolves to a single @sentry/core@10.40.0. Moving to 10.64.0 would need a coordinated bump of @sentry/nextjs (web) and @sentry/node + @sentry/profiling-node (backend) together.

No serverExternalPackages entry needed.@sentry/profiling-node loads a native .node addon through a require() whose path is computed at runtime, which normally means it has to be marked external. Next.js already ships it in its built-in external list (next/dist/lib/server-external-packages.jsonc), so no config is required. Confirmed by building with and without an explicit entry: instrumentation.js hashed identically and the file trace was unchanged.

browserTracingIntegration is not listed explicitly.@sentry/nextjs pushes its own App Router-aware version into the default integrations, and passing integrations as an array merges with the defaults rather than replacing them. Listing the generic one would shadow it.

Verification

  • Ran the node profiler against a capturing transport: emits ["profile_chunk", "transaction"] for a sampled span, confirming the native addon loads and profileLifecycle: 'trace' behaves as configured. With the option omitted (SDK default 'manual') only ["transaction"] is emitted.
  • next build passes, and .next/standalone traces the profiler plus all 28 prebuilt binaries, including the two linux-*-musl-137 ones the node:24-alpine runtime image needs.
  • Typecheck and lint clean on the touched files.

Follow-up worth considering

Server-side profileSessionSampleRate: 1.0 profiles every process. app.sourcebot.dev runs a single web replica whose event loop already saturates under /browse render bursts, so it may be worth dialing this down on the server. Browser profiling is client-side and costs nothing there.

🤖 Generated with Claude Code


Note

Medium Risk
Server profiling uses a native addon at 100% session sampling alongside full trace sampling, which can add CPU/overhead on hot paths; changes are observability-only, not auth or data handling.

Overview
Turns on Sentry performance profiling for the Next.js web app on both the server and client, tied to sampled traces instead of always-on profiling.

Server init registers nodeProfilingIntegration() (new @sentry/profiling-node, version-matched to @sentry/nextjs) with profileSessionSampleRate: 1.0 and profileLifecycle: 'trace'. Client init adds browserProfilingIntegration() with the same profiling options. debug: false is dropped from both inits.

next.config.mjs adds a global Document-Policy: js-profiling header so browser profiling can use the JS Self-Profiling API.

Reviewed by Cursor Bugbot for commit a992a80. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Added enhanced performance monitoring for web sessions.
    • Enabled browser and server-side profiling to provide deeper insight into application performance.
    • Expanded monitoring coverage across all application routes for more consistent diagnostics.

Adds @sentry/profiling-node and wires up profiling on both the server
(nodeProfilingIntegration) and the browser (browserProfilingIntegration).
Both use profileLifecycle: 'trace', so a profiler only runs while a sampled
root span is active rather than continuously.
Browser profiling additionally requires the document to opt into the JS
Self-Profiling API, so a `Document-Policy: js-profiling` response header is
added alongside the existing security headers.
@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs. It
depends on @sentry/core and @sentry/node at exact versions, so a newer minor
would pull a second copy of the SDK into the tree and the profiler would
register against a different global.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

This comment has been minimized.

brendan-kellamand others added 2 commits July 9, 2026 21:59
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0e44652e-025e-4883-b6c2-8a62f7475d65

📥 Commits

Reviewing files that changed from the base of the PR and between 139b238 and a992a80.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (4)
  • packages/web/next.config.mjs
  • packages/web/package.json
  • packages/web/src/instrumentation-client.ts
  • packages/web/src/sentry.server.config.ts

Walkthrough

Changes

Sentry profiling

Layer / File(s)Summary
Configure client and server profiling
packages/web/package.json, packages/web/src/instrumentation-client.ts, packages/web/src/sentry.server.config.ts, packages/web/next.config.mjs
Adds browser and Node Sentry profiling integrations, profiling sampling and lifecycle settings, the Node profiling dependency, and the Document-Policy: js-profiling header for all routes.

Estimated code review effort: 2 (Simple) | ~10 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan-kellam/sentry-profiling

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@brendan-kellam
brendan-kellam merged commit 4aec5d9 into mainJul 10, 2026
10 checks passed
@brendan-kellam
brendan-kellam deleted the brendan-kellam/sentry-profiling branch July 10, 2026 05:01
@github-actionsgithub-actionsBot mentioned this pull request Jul 10, 2026
@github-actions

github-actionsBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

License Audit

⚠️Status: PASS

MetricCount
Total packages2222
Resolved (non-standard)17
Unresolved0
Strong copyleft0
Weak copyleft38

Weak Copyleft Packages (informational)

PackageVersionLicense
@img/sharp-libvips-darwin-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.0.5LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-ppc641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-riscv641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.2.4LGPL-3.0-or-later
@img/sharp-wasm320.33.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-wasm320.34.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-win32-arm640.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.34.5Apache-2.0 AND LGPL-3.0-or-later
axe-core4.10.3MPL-2.0
lightningcss1.32.0MPL-2.0
lightningcss-android-arm641.32.0MPL-2.0
lightningcss-darwin-arm641.32.0MPL-2.0
lightningcss-darwin-x641.32.0MPL-2.0
lightningcss-freebsd-x641.32.0MPL-2.0
lightningcss-linux-arm-gnueabihf1.32.0MPL-2.0
lightningcss-linux-arm64-gnu1.32.0MPL-2.0
lightningcss-linux-arm64-musl1.32.0MPL-2.0
lightningcss-linux-x64-gnu1.32.0MPL-2.0
lightningcss-linux-x64-musl1.32.0MPL-2.0
lightningcss-win32-arm64-msvc1.32.0MPL-2.0
lightningcss-win32-x64-msvc1.32.0MPL-2.0
Resolved Packages (17)
PackageVersionOriginalResolvedSource
codemirror-lang-elixir4.0.0UNKNOWNApache-2.0GitHub repo (livebook-dev/codemirror-lang-elixir) LICENSE via GitHub license API
khroma2.1.0UNKNOWNMITGitHub repo (fabiospampinato/khroma) LICENSE via GitHub license API
lezer-elixir1.1.2UNKNOWNApache-2.0GitHub repo (livebook-dev/lezer-elixir) LICENSE via GitHub license API
map-stream0.1.0UNKNOWNMITGitHub repo (dominictarr/map-stream) LICENSE via GitHub license API
memorystream0.3.1UNKNOWNMITextracted from 'licenses' object [{type:MIT}] in npm registry metadata; confirmed via GitHub repo LICENSE
valid-url1.0.9UNKNOWNMITGitHub repo (ogt/valid-url) LICENSE file text (MIT license)
posthog-js1.369.0SEE LICENSE IN LICENSEApache-2.0GitHub repo (PostHog/posthog-js) LICENSE file text (Apache License 2.0)
pause-stream0.0.11["MIT","Apache2"]MIT OR Apache-2.0GitHub repo (dominictarr/pause-stream) LICENSE file (dual licensed MIT and Apache 2)
@sentry/cli2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-darwin2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brendan-kellam
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(web): enable Sentry node and browser profiling - #1431

Merged
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling
Jul 10, 2026
Merged

feat(web): enable Sentry node and browser profiling#1431
brendan-kellam merged 3 commits into
mainfrom
brendan-kellam/sentry-profiling

Conversation

@brendan-kellam

@brendan-kellambrendan-kellam commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Enables Sentry profiling in the web app, on both the server and the browser.

Changes

  • Added @sentry/profiling-node to packages/web.
  • sentry.server.config.ts: registered nodeProfilingIntegration().
  • instrumentation-client.ts: registered Sentry.browserProfilingIntegration().
  • Both set profileSessionSampleRate: 1.0 and profileLifecycle: 'trace', so a profiler runs only while a sampled root span is active rather than continuously.
  • next.config.mjs: added a Document-Policy: js-profiling response header, which browser profiling requires in order to opt the document into the JS Self-Profiling API.

Notes

Version pinning.@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs, rather than the latest 10.64.0. It depends on @sentry/core and @sentry/node at exact versions, so a newer minor would install a second copy of the SDK alongside the one @sentry/nextjs pulls in, and the profiler would register against a different global carrier and silently emit nothing. Verified the tree still resolves to a single @sentry/core@10.40.0. Moving to 10.64.0 would need a coordinated bump of @sentry/nextjs (web) and @sentry/node + @sentry/profiling-node (backend) together.

No serverExternalPackages entry needed.@sentry/profiling-node loads a native .node addon through a require() whose path is computed at runtime, which normally means it has to be marked external. Next.js already ships it in its built-in external list (next/dist/lib/server-external-packages.jsonc), so no config is required. Confirmed by building with and without an explicit entry: instrumentation.js hashed identically and the file trace was unchanged.

browserTracingIntegration is not listed explicitly.@sentry/nextjs pushes its own App Router-aware version into the default integrations, and passing integrations as an array merges with the defaults rather than replacing them. Listing the generic one would shadow it.

Verification

  • Ran the node profiler against a capturing transport: emits ["profile_chunk", "transaction"] for a sampled span, confirming the native addon loads and profileLifecycle: 'trace' behaves as configured. With the option omitted (SDK default 'manual') only ["transaction"] is emitted.
  • next build passes, and .next/standalone traces the profiler plus all 28 prebuilt binaries, including the two linux-*-musl-137 ones the node:24-alpine runtime image needs.
  • Typecheck and lint clean on the touched files.

Follow-up worth considering

Server-side profileSessionSampleRate: 1.0 profiles every process. app.sourcebot.dev runs a single web replica whose event loop already saturates under /browse render bursts, so it may be worth dialing this down on the server. Browser profiling is client-side and costs nothing there.

🤖 Generated with Claude Code


Note

Medium Risk
Server profiling uses a native addon at 100% session sampling alongside full trace sampling, which can add CPU/overhead on hot paths; changes are observability-only, not auth or data handling.

Overview
Turns on Sentry performance profiling for the Next.js web app on both the server and client, tied to sampled traces instead of always-on profiling.

Server init registers nodeProfilingIntegration() (new @sentry/profiling-node, version-matched to @sentry/nextjs) with profileSessionSampleRate: 1.0 and profileLifecycle: 'trace'. Client init adds browserProfilingIntegration() with the same profiling options. debug: false is dropped from both inits.

next.config.mjs adds a global Document-Policy: js-profiling header so browser profiling can use the JS Self-Profiling API.

Reviewed by Cursor Bugbot for commit a992a80. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Added enhanced performance monitoring for web sessions.
    • Enabled browser and server-side profiling to provide deeper insight into application performance.
    • Expanded monitoring coverage across all application routes for more consistent diagnostics.

Adds @sentry/profiling-node and wires up profiling on both the server
(nodeProfilingIntegration) and the browser (browserProfilingIntegration).
Both use profileLifecycle: 'trace', so a profiler only runs while a sampled
root span is active rather than continuously.
Browser profiling additionally requires the document to opt into the JS
Self-Profiling API, so a `Document-Policy: js-profiling` response header is
added alongside the existing security headers.
@sentry/profiling-node is pinned to ^10.40.0 to match @sentry/nextjs. It
depends on @sentry/core and @sentry/node at exact versions, so a newer minor
would pull a second copy of the SDK into the tree and the profiler would
register against a different global.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

This comment has been minimized.

brendan-kellamand others added 2 commits July 9, 2026 21:59
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0e44652e-025e-4883-b6c2-8a62f7475d65

📥 Commits

Reviewing files that changed from the base of the PR and between 139b238 and a992a80.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (4)
  • packages/web/next.config.mjs
  • packages/web/package.json
  • packages/web/src/instrumentation-client.ts
  • packages/web/src/sentry.server.config.ts

Walkthrough

Changes

Sentry profiling

Layer / File(s)Summary
Configure client and server profiling
packages/web/package.json, packages/web/src/instrumentation-client.ts, packages/web/src/sentry.server.config.ts, packages/web/next.config.mjs
Adds browser and Node Sentry profiling integrations, profiling sampling and lifecycle settings, the Node profiling dependency, and the Document-Policy: js-profiling header for all routes.

Estimated code review effort: 2 (Simple) | ~10 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch brendan-kellam/sentry-profiling

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@brendan-kellam
brendan-kellam merged commit 4aec5d9 into mainJul 10, 2026
10 checks passed
@brendan-kellam
brendan-kellam deleted the brendan-kellam/sentry-profiling branch July 10, 2026 05:01
@github-actionsgithub-actionsBot mentioned this pull request Jul 10, 2026
@github-actions

github-actionsBot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

License Audit

⚠️Status: PASS

MetricCount
Total packages2222
Resolved (non-standard)17
Unresolved0
Strong copyleft0
Weak copyleft38

Weak Copyleft Packages (informational)

PackageVersionLicense
@img/sharp-libvips-darwin-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-darwin-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.0.5LGPL-3.0-or-later
@img/sharp-libvips-linux-arm1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-ppc641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-riscv641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-s390x1.2.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linux-x641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-arm641.2.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.0.4LGPL-3.0-or-later
@img/sharp-libvips-linuxmusl-x641.2.4LGPL-3.0-or-later
@img/sharp-wasm320.33.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-wasm320.34.5Apache-2.0 AND LGPL-3.0-or-later AND MIT
@img/sharp-win32-arm640.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-ia320.34.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.33.5Apache-2.0 AND LGPL-3.0-or-later
@img/sharp-win32-x640.34.5Apache-2.0 AND LGPL-3.0-or-later
axe-core4.10.3MPL-2.0
lightningcss1.32.0MPL-2.0
lightningcss-android-arm641.32.0MPL-2.0
lightningcss-darwin-arm641.32.0MPL-2.0
lightningcss-darwin-x641.32.0MPL-2.0
lightningcss-freebsd-x641.32.0MPL-2.0
lightningcss-linux-arm-gnueabihf1.32.0MPL-2.0
lightningcss-linux-arm64-gnu1.32.0MPL-2.0
lightningcss-linux-arm64-musl1.32.0MPL-2.0
lightningcss-linux-x64-gnu1.32.0MPL-2.0
lightningcss-linux-x64-musl1.32.0MPL-2.0
lightningcss-win32-arm64-msvc1.32.0MPL-2.0
lightningcss-win32-x64-msvc1.32.0MPL-2.0
Resolved Packages (17)
PackageVersionOriginalResolvedSource
codemirror-lang-elixir4.0.0UNKNOWNApache-2.0GitHub repo (livebook-dev/codemirror-lang-elixir) LICENSE via GitHub license API
khroma2.1.0UNKNOWNMITGitHub repo (fabiospampinato/khroma) LICENSE via GitHub license API
lezer-elixir1.1.2UNKNOWNApache-2.0GitHub repo (livebook-dev/lezer-elixir) LICENSE via GitHub license API
map-stream0.1.0UNKNOWNMITGitHub repo (dominictarr/map-stream) LICENSE via GitHub license API
memorystream0.3.1UNKNOWNMITextracted from 'licenses' object [{type:MIT}] in npm registry metadata; confirmed via GitHub repo LICENSE
valid-url1.0.9UNKNOWNMITGitHub repo (ogt/valid-url) LICENSE file text (MIT license)
posthog-js1.369.0SEE LICENSE IN LICENSEApache-2.0GitHub repo (PostHog/posthog-js) LICENSE file text (Apache License 2.0)
pause-stream0.0.11["MIT","Apache2"]MIT OR Apache-2.0GitHub repo (dominictarr/pause-stream) LICENSE file (dual licensed MIT and Apache 2)
@sentry/cli2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-darwin2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm2.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-linux-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-arm642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-i6862.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)
@sentry/cli-win32-x642.58.5FSL-1.1-MITFSL-1.1-MIT (Functional Source License 1.1, MIT Future License)known license identifier (source-available, converts to MIT after 2 years; not copyleft)

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@brendan-kellam