use env_logger::Builder;
use log::LevelFilter;
use std::env;
use std::io::Write;
pub fn init_logging(verbose: u8, quiet: bool) {
let use_env = env::var("RUST_LOG").is_ok();
let mut builder = Builder::new();
if use_env {
builder.parse_default_env();
log::debug!(
"Logging initialized from RUST_LOG environment variable: {:?}",
env::var("RUST_LOG").ok()
);
} else {
let level = determine_level(verbose, quiet);
builder.filter_level(level);
}
configure_format(&mut builder, verbose);
builder.init();
if !use_env {
let level = determine_level(verbose, quiet);
log::debug!("Logging initialized at level: {:?}", level);
}
}
fn determine_level(verbose: u8, quiet: bool) -> LevelFilter {
if quiet {
LevelFilter::Error
} else {
match verbose {
0 => LevelFilter::Info,
1 => LevelFilter::Debug,
_ => LevelFilter::Trace,
}
}
}
fn configure_format(builder: &mut Builder, verbose: u8) {
#[cfg(debug_assertions)]
{
builder.format(move |buf, record| {
let timestamp = buf.timestamp_seconds();
let level = record.level();
let level_style = buf.default_level_style(level);
if verbose >= 2 {
writeln!(
buf,
"{} {level_style}{:<5}{level_style:#} [{}] {}",
timestamp,
level,
record.module_path().unwrap_or("unknown"),
record.args()
)
} else if verbose >= 1 {
writeln!(
buf,
"{} {level_style}{:<5}{level_style:#} [{}] {}",
timestamp,
level,
record.module_path().unwrap_or("unknown"),
record.args()
)
} else {
writeln!(
buf,
"{} {level_style}{:<5}{level_style:#} {}",
timestamp,
level,
record.args()
)
}
});
}
#[cfg(not(debug_assertions))]
{
let _ = verbose; builder.format(|buf, record| {
let level = record.level();
let level_style = buf.default_level_style(level);
writeln!(
buf,
"{level_style}{:<5}{level_style:#} {}",
level,
record.args()
)
});
}
}
pub fn current_level_name() -> &'static str {
match log::max_level() {
LevelFilter::Off => "off",
LevelFilter::Error => "error",
LevelFilter::Warn => "warn",
LevelFilter::Info => "info",
LevelFilter::Debug => "debug",
LevelFilter::Trace => "trace",
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_determine_level_default() {
assert_eq!(determine_level(0, false), LevelFilter::Info);
}
#[test]
fn test_determine_level_verbose() {
assert_eq!(determine_level(1, false), LevelFilter::Debug);
}
#[test]
fn test_determine_level_trace() {
assert_eq!(determine_level(2, false), LevelFilter::Trace);
assert_eq!(determine_level(3, false), LevelFilter::Trace);
}
#[test]
fn test_determine_level_quiet() {
assert_eq!(determine_level(0, true), LevelFilter::Error);
}
#[test]
fn test_determine_level_quiet_overrides_verbose() {
assert_eq!(determine_level(2, true), LevelFilter::Error);
}
#[test]
fn test_current_level_name_values() {
let name = current_level_name();
assert!(
["off", "error", "warn", "info", "debug", "trace"].contains(&name),
"Unexpected level name: {}",
name
);
}
}