Mirrors PR #429 for the planner app. Each HTTP request now gets a requestId (inbound X-Request-Id honored, otherwise a fresh UUID), echoed on the response, and propagated to every downstream log call via AsyncLocalStorage + pino's \`mixin\`. Tests: planner logger.server.test.ts (2 cases, same shape as the journal version). Full repo: pnpm typecheck, pnpm lint, pnpm test all green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
26 lines
834 B
TypeScript
26 lines
834 B
TypeScript
import pino from "pino";
|
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
|
/**
|
|
* Per-request context propagated through the async stack. The HTTP
|
|
* server wraps each request in `requestContext.run({ requestId }, ...)`
|
|
* so every downstream `logger.info(...)` automatically tags log lines
|
|
* with `requestId` — see apps/journal/app/lib/logger.server.ts for the
|
|
* same pattern in the journal app.
|
|
*/
|
|
export interface RequestContext {
|
|
requestId: string;
|
|
}
|
|
|
|
export const requestContext = new AsyncLocalStorage<RequestContext>();
|
|
|
|
export const logger = pino({
|
|
level: process.env.LOG_LEVEL ?? "info",
|
|
mixin: () => {
|
|
const ctx = requestContext.getStore();
|
|
return ctx ? { requestId: ctx.requestId } : {};
|
|
},
|
|
...(process.env.NODE_ENV !== "production"
|
|
? { transport: { target: "pino-pretty" } }
|
|
: {}),
|
|
});
|