Profiling
Profiling samples your process's call stacks while it works, so you can see where the time actually goes — inside the transaction that tracing already told you was slow.
Errora accepts both profile shapes:
- Transaction profiles (v1) — bounded by one transaction.
- Continuous profiling chunks (v2) — a rolling stream, not tied to a transaction.
Setup
Profiling rides on tracing, so traces_sample_rate must be non-zero.
sentry_sdk.init(
dsn="…",
traces_sample_rate=0.2,
profiles_sample_rate=1.0, # fraction *of sampled transactions*
)
// Node.js
import { nodeProfilingIntegration } from "@sentry/profiling-node";
Sentry.init({
dsn: "…",
tracesSampleRate: 0.2,
profilesSampleRate: 1.0,
integrations: [nodeProfilingIntegration()],
});
# Laravel .env
SENTRY_TRACES_SAMPLE_RATE=0.2
SENTRY_PROFILES_SAMPLE_RATE=1.0
profiles_sample_rate multiplies with traces_sample_rate: 0.2 × 1.0 means 20% of
requests are traced and all of those are profiled.
Reading a profile
Profiling lists profiles with their transaction, duration, sample count, environment and release. Open one for:
- The flamegraph — width is time, not sample count. Each sample is weighted by the gap to the next sample on the same thread, so a thread that happens to be sampled twice as often does not look twice as slow. Gaps are clamped, so a paused profiler can't dominate the graph.
- Self time per function — the time spent in the function itself, excluding callees.
- Threads — switch between them.
Slowest functions for the whole project is its own view. That ranking is computed at ingest and stored per function, so it is an indexed query rather than a decompress-everything scan.
API
GET /api/v1/projects/{project_id}/profiles?stats_period=24h&limit=&offset=
GET /api/v1/projects/{project_id}/profiles/overview
GET /api/v1/projects/{project_id}/profiles/functions
GET /api/v1/projects/{project_id}/profiles/{profile_id}
GET /api/v1/projects/{project_id}/profiles/{profile_id}/flamegraph
Cost
Profiles are metered as the Profiling service, per profile. They are also the bulkiest
payload the SDK sends, so keep profiles_sample_rate low in production once you have found
your hot paths — or turn it up temporarily during an investigation.
Troubleshooting
| Symptom | Cause / fix |
|---|---|
| No profiles at all | traces_sample_rate is 0, the profiling package isn't installed (Node needs @sentry/profiling-node), or the platform has no profiler |
| Profiles but empty flamegraph | The transaction was too short to collect samples — profile a heavier endpoint |
Everything is <unknown> | Native frames without symbols; ship a build with symbols, or profile the interpreted layer |
| Costs climbing | Lower profiles_sample_rate; it multiplies with the trace sample rate |