Instrumentation and tracing
Production debugging gets easier when logs, errors, traces, and Web Vitals describe the same request without exposing the person behind it.
Register server instrumentation once
Place instrumentation.ts at the project root, or beside app inside src when the project uses a src directory. Its register function runs when a server instance starts, before it begins handling requests.
Import runtime-specific packages inside register. A Node tracing library may not run in the edge runtime, and top-level imports can fail before your runtime check has a chance to help.
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
await import('./instrumentation-node')
}
if (process.env.NEXT_RUNTIME === 'edge') {
await import('./instrumentation-edge')
}
}Capture server errors with useful context
The onRequestError hook can forward errors captured by the server to an observability provider. Include the route, operation, deployment version, and a correlation identifier. Avoid request bodies, cookies, access tokens, and personal fields by default.
A stack trace without release information tells you where code failed but not which code was running. Attach a commit SHA or deployment identifier to logs and error events.
Write logs that can answer a question
Structured logs are easier to filter than sentences assembled for the console. Use stable fields such as event, route, durationMs, status, requestId, and resourceId. Keep the human message short.
Choose log levels deliberately. A validation rejection is usually expected information, not an error page for the on-call engineer. A failed database connection is different.
Traces explain one request; metrics reveal a pattern
A trace connects the work inside a request: rendering, database queries, service calls, and cache access. Metrics show whether latency or failure rate changed across thousands of requests. Use both before deciding where a slowdown lives.
Measure product operations as well as framework internals. Checkout completion time or search failure rate is often more useful than a generic request average.
Alert on user impact, not every unusual event
An alert should ask for action. A brief increase in one harmless warning may belong on a dashboard, while sustained checkout failures should wake somebody up.
For every alert, write the likely causes, the first dashboard to open, and a safe mitigation. If nobody knows what to do when it fires, it is noise rather than protection.
Can you explain “Instrumentation and tracing” without reaching for the API reference?
Describe the main trade-off, one failure mode, and the decision you would make in a real project.