recipes / logging
Log JSON lines to stdout
One JSON object per line on stdout. No files, no log rotation, no agents inside the container.
Kubernetes collects whatever a container writes to stdout and stderr. Log there,
in a format that machines parse and humans can still read with jq.
Without dependencies
// src/log.js
export const log = (level, msg, fields = {}) =>
process.stdout.write(
JSON.stringify({ time: new Date().toISOString(), level, msg, ...fields }) + "\n",
);
With pino
import pino from "pino";
export const log = pino({ level: process.env.LOG_LEVEL ?? "info" });
log.info({ port: 3000 }, "listening");
Pino writes JSON lines, is fast, and has no pretty-printing in production unless
you add it. Use pino-pretty only on your laptop.
Notes
console.logis synchronous when stdout is a pipe on Linux. Under heavy logging it blocks the event loop. Pino is asynchronous by default.- Do not log probe requests. Filter
/healthzand/readyzout of request logging. - Put the request ID in every line of a request. Read it from the
traceparentorx-request-idheader set by your ingress. - Do not write log files. The container has a read-only root filesystem and files vanish with the Pod.
See it applied
- examples/full/src/log.js in the repository
- examples/full - every recipe applied to one app
Updated 2026-09-10 · tags: logging, observability, pino · edit on GitHub