Skip to Content

src/lib/log.ts — Root logger

Single factory for the pino logger. Two modes:

  • Pretty (dev/test): pino-pretty transport, colorized, HH:MM:ss.l timestamps, pid/hostname hidden so local logs stay readable.
  • JSON (production): raw pino JSON to stdout. systemd’s StandardOutput=journal routes it into journald, which preserves the structure for journalctl -o json and downstream log shippers (e.g. promtail).

Public surface

ExportShapePurpose
createLogger(opts)({level, pretty}) => pino.LoggerReturns the root logger
LoggerOptions{level: string, pretty: boolean}

Why one factory

Every other module gets its logger from Fastify’s request.log (which is a child of this root) or from the explicit logger passed into a factory. Nothing imports pino directly outside this file — that keeps log formatting decisions in one place.

Request correlation

Fastify is configured in src/http/server.ts with requestIdLogLabel: 'requestId' and a UUID genReqId. Every log line emitted during a request — including the canonical onResponse summary line — carries the same requestId. See docs/components/http-server.md.

Tests

test/unit/logger.test.ts — verifies the summary line shape (requestId, route, durationMs, outcome, statusCode), that 2xx maps to outcome=ok and 4xx maps to outcome=rejected, and that handler child logs share the request’s requestId.