Rust:
Logging
How to:
Let’s set up a basic logging scenario in Rust using the log
crate, which provides a logging facade, and env_logger
, a logging implementation for the log
crate. First, add them to your Cargo.toml:
[dependencies]
log = "0.4.14"
env_logger = "0.9.0"
Now, set up and initialize the logger in your main.rs
:
use log::{info, warn};
fn main() {
env_logger::init();
info!("This is an info message.");
warn!("This is a warning message.");
}
Run your app with RUST_LOG=info cargo run
, and you’ll see the output:
INFO: This is an info message.
WARN: This is a warning message.
Play around with the RUST_LOG
environment variable by setting it to error
, warn
, info
, debug
, or trace
to control the verbosity of your logs.
Deep Dive
The concept of logging isn’t anything new; it has been around since the early days of computing. Before logging was common in software, developers relied on primitive methods such as print statements or debugger tools to trace program execution. As programs grew in complexity, so too did the need for structured approaches to logging.
In Rust, the log
crate abstracts away logging implementation details, allowing developers to plug in different logging backends. While env_logger
is a common choice, there are alternatives like fern
, slog
, or tracing
each with their own set of features and configuration options.
Some considerations when implementing logging include:
Log Levels: Controlling verbosity is key. Rust’s
log
crate defines several log levels: error, warn, info, debug, and trace, in decreasing order of severity.Performance: Logging can impact performance. It’s critical to use it judiciously, making sure to avoid logging in performance-critical paths or excessively verbose logs in production.
Structured Logging: Modern best practices involve structured logging, where logs are written in a machine-readable format like JSON. Libraries like
slog
allow for structured logging in Rust, which can be indexed and queried using log management systems like ELK Stack or Splunk.Asynchronous Logging: To minimize impact on the main application, logging can be done asynchronously. This is often achieved by having the logging library write to an in-memory queue, and a separate thread processes the queue and writes logs to the destination.
Configuration: Many logging frameworks support configuration through environment variables, configuration files, and/or code. This flexibility is key for fine-tuning output in different environments (development, staging, production).
See Also
- The
log
crate documentation: https://docs.rs/log/ - The
env_logger
crate documentation: https://docs.rs/env_logger/ - Rust by Example logging page: https://doc.rust-lang.org/rust-by-example/std_misc/log.html
- The
slog
crate, an alternative logging framework: https://github.com/slog-rs/slog - Tracing, a framework for instrumenting Rust programs: https://crates.io/crates/tracing