Set Up Profiling

Collect & view performance insights for JavaScript programs with Sentry's Profiling integrations. Get started with profiling to understand your application's performance.

Profiling captures function-level data from your production code to enable you to fine-tune your app's performance. It tracks what's being called, how often, and where. In the browser, this helps you pinpoint causes of UI jank, understand why metrics like Interaction to Next Paint (INP) are slow, or identify long tasks blocking repaints and causing frame drops.

Requirements: @sentry/browser SDK version 10.27.0+ (or 7.60.0+ for deprecated transaction-based profiling)

Copied
npm install @sentry/browser --save

Your server must return Document-Policy: js-profiling in response headers.

How you configure this depends on your hosting platform or server. Select your setup below:

Vercel

Add to vercel.json:

vercel.json
Copied
{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "Document-Policy",
          "value": "js-profiling"
        }
      ]
    }
  ]
}
Netlify

Add to netlify.toml:

netlify.toml
Copied
[[headers]]
  for = "/*"
  [headers.values]
    Document-Policy = "js-profiling"

Or add to _headers file in your publish directory:

_headers
Copied
/*
  Document-Policy: js-profiling
Express / Node.js

Use middleware to set the header:

server.js
Copied
app.use((req, res, next) => {
  res.set("Document-Policy", "js-profiling");
  next();
});

// Or for a specific route
app.get("/", (req, res) => {
  res.set("Document-Policy", "js-profiling");
  res.sendFile("index.html");
});
Nginx

Add to your server or location block:

nginx.conf
Copied
server {
    location / {
        add_header Document-Policy "js-profiling";
        # ... rest of your config
    }
}
Apache

Add to .htaccess or your server config:

.htaccess
Copied
<IfModule mod_headers.c>
    Header set Document-Policy "js-profiling"
</IfModule>
AWS CloudFront

Use a CloudFront Response Headers Policy or a CloudFront Function:

cloudfront-function.js
Copied
function handler(event) {
  var response = event.response;
  var headers = response.headers;
  headers["document-policy"] = { value: "js-profiling" };
  return response;
}

Attach this function as a "Viewer Response" function to your CloudFront distribution.

ASP.NET Core

Add middleware to set the header:

Program.cs
Copied
app.Use(async (context, next) => {
    context.Response.OnStarting(() => {
        context.Response.Headers.Append("Document-Policy", "js-profiling");
        return Task.CompletedTask;
    });
    await next();
});

Copied
import * as Sentry from "@sentry/browser";

Sentry.init({
  dsn: "___PUBLIC_DSN___",
  integrations: [
    // Add browser profiling integration to the list of integrations
    Sentry.browserTracingIntegration(),
    Sentry.browserProfilingIntegration(),
  ],

  // Set tracesSampleRate to 1.0 to capture 100%
  // of transactions for tracing.
  // We recommend adjusting this value in production
  tracesSampleRate: 1.0,
  // Set `tracePropagationTargets` to control for which URLs trace propagation should be enabled
  tracePropagationTargets: ["localhost", /^https:\/\/yourserver\.io\/api/],

  // Set profileSessionSampleRate to 1.0 to profile during every session.
  // The decision, whether to profile or not, is made once per session (when the SDK is initialized).
  profileSessionSampleRate: 1.0,
});

ModeDescriptionUse When
Manual (default)You control when profiling runsProfiling specific user flows or interactions
TraceProfiler runs automatically with active spansYou want profiles attached to all traced operations

Start and stop the profiler around code you want to profile:

Copied
Sentry.uiProfiler.startProfiler();
// Code here will be profiled
Sentry.uiProfiler.stopProfiler();

Profiles automatically attach to spans. Enable by setting profileLifecycle: "trace":

Copied
Sentry.init({
  dsn: "___PUBLIC_DSN___",
  integrations: [
    Sentry.browserTracingIntegration(),
    Sentry.browserProfilingIntegration(),
  ],
  tracesSampleRate: 1.0,
  profileSessionSampleRate: 1.0,
  profileLifecycle: "trace",
});

Sentry ProfilingChrome DevTools
EnvironmentProduction (real users)Local development
Sampling rate100Hz (10ms period)1000Hz (1ms period)
Source mapsDeobfuscated function namesMinified names
Data scopeAggregated across usersSingle session
Troubleshooting

Chrome DevTools shows "Profiling Overhead"

When browserProfilingIntegration is enabled, Chrome DevTools incorrectly attributes rendering work as profiling overhead. Disable the integration when using DevTools locally.

Profiles only from Chrome users

This is expected. The JS Self-Profiling API is currently only implemented in Chromium browsers. Consider this bias when analyzing data.

Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").