Skip to content

feat(logging): replace Winston with Pino structured JSON logging and correlation IDs - #2

Open
CodedSceptre wants to merge 1 commit into
mainfrom
feature/pino-logging
Open

feat(logging): replace Winston with Pino structured JSON logging and correlation IDs#2
CodedSceptre wants to merge 1 commit into
mainfrom
feature/pino-logging

Conversation

@CodedSceptre

@CodedSceptre CodedSceptre commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Summary

Replace Winston with Pino for structured JSON logging with per-request correlation ID tracing.

What was implemented

  • Pino logger (backend/src/logger.ts) — replaces Winston with a Pino instance configured from the LOG_LEVEL env var (supports fatal, error, warn, info, debug, trace)
  • Sensitive field redaction — Pino's built-in redact option strips authorization, password, token, privateKey, apiKey, secret, mnemonic, and nested variants (body.password, req.headers.authorization, etc.) before writing any log line
  • Correlation ID middleware (correlationIdMiddleware()) — reads X-Request-ID (priority) or X-Correlation-ID from incoming headers, falls back to a fresh UUID v4; stamps req.correlationId and a child req.log logger; echoes the ID back in the X-Correlation-ID response header
  • Request logger middleware (createRequestLogger()) — logs one structured JSON line per request/response containing correlationId, method, path, status, durationMs, ip; skips /api/health to reduce noise; uses error/warn/info level based on HTTP status
  • Loki/Promtail compatibility — all log lines are single-line JSON with level as a string label (not an integer), matching Promtail's label-extraction pipeline
  • Config update (backend/src/config/index.ts) — LOG_LEVEL Zod enum updated from Winston's levels (http, verbose, silly) to Pino's levels (fatal, trace)
  • Env example update (backend/.env.example) — comment clarifies the Pino level names

Tests

  • 14 new unit tests in backend/src/middleware/__tests__/pinoLogger.test.ts covering:
    • Pino logger instance methods
    • correlationIdMiddleware — UUID generation, header propagation (X-Request-ID and X-Correlation-ID), req.log child logger attachment
    • createRequestLogger — response flow, health-check exclusion, status-level mapping
    • Stream-injection test verifying JSON log line structure and field names

Acceptance criteria

  • Pino logger configured with log level from LOG_LEVEL env var
  • Every HTTP request logs: method, path, status, duration, correlationId
  • Correlation ID from X-Request-ID header or generated if absent
  • Correlation ID passed to all downstream calls via req.log child logger
  • Sensitive fields redacted (tokens, private keys)
  • Logs shipped to Loki via Promtail (JSON format compatible with Promtail config)

Closes soterika#298

…on IDs

- Rewrite logger.ts: swap Winston for Pino v9 (JSON output, Loki-compatible)
- Log level driven by LOG_LEVEL env var (default: info)
- Sensitive field redaction at serialisation time: authorization, password,
  token, accessToken, refreshToken, privateKey, apiKey, secret, mnemonic, seed
- correlationIdMiddleware(): reads X-Request-ID or X-Correlation-ID header,
  falls back to UUID v4; echoes ID in X-Correlation-ID response header
- createRequestLogger(): logs method, path, status, durationMs, correlationId
  for every request; skips /api/health to reduce noise; uses error/warn/info
  level based on HTTP status
- Child logger (req.log) attached to every request for downstream use
- Update LOG_LEVEL enum in config/index.ts to Pino levels:
  fatal | error | warn | info | debug | trace
- Add pino@^9.7.0 and pino-http@^10.4.0 to package.json
- 14 Vitest tests: logger methods, correlationId middleware (UUID gen,
  header propagation, child logger), request logger (flow, health skip,
  level selection, correlation ID propagation), stream-injection log content

Closes #2
@CodedSceptre CodedSceptre changed the title feat: replace Winston with Pino structured JSON logging feat(logging): replace Winston with Pino structured JSON logging and correlation IDs Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement structured logging with Pino and correlation IDs

1 participant