Configure Logging
Enable log levels per module
Creates two modules foo
and nested foo::bar
with logging directives
controlled separately with RUST_LOG
environmental variable.
mod foo { mod bar { pub fn run() { log::warn!("[bar] warn"); log::info!("[bar] info"); log::debug!("[bar] debug"); } } pub fn run() { log::warn!("[foo] warn"); log::info!("[foo] info"); log::debug!("[foo] debug"); bar::run(); } } fn main() { env_logger::init(); log::warn!("[root] warn"); log::info!("[root] info"); log::debug!("[root] debug"); foo::run(); }
RUST_LOG
environment variable controls env_logger
output.
Module declarations take comma separated entries formatted like
path::to::module=log_level
. From the cloned Rust Cookbook repository,
run the example as follows:
RUST_LOG="warn,log_mod::foo=info,log_mod::foo::bar=debug" cargo run --example log-mod
This sets the default log::Level
to warn
for the entire
application, module foo
in the application to info
, and sub-module
foo::bar
to debug
.
Note that because the example filename has a minus sign ('-') in it, which is converted to and underscore ('_') because module names cannot have a minus sign.
[2022-05-21T12:30:34Z WARN log_mod] [root] warn
[2022-05-21T12:30:34Z WARN log_mod::foo] [foo] warn
[2022-05-21T12:30:34Z INFO log_mod::foo] [foo] info
[2022-05-21T12:30:34Z WARN log_mod::foo::bar] [bar] warn
[2022-05-21T12:30:34Z INFO log_mod::foo::bar] [bar] info
[2022-05-21T12:30:34Z DEBUG log_mod::foo::bar] [bar] debug
Use a custom environment variable to set up logging
Builder
configures logging.
[Builder::parse
] parses MY_APP_LOG
environment variable contents in the form of RUST_LOG
syntax.
Then, Builder::init
initializes the logger.
All these steps are normally done internally by env_logger::init
.
use log::{error, info, warn}; use env_logger::Builder; fn main() { Builder::new() .parse_env("MY_APP_LOG") .init(); info!("informational message"); warn!("warning message"); error!("this is an error {}", "message"); }
Without setting MY_APP_LOG
, the output of the example will be something like:
$ cargo run --quiet --example log-env-variable
[2022-04-17T00:52:42Z ERROR log_env_variable] this is an error message
When setting the environment variable MY_APP_LOG
with a different log level, more
will be printed:
$ MY_APP_LOG=warn cargo run --quiet --example log-env-variable
[2022-04-17T00:56:51Z WARN log_env_variable] warning message
[2022-04-17T00:56:51Z ERROR log_env_variable] this is an error message
Include timestamp in log messages
Creates a custom logger configuration with Builder
.
Each log entry calls Local::now
to get the current DateTime
in local
timezone and uses DateTime::format
with strftime::specifiers
to format
a timestamp used in the final log.
The example calls Builder::format
to set a closure which formats each
message text with timestamp, Record::level
and body (Record::args
).
use std::io::Write; use chrono::Local; use env_logger::Builder; use log::LevelFilter; fn main() { Builder::new() .format(|buf, record| { writeln!(buf, "{} [{}] - {}", Local::now().format("%Y-%m-%dT%H:%M:%S"), record.level(), record.args() ) }) .filter(None, LevelFilter::Info) .init(); log::warn!("warn"); log::info!("info"); log::debug!("debug"); }
stderr output will contain
2017-05-22T21:57:06 [WARN] - warn
2017-05-22T21:57:06 [INFO] - info
Log messages to a custom location
log4rs configures log output to a custom location. log4rs can use either an external YAML file or a builder configuration.
Create the log configuration with log4rs::append::file::FileAppender
. An
appender defines the logging destination. The configuration continues with
encoding using a custom pattern from log4rs::encode::pattern
.
Assigns the configuration to log4rs::config::Config
and sets the default
log::LevelFilter
.
use std::error::Error; use log::LevelFilter; use log4rs::append::file::FileAppender; use log4rs::encode::pattern::PatternEncoder; use log4rs::config::{Appender, Config, Root}; fn main() -> Result<(), Box<dyn Error>> { let logfile = FileAppender::builder() .encoder(Box::new(PatternEncoder::new("{l} - {m}\n"))) .build("log/output.log")?; let config = Config::builder() .appender(Appender::builder().build("logfile", Box::new(logfile))) .build(Root::builder() .appender("logfile") .build(LevelFilter::Info))?; log4rs::init_config(config)?; log::info!("Hello, world!"); Ok(()) }