You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add `defineNodeInstrumentation()` for Next.js root `instrumentation.ts`: gate on `NEXT_RUNTIME === 'nodejs'`, cache the dynamic `import()` of `lib/evlog` between `register` and `onRequestError`, and export `NextInstrumentationRequest` / `NextInstrumentationErrorContext` types.
Next.js supports an [`instrumentation.ts`](https://nextjs.org/docs/app/guides/instrumentation) file at the project root for server startup hooks and error reporting. evlog provides `createInstrumentation()` to integrate with this pattern.
69
+
70
+
::callout{icon="i-lucide-info"color="info"}
71
+
These two APIs serve different purposes and can be used independently or together:
72
+
73
+
-**`createEvlog()`** — per-request wide events via `withEvlog()`
74
+
-**`createInstrumentation()`** — server startup (`register()`) + unhandled error reporting (`onRequestError()`) across all routes, including SSR and RSC
75
+
- Both can coexist: `register()` initializes and locks the logger first, so `createEvlog()` respects it. Each can have its own `drain`.
76
+
::
77
+
78
+
### 1. Add instrumentation exports to your evlog instance
Next.js evaluates `instrumentation.ts` in both Node.js and Edge runtimes. Load your real `lib/evlog.ts` only when `NEXT_RUNTIME === 'nodejs'` so Edge bundles never pull Node-only drains (fs, adapters, etc.).
94
+
95
+
**Recommended** — `defineNodeInstrumentation` gates the Node runtime, dynamic-imports your module once (cached), and forwards `register` / `onRequestError`:
**Manual** — same behavior with explicit handlers; use this if you want full control in the root file (extra branches, per-error logic, or a different import strategy). Without a shared helper, each `onRequestError` typically re-runs `import('./lib/evlog')` unless you add your own cache.
Both styles are supported: the helper is optional sugar, not a takeover. `defineNodeInstrumentation` only forwards Next’s two hooks to whatever you export from `lib/evlog` — it does not prevent other work in your app.
126
+
127
+
### Custom behavior (evlog + your code)
128
+
129
+
-**Root `instrumentation.ts`** — Next’s stable surface here is `register` and `onRequestError`. The evlog helper exports exactly those; it does not reserve the whole file. If you need **additional** top-level exports later (when Next documents them), use the **manual** wiring and compose by hand, or keep evlog’s hooks minimal and put everything else in `lib/evlog.ts`.
130
+
-**`lib/evlog.ts` (recommended for composition)** — wrap evlog’s handlers so you stay free to add startup work, metrics, or extra logging without fighting the helper:
// optional: your own side effects (metrics, etc.)
152
+
}
153
+
```
154
+
155
+
Then keep `instrumentation.ts` as a thin import (`defineNodeInstrumentation` or manual) that only loads `./lib/evlog` on Node — your customization lives next to `createEvlog()` in one place.
156
+
157
+
Next.js automatically calls these exports:
158
+
159
+
-`register()` — Runs once when the server starts. Initializes the evlog logger with your configured drain, sampling, and options. When `captureOutput` is enabled, `stdout` and `stderr` writes are captured as structured log events.
160
+
-`onRequestError()` — Called on every unhandled request error. Emits a structured error log with the error message, digest, stack trace, request path/method, and routing context (`routerKind`, `routePath`, `routeType`, `renderSource`).
161
+
162
+
::callout{icon="i-lucide-info"color="info"}
163
+
`captureOutput` only activates in the Node.js runtime (`NEXT_RUNTIME === 'nodejs'`). It patches `process.stdout.write` and `process.stderr.write` to emit structured `log.info` / `log.error` events alongside the original output.
164
+
::
165
+
166
+
### Configuration
167
+
168
+
The `createInstrumentation()` factory accepts global logger options (`enabled`, `service`, `env`, `pretty`, `silent`, `sampling`, `stringify`, `drain`) plus:
169
+
170
+
| Option | Type | Default | Description |
171
+
|--------|------|---------|-------------|
172
+
|`captureOutput`|`boolean`|`false`| Capture stdout/stderr as structured log events |
173
+
66
174
## Production Configuration
67
175
68
176
A real-world `lib/evlog.ts` with enrichers, batched drain, tail sampling, and route-based service names:
0 commit comments