Logging and Observability
Turn a running Node service into something you can actually see inside
- explain why structured (JSON) logging beats
console.login production, and use pino to produce it; - choose the right log level and configure it per environment;
- attach a correlation id to every log line of a request using
AsyncLocalStorage; - expose metrics in Prometheus format and reason about the RED method;
- describe how distributed tracing stitches spans into one trace with context propagation;
- write correct liveness and readiness health checks.
1. Observability vs monitoring: the three pillars
Monitoring tells you whether the system is healthy against known thresholds ("CPU > 90%", "error rate > 1%"). Observability is broader: it is the property that lets you explore why, following a trail from a symptom to a root cause you had not predefined. You cannot bolt it on afterwards — a service is observable only if it was instrumented to emit useful signals.
The three pillars each answer a different question:
- Logs — "what exactly happened at this moment?" Discrete, timestamped events with context. High detail, high volume, higher cost per byte.
- Metrics — "how much / how many / how fast, over time?" Cheap numeric time series (counters, gauges, histograms) that aggregate well and drive dashboards and alerts.
- Traces — "what was the end-to-end path of this one request?" A tree of timed spans across services, showing where latency actually went.
They are complementary, not interchangeable. A metric alert fires ("checkout latency p99 spiked"); a trace shows the slow span is a database call; the logs on that span reveal the exact query and the row that locked. Use each for what it is good at.