Logging in Rust
Here’s the translation of the Go logging example to Rust, formatted in Markdown suitable for Hugo:
Rust provides several options for logging, including the standard library’s log
crate and more feature-rich third-party crates like env_logger
and slog
. In this example, we’ll use both the log
crate and slog
for structured logging.
First, let’s add the necessary dependencies to your Cargo.toml
:
[dependencies]
log = "0.4"
env_logger = "0.10"
slog = "2.7"
slog-json = "2.6"
slog-term = "2.9"
Now, let’s look at the Rust code:
use log::{info, set_logger, set_max_level, LevelFilter, Log, Metadata, Record};
use slog::{Drain, Logger, o};
use slog_json::Json;
use std::io::Write;
struct SimpleLogger;
impl Log for SimpleLogger {
fn enabled(&self, metadata: &Metadata) -> bool {
metadata.level() <= log::Level::Info
}
fn log(&self, record: &Record) {
if self.enabled(record.metadata()) {
println!("{} - {}", record.level(), record.args());
}
}
fn flush(&self) {}
}
static LOGGER: SimpleLogger = SimpleLogger;
fn main() {
// Set up the simple logger
set_logger(&LOGGER).unwrap();
set_max_level(LevelFilter::Info);
// Using the simple logger
info!("standard logger");
// Logging with timestamp
env_logger::Builder::from_default_env()
.format(|buf, record| {
writeln!(buf,
"{} [{}] - {}",
chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.6f"),
record.level(),
record.args()
)
})
.init();
info!("with microsecond precision");
// Logging with file and line information
log::logger().flush();
env_logger::builder()
.format(|buf, record| {
writeln!(buf,
"{} {}:{} - {}",
record.level(),
record.file().unwrap_or("unknown"),
record.line().unwrap_or(0),
record.args()
)
})
.init();
info!("with file/line");
// Creating a custom logger with slog
let plain = slog_term::PlainSyncDecorator::new(std::io::stdout());
let logger = Logger::root(
slog_term::FullFormat::new(plain).build().fuse(),
o!("version" => env!("CARGO_PKG_VERSION"))
);
slog::info!(logger, "from custom logger"; "key" => "val");
// Logging to a string buffer
let mut buf = Vec::new();
let writer = std::io::Cursor::new(&mut buf);
let json = Json::default(writer).build().fuse();
let buffer_logger = Logger::root(json, o!());
slog::info!(buffer_logger, "hello"; "to" => "buffer");
println!("from buffer: {}", String::from_utf8_lossy(&buf));
// Structured logging with slog-json
let json_drain = Json::new(std::io::stderr())
.set_pretty(false)
.build()
.fuse();
let json_logger = Logger::root(json_drain, o!());
slog::info!(json_logger, "hi there");
slog::info!(json_logger, "hello again"; "key" => "val", "age" => 25);
}
This Rust code demonstrates various logging techniques:
We start by setting up a simple logger using the
log
crate.We then use
env_logger
to add timestamps to our log messages.Next, we show how to include file and line information in log messages.
We create a custom logger using
slog
with a terminal output.We demonstrate logging to a buffer.
Finally, we use
slog-json
for structured logging in JSON format.
To run the program:
$ cargo run
Sample output (the date and time emitted will depend on when the example ran):
INFO - standard logger
2023-08-22 10:45:16.904141 [INFO] - with microsecond precision
INFO src/main.rs:67 - with file/line
Aug 22 10:45:16.904166.INFO from custom logger version="0.1.0" key="val"
from buffer: {"msg":"hello","to":"buffer","level":"info","ts":"2023-08-22T10:45:16.904178Z"}
{"msg":"hi there","level":"info","ts":"2023-08-22T10:45:16Z"}
{"msg":"hello again","key":"val","age":25,"level":"info","ts":"2023-08-22T10:45:16Z"}
This example showcases different logging methods in Rust, from basic logging to structured logging with JSON output. The concepts are similar to those in other languages, but the implementation details are specific to Rust and its ecosystem.