Logging

Structured Logs — the Single Most Useful Production Tool

Logging

console.log is fine for dev. Production needs structured JSON logs with levels, request IDs, and ingestion-ready format.

4 min read Level 2/5 #nodejs#logging#pino
What you'll learn
  • Use pino for structured JSON logs
  • Include a request ID
  • Pick the right log levels

Structured logs are JSON objects — easy to grep, easy to ingest into log services (Datadog, Sentry, Logtail, Cloudwatch). Plain console.log strings are not.

Pino — The Standard

npm install pino
import pino from "pino";

const log = pino({
  level: process.env.LOG_LEVEL ?? "info",
});

log.info("server up");
log.warn({ userId: 42 }, "rate limit warning");
log.error({ err }, "DB query failed");

Output (one JSON object per line — “ndjson”):

{"level":30,"time":1714512345678,"msg":"server up"}
{"level":40,"time":1714512345700,"userId":42,"msg":"rate limit warning"}

Levels: trace(10) < debug(20) < info(30) < warn(40) < error(50) < fatal(60).

Pretty In Development

Pino logs raw JSON. To pretty-print in dev:

node server.mjs | npx pino-pretty

Or programmatically:

const log = pino({
  transport: process.env.NODE_ENV === "development"
    ? { target: "pino-pretty" }
    : undefined,
});

Per-Request Loggers

Attach a request ID and surface it in every log:

import pinoHttp from "pino-http";

app.use(pinoHttp({ logger: log }));

app.get("/users/:id", (req, res) => {
  req.log.info({ userId: req.params.id }, "user lookup");
});

Now every log for a given request includes its reqId — invaluable when correlating multi-step traces in a busy production log.

Levels Cheat Sheet

LevelUse for
tracePer-character, per-iteration
debugUseful for one bug; off in prod
infoServer up, user signed up, job completed
warnRecoverable issue (retry succeeded, deprecation)
errorFailed request, exception caught
fatalAbout to crash

In production: info and above. Never log secrets (passwords, tokens, API keys).

Where Logs Go

  • Stdout — let the platform (container, systemd, Kubernetes, Render, Fly) collect. Don’t write to files yourself in modern deployments.
  • Log service — Logtail, Datadog, Axiom, Better Stack. Ship to one once you have any production traffic.
Performance →