Structured logging is fundamental to understanding distributed systems, but its real power isn’t in making logs readable; it’s in making them queryable.

Let’s look at a simple web request flowing through a few services.

Imagine a user requests /users/123.

Service A (API Gateway) receives the request. It logs:

{
  "timestamp": "2023-10-27T10:00:00Z",
  "level": "INFO",
  "service": "api-gateway",
  "trace_id": "abc-123",
  "span_id": "span-a",
  "request_method": "GET",
  "request_path": "/users/123",
  "remote_addr": "192.168.1.10",
  "user_id": "user-456"
}

Then, it forwards the request to Service B (User Service), adding trace_id and span_id.

Service B (User Service) receives the request. It logs:

{
  "timestamp": "2023-10-27T10:00:01Z",
  "level": "INFO",
  "service": "user-service",
  "trace_id": "abc-123",
  "span_id": "span-b",
  "parent_span_id": "span-a",
  "request_method": "GET",
  "request_path": "/users/123",
  "user_id": "user-456",
  "db_query_time_ms": 50
}

It fetches data from Service C (Database Service).

Service C (Database Service) logs:

{
  "timestamp": "2023-10-27T10:00:01Z",
  "level": "INFO",
  "service": "database-service",
  "trace_id": "abc-123",
  "span_id": "span-c",
  "parent_span_id": "span-b",
  "operation": "SELECT",
  "table": "users",
  "rows_returned": 1,
  "query_duration_ms": 45
}

All these logs, if sent to a central logging system like Elasticsearch, Splunk, or Loki, can be filtered, aggregated, and analyzed.

The problem structured logging solves is the ambiguity and manual parsing inherent in plain-text logs. When you have hundreds of services, each logging in its own format, finding a specific error, correlating events across services, or understanding performance bottlenecks becomes a Herculean task. Structured logging, by enforcing a consistent, machine-readable format (typically JSON), turns logs from a narrative into a dataset.

The key is to include context that allows you to answer questions like:

  • "What happened during the request with trace_id: abc-123?"
  • "Which requests from user_id: user-456 were slow?"
  • "Show me all SELECT operations on the users table that took longer than 30ms."
  • "What’s the average db_query_time_ms for requests handled by user-service?"

This requires a disciplined approach to logging. Every service involved in a request should log events that include a consistent trace_id to link them together. span_id and parent_span_id (as seen in the example) further refine this, allowing you to trace the causality and duration of individual operations within a distributed trace.

Beyond tracing, other common and crucial fields include:

  • service: The name of the service generating the log.
  • level: Log severity (e.g., INFO, WARN, ERROR, DEBUG).
  • timestamp: Standardized time, ideally UTC.
  • request_id or correlation_id: A unique ID for a specific incoming request.
  • user_id or account_id: The principal making the request.
  • http.method, http.url, http.status_code: For web services.
  • db.statement, db.table, db.duration_ms: For database interactions.
  • error.message, error.type, error.stacktrace: When things go wrong.

The most surprising truth about structured logging is that its primary benefit isn’t human readability, but the ability to perform complex aggregations and anomaly detection across vast log volumes. When you see a log line like {"service": "payment-processor", "transaction_id": "tx-xyz", "event": "charge_failed", "reason_code": "INSUFFICIENT_FUNDS", "amount_usd": 199.99}, you can immediately write a query like count(*) WHERE service = 'payment-processor' AND event = 'charge_failed' AND reason_code = 'INSUFFICIENT_FUNDS' to understand the frequency of a specific failure mode, or avg(amount_usd) WHERE service = 'payment-processor' AND event = 'charge_failed' to see how much money is being lost to that specific failure.

The next step from here is understanding how to make these logs actionable through alerting based on specific structured fields and counts.

Want structured learning?

Take the full Distributed Systems course →