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

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

References