We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Structured Logging

Up to now we've been logging messages as raw strings, with metadata strewn inconsistently throughout each message. If you've ever tried to debug an application that uses such sloppy logs, you've probably hit these limitations:

  • Readability: Raw strings are hard to read, especially when they include compact JSON or XML.
  • Aggregation: Plain-old strings lack a known structure, which makes them hard to aggregate across event types.
  • Searchability: Raw strings are hard to search, making it difficult to find specific patterns.

Structured logging solves these problems.

"Structured logging" doesn't refer to one specific shape of log entry. It means using some consistent structure, typically key-value pairs. Say we have this raw unstructured log:

User 9284 failed to login at 2024-10-01T12:34:56Z from IP address 102.32.21.192

Instead, let's use a structured log with key-value pairs. In Go, that's typically done with log/slog:

slog.Error("login failed",
	"user_id", 9284,
	"timestamp", "2024-10-01T12:34:56Z",
	"ip_address", "102.32.21.192")

It produces an entry that can be serialized to text:

time=2024-10-01T12:34:56Z level=ERROR msg="login failed" user_id=9284 timestamp=2024-10-01T12:34:56Z ip_address=102.32.21.192

Or to a structured object for storage in a log aggregation system:

{
  "time": "2024-10-01T12:34:56Z",
  "level": "ERROR",
  "msg": "login failed",
  "user_id": 9284,
  "timestamp": "2024-10-01T12:34:56Z",
  "ip_address": "102.32.21.192"
}

Click to play video