Best practices for logging, metrics, tracing, alerting, and observability — structured logging, correlation IDs, Prometheus metrics, distributed tracing, and dashboard design. Use when adding logging, designing monitoring, setting up dashboards, debugging production issues, or whenever the user mentions "logging," "observability," "metrics," "tracing," "Prometheus," "Grafana," "Jaeger," "OpenTelemetry," "structured logging," or "alerting."
Logging & Observability
The Three Pillars
Logs — discrete events: "user logged in at 10:32:14"
Metrics — aggregatable numbers: 50 req/s, 200ms p99 latency
Traces — request lifecycle across services: "order #123 took 400ms total"
All three are needed. None replaces the others.
Structured Logging
Log in JSON format — machine-readable, parsable, searchable.
// ❌ Unstructured (text search grey area)
"User 123 created order 456 for $50.99"// ✅ Structured (parseable, filterable)
{"level":"info","time":"2025-07-25T10:32:14Z","message":"order created","service":"order-service","trace_id":"abc123def456","user_id":"123","order_id":"456","amount":50.99,"currency":"USD","duration_ms":45}
Log Levels — Use Consistently
Level
When
Example
ERROR
Something is broken. Needs human attention.
DB connection failed, payment declined
WARN
Something unexpected but recoverable.
Retry succeeded, rate limit approaching
INFO
Notable lifecycle events. User-triggered actions.
Order created, user signed up, scheduled job ran
DEBUG
Detailed context for debugging. Off in prod.
SQL query, request body, iteration details
TRACE
Very fine-grained. For deep debugging only.
Function entry/exit, loop iterations
What to Log
Every error with stack trace, context, and correlation ID.
Every request at INFO — method, path, status, duration.
Business events — state transitions (order created → paid → shipped).