Logging in Rust: Overview of the Best Libraries and Solutions for Your Project

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Logging for Rust: Best Solutions

Logging is a critically important component of any serious Rust application. It helps track code execution, identify errors, monitor performance, and analyze system behavior in production. In this article, we will review the main libraries for logging in the Rust ecosystem, their features, advantages, and usage examples.



Why is Logging Important in Rust?

Rust, being a systems language, places high demands on reliability and predictability. Logging allows you to:

  • Track execution flow in multithreaded applications.
  • Record unexpected states and panics.
  • Conduct security audits.
  • Collect metrics for performance optimization.


Main Libraries for Logging



1. log — Logging Facade

log is the standard facade (abstract layer) for logging in Rust. It defines the macros info!, warn!, error!, debug!, trace! and the Log trait. By itself, it does not output logs — a backend (e.g., env_logger or slog) is required for that.

// Cargo.toml[dependencies]log = "0.4"

// main.rsuse log::{info, warn, error};

fn main() { // Backend initialization is mandatory env_logger::init(); info!("Application started"); warn!("Low memory: {}%", 15); error!("Critical error: {}", "connection failure");}


2. env_logger — Simple and Fast Backend

env_logger is the most popular backend for log. It is configured via the RUST_LOG environment variable. Supports filtering by modules and levels.

// Installation// cargo add env_logger

// Configuration exampleuse log::LevelFilter;

fn main() { env_logger::Builder::from_env( env_logger::Env::default().default_filter_or("info") ).init();

log::info!("Running with INFO level"); log::debug!("This message will not be displayed");}

// Run with variable:// RUST_LOG=debug cargo run


3. slog — Structured Logging

slog is a powerful library for structured logging. Supports key-value pairs, logger chains, asynchronous writing, and custom drivers. Ideal for complex systems where context is important.

// Cargo.toml[dependencies]slog = "2.7"slog-term = "2.9"slog-json = "2.6"

// main.rsuse slog::{o, Drain, Logger, info};

fn main() { let decorator = slog_term::TermDecorator::new().build(); let drain = slog_term::FullFormat::new(decorator).build().fuse(); let drain = slog_async::Async::new(drain).build().fuse();

let logger = Logger::root(drain, o!("version" => "1.0"));

info!(logger, "Server started"; "port" => 8080, "env" => "production");}


4. tracing — Instrumentation and Tracing

tracing is a modern library from the Tokio team, designed for structured logging and tracing. It allows creating spans — time intervals with context, which is indispensable for asynchronous and multithreaded applications.

// Cargo.toml[dependencies]tracing = "0.1"tracing-subscriber = "0.3"

// main.rsuse tracing::{info, span, Level};use tracing_subscriber::fmt;

fn main() { // Initialize subscriber fmt::init();

let span = span!(Level::INFO, "main", "app" = "my_service"); let _guard = span.enter();

info!("Processing request"); // Logs inside the span automatically contain context}


Library Comparison

  • log + env_logger: Simplicity, minimalism, suitable for small projects

Recommendations