Logging Best Practices
Logs are how you understand what your application did in production when you weren't watching. Done well, they turn a 2 a.m. incident into a quick search; done badly, they're noise that also leaks secrets.
The shift that matters most is from human-readable strings to structured, machine-parseable events with consistent fields and a correlation ID — so you can filter, aggregate, and trace a request across services.
TL;DR
- Log structured JSON, not concatenated strings.
- Attach a correlation/request ID to every log line.
- Use the right level (DEBUG/INFO/WARN/ERROR) and be consistent.
- Never log secrets or PII — passwords, tokens, full PANs, emails.
Quick Example
A structured, contextual log line you can actually query later:
Core Concepts
Log levels
Structured logging
Emit JSON with consistent field names, an ISO-8601 timestamp, and standard metadata (service, version, environment). Machines can then filter and aggregate without fragile regex.
Context & correlation
Thread a request ID through every log for a request (and a trace/span ID across services), so you can reconstruct a single flow end to end. See OpenTelemetry.
Logs, metrics, traces
Logs are one of the three pillars of observability: logs (what happened), metrics (how much/how often), traces (where time went). Use logs for detail, not for counting — that's what metrics are for.
Best Practices
Log requests with a middleware
Redact sensitive data
Prefer an allowlist of fields to log over a blocklist of fields to hide. Redact passwords, tokens, API keys, and PII before they reach the log.
Aggregate centrally
Ship logs to a central store (ELK, Loki, CloudWatch, Datadog) with retention and alerting. Logs trapped on one box don't help during an incident.
Common Mistakes
Logging secrets or PII
Unstructured string logs
FAQ
What log level should I use?
INFO for normal operational events, WARN for recoverable oddities, ERROR for failures that need attention, DEBUG for detail you'd only want while diagnosing (usually disabled in prod). Be consistent so alerts on ERROR mean something.
Structured or plain-text logs?
Structured (JSON) for anything that goes to an aggregator — it's queryable and aggregatable. Plain text is fine only for local development where you read logs by eye.
How do I trace a request across services?
Generate or propagate a correlation/trace ID at the edge and include it on every log line and outbound call. Distributed tracing (OpenTelemetry) standardizes this with trace and span IDs.
What should I never log?
Passwords, tokens, API keys, session IDs, full card numbers, and personal data beyond what you truly need. Redact at the logging boundary so it can't slip through.
Related Topics
- Error Handling — What to log when things fail
- Monitoring — Metrics and alerting
- OpenTelemetry — Distributed tracing
- Grafana — Visualizing logs and metrics