Logging


https://github.com/pinojs/pino
https://getpino.io/
https://kubernetes.io/docs/concepts/cluster-administration/logging/
https://pm2.io/docs/runtime/guide/log-management/
https://man7.org/linux/man-pages/man8/logrotate.8.html

1. Important Points#

logging rules:
    production logs should be structured JSON
    container app should write to stdout/stderr
    include service / env / request_id / trace_id
    do not log password / token / cookie / authorization
    error log should include stack
    log level must be configurable

2. Log Levels#

Level Use Case
debug local troubleshooting
info business/runtime events
warn recoverable abnormal condition
error request/dependency failed
fatal process cannot continue

3. Logging Library Setup#

npm install pino
npm install -D pino-pretty
import pino from "pino";

const isLocal = process.env.NODE_ENV === "local";

export const logger = pino({
  level: process.env.LOG_LEVEL ?? "info",
  base: {
    service: process.env.SERVICE_NAME ?? "order-api",
    env: process.env.NODE_ENV ?? "local"
  },
  redact: {
    paths: [
      "req.headers.authorization",
      "req.headers.cookie",
      "password",
      "token",
      "*.password",
      "*.token"
    ],
    censor: "[REDACTED]"
  },
  transport: isLocal
    ? {
        target: "pino-pretty",
        options: {
          colorize: true,
          translateTime: "SYS:standard"
        }
      }
    : undefined
});

4. Request / Context Logging#

import { randomUUID } from "node:crypto";
import { logger } from "./logger.js";

export function requestLogger(req, res, next) {
  const start = Date.now();
  const requestId = req.header("x-request-id") ?? randomUUID();

  res.setHeader("x-request-id", requestId);

  req.log = logger.child({
    request_id: requestId,
    method: req.method,
    path: req.path
  });

  res.on("finish", () => {
    req.log.info({
      status_code: res.statusCode,
      duration_ms: Date.now() - start
    }, "request completed");
  });

  next();
}

5. Error Logging#

export function errorHandler(error, req, res, _next) {
  if (error.name === "AppError") {
    req.log.warn({
      error_code: error.code,
      status_code: error.statusCode
    }, error.message);

    res.status(error.statusCode).json({
      error: {
        code: error.code,
        message: error.message
      }
    });
    return;
  }

  req.log.error({ err: error }, "unexpected error");

  res.status(500).json({
    error: {
      code: "INTERNAL_ERROR",
      message: "internal server error"
    }
  });
}

6. Log Format#

{
  "level": 30,
  "time": 1790599200000,
  "service": "order-api",
  "env": "prod",
  "request_id": "req-1001",
  "method": "POST",
  "path": "/orders",
  "status_code": 201,
  "duration_ms": 18,
  "msg": "request completed"
}

7. Sensitive Data#

never log:
    password
    token
    authorization header
    cookie
    private key
    credit card

8. Docker#

container logging:
    write logs to stdout/stderr
    Docker logging driver handles collection and rotation
services:
  order-api:
    image: order-api:1.0.0
    logging:
      driver: json-file
      options:
        max-size: "100m"
        max-file: "5"

9. Kubernetes#

kubectl logs deploy/order-api
kubectl logs deploy/order-api --previous
collection:
    Fluent Bit / Fluentd / Vector / OpenTelemetry Collector
    send to Loki / Elasticsearch / OpenSearch / CloudWatch Logs

10. VM / systemd#

[Service]
User=app
WorkingDirectory=/opt/order-api
Environment=NODE_ENV=prod
Environment=LOG_LEVEL=info
ExecStart=/usr/bin/node /opt/order-api/src/main.js
Restart=always
journalctl -u order-api -f

11. Log Rotation#

/var/log/order-api/*.log {
    daily
    rotate 14
    missingok
    notifempty
    compress
    delaycompress
    copytruncate
    create 0640 app app
}
sudo logrotate -d /etc/logrotate.d/order-api
sudo logrotate -f /etc/logrotate.d/order-api

12. Process Manager#

pm2 start src/main.js --name order-api
pm2 logs order-api

pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 100M
pm2 set pm2-logrotate:retain 14
pm2 set pm2-logrotate:compress true

13. Cloud Logging#

Platform Common Target
AWS ECS / EKS CloudWatch Logs / FireLens
GCP GKE / Cloud Run Cloud Logging
Azure AKS / App Service Azure Monitor / Log Analytics
Alibaba ACK Simple Log Service
Self-managed K8S Loki / Elasticsearch / OpenSearch

14. Production Checklist#

application:
    structured JSON logs
    request_id / trace_id included
    log level configurable
    secrets redacted
    unexpected errors include stack

runtime:
    container writes stdout/stderr
    VM file logs use logrotate
    centralized log backend configured