Logging & Monitoring
Rules
- Structured logging: JSON format with
timestamp, level, message, requestId, userId fields
- Log levels:
error (broken), warn (degraded), info (business events), debug (development only)
- Use Pino for Node.js logging — fast, structured, JSON by default
- Sentry for error tracking: initialize early, capture unhandled exceptions, add user context and breadcrumbs
- Correlate logs with request IDs — generate a UUID per request, pass through all service calls
- Never log secrets, passwords, tokens, or full credit card numbers — redact sensitive fields
- Alert on error rate spikes, not individual errors — use thresholds (e.g., >5% error rate in 5 min)
- Axiom/Datadog: ship logs via OTLP or native SDK, add custom metrics for business KPIs
- Health check endpoint:
GET /health returning { status: "ok" } with DB connectivity check
- Monitor response times at p50, p95, p99 — alert on p95 degradation
Patterns
import pino from "pino";
const logger = pino({ level: process.env.LOG_LEVEL || "info" });
logger.info({ userId, action: "checkout", orderId }, "Order placed");
logger.error({ err, requestId }, "Payment processing failed");
import * as Sentry from "@sentry/nextjs";
Sentry.init({ dsn: process.env.SENTRY_DSN, tracesSampleRate: 0.1 });
Avoid
console.log in production — use a structured logger
- Logging every request body — log summaries, not payloads
- Ignoring unhandled promise rejections — always capture them
- Alert fatigue from noisy alerts — tune thresholds, group similar errors