Observability Basics (Structured Logs, Correlation IDs)
Understanding a system's internal state from its external outputs — structured logs and a correlation id threaded through a request's full call chain.
Purpose
Observability means a system’s internal behavior can be understood from its external outputs — logs, traces, metrics — without attaching a debugger to a live instance. Structured logging and correlation IDs are the everyday building blocks.
Example
logger.info('order.placed', {
orderId: order.id,
userId: order.userId,
amount: order.total,
correlationId: request.correlationId,
});
Behavior notes
- A structured log uses consistent, machine-parseable fields (JSON, typically) rather than a
free-text message — enables querying and aggregation (“show me every
order.placedevent for this user”) that free-text logs make much harder. - A correlation id is generated once per incoming request and threaded through every downstream call and log line it causes, making it possible to reconstruct a single request’s full path across multiple services or async steps after the fact.
- A consistent error taxonomy (a small, fixed set of error categories used across a codebase) lets monitoring and alerting key off category rather than parsing free-text error messages.
- Metrics (counters, gauges, histograms) aggregate over many events for trend visibility; traces follow one request’s timing across service boundaries; logs capture discrete events — the three complement each other rather than substituting for one another.
Common mistakes
- Logging free-text messages with no consistent structure, making later querying and aggregation difficult or impossible.
- Generating a correlation id per service instead of per originating request, losing the ability to trace a single request’s full path.
Runtime notes
A design practice applicable to any backend or client system — specific tooling (log aggregators, tracing systems) varies, but the underlying principles are runtime-agnostic.