Logging libraries look interchangeable until they're not. The choice affects throughput at scale, debugging quality, and operational ergonomics. The wrong choice costs more than you'd guess; the right choice is invisible.
Structured output is non-negotiable
JSON or logfmt by default. Free-text logs in 2026 mean grep instead of query. Every modern library supports structured. If yours doesn't, replace it.
Performance dimension
High-throughput services: 'low-cost when log level is off' matters more than raw write speed. Look for lazy evaluation (don't format if disabled). Allocation-free hot paths. Examples: Zap (Go), Rust's tracing, Java's Log4j 2 with async appenders.
Context propagation
Trace ID, request ID, user ID — every log line should have them. Library support for 'add context once, get it on every log' (MDC in Java, structured contexts in Go/Rust) saves thousands of explicit context-passing lines.
Async vs sync writes
Sync writes: simple, may block on disk I/O. Async: throughput up, but may lose logs on crash. Trade-off matters at high RPS. Async with periodic flush is the common compromise.
Ecosystem fit
Does your APM (Datadog, New Relic, etc.) auto-parse this library's output? Does it integrate with your tracing library? Picking the popular library in your language is usually right because of ecosystem.