log

A lightweight logging facade for Rust that decouples libraries from the logging implementation applications choose.

Library
Cargo
v0.4.34
2,552 stars
MIT OR Apache-2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
71 /100 Good
Development Activity 60
Maintenance 48
Community 76
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
90 /100 Excellent
Architecture 92
Code Quality 90
Innovation 88
Learning Curve 90

log is the de facto standard logging facade for the Rust ecosystem. It provides a single, lightweight logging API built around five leveled macros - error!, warn!, info!, debug! and trace! - that libraries call without committing to any particular output backend. Applications then select and initialize a compatible logger implementation (such as env_logger, fern, or log4rs) at startup, so the same instrumented code can log to the console, a file, syslog, or anywhere else.

When no logger is installed, log falls back to a zero-cost noop that reduces each call to an integer load, comparison, and jump, making it safe to instrument hot paths. Optional compile-time level filtering and an opt-in structured key-value (kv) API round out a facade that is depended on by a huge share of the crates.io registry.

What You Get

  • Five leveled logging macros - error!, warn!, info!, debug! and trace! - plus the general log! macro, all accepting println!-style format strings.
  • The Log trait and a global logger registration API (set_logger / set_boxed_logger) that any backend can implement.
  • A zero-cost noop fallback when no logger is initialized, so instrumentation is safe to leave in hot paths.
  • Compile-time and runtime level filtering, including release-specific max-level features to strip verbose logging from production builds.
  • An optional structured logging (kv) API for attaching typed key-value data to records via Serde or sval.

Common Use Cases

  • Instrumenting a reusable library so downstream consumers can capture its diagnostics without dictating their logging stack.
  • Wiring an application to a concrete backend (env_logger, fern, log4rs, tracing-log) initialized once at startup.
  • Stripping debug and trace calls from release binaries at compile time using the release_max_level_* features for zero runtime overhead.
  • Attaching structured key-value context to log records for machine-parseable, searchable output.

Under The Hood

Architecture - The crate centers on the Log trait (enabled, log, flush) in src/lib.rs, a single global logger stored behind an AtomicUsize state machine plus a &'static dyn Log reference set once via set_logger/set_boxed_logger. The user-facing macros in src/macros.rs expand to a cheap STATIC_MAX_LEVEL comparison against the record’s level before ever touching the global logger, so disabled calls short-circuit to a noop. Record data flows through Record/RecordBuilder and Metadata structs, with __private_api.rs bridging macro expansions to the runtime; the optional kv module under src/kv/ layers a Source/Key/Value model over records for structured data. Tech Stack - Pure Rust (edition 2021, MSRV 1.71), zero required runtime dependencies; optional integrations are gated behind Cargo features - serde_core, sval/sval_ref, and value-bag power the kv_serde/kv_sval structured-logging paths. A rich feature matrix (std, kv, and the max_level_* / release_max_level_* families) controls compile-time behavior. Code Quality - Mature and heavily tested: dedicated integration and macro test suites live in tests/integration.rs and tests/macros.rs, a separate test_max_level_features/ workspace exercises the static-level feature combinations, and benches/ guards performance. Naming is consistent, the public surface is small and well-documented with doc examples that double as doctests, and 138 contributors over a decade reflect strong review discipline. API Design - Exceptionally ergonomic: instrumenting code is a one-line use log::info; plus a println!-style call, and the facade/implementation split means library authors need make no backend decisions. The macros accept optional target: and logger: arguments and inline capture syntax, the structured kv extensions are opt-in so newcomers are never exposed to complexity they don’t need, and near-zero boilerplate is required to get started.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers