//! Logging module. //! //! For test logging see [`mod@test`]. #[cfg(feature = "test")] pub mod test; use std::io::{self, Write}; use chrono::prelude::*; use colored::*; use log::{Level, Log, Metadata, Record}; /// A logger that logs to `stdout`. pub struct Logger; impl Logger { pub fn new() -> Self { Self } } impl Default for Logger { fn default() -> Self { Self::new() } } impl Log for Logger { fn enabled(&self, metadata: &Metadata) -> bool { metadata.level() <= log::max_level() } fn log(&self, record: &Record) { if self.enabled(record.metadata()) { let target = record.target(); let message = format!( "{:<5} {:<8} {}", record.level(), target.cyan(), record.args() ); let message = format!( "{} {}", Local::now().to_rfc3339_opts(SecondsFormat::Millis, true), message, ); let message = match record.level() { Level::Error => message.red(), Level::Warn => message.yellow(), Level::Info => message.normal(), Level::Debug => message.dimmed(), Level::Trace => message.white().dimmed(), }; writeln!(&mut io::stdout(), "{message}").expect("write shouldn't fail"); } } fn flush(&self) {} } /// A logger that logs to `stderr`. pub struct StderrLogger; impl StderrLogger { pub fn new() -> Self { Self } } impl Default for StderrLogger { fn default() -> Self { Self::new() } } impl Log for StderrLogger { fn enabled(&self, metadata: &Metadata) -> bool { metadata.level() <= log::max_level() } fn log(&self, record: &Record) { if self.enabled(record.metadata()) { let message = format!( "{:<5} {:<8} {}", record.level(), record.target(), record.args() ); writeln!(&mut io::stderr(), "{message}").expect("write shouldn't fail"); } } fn flush(&self) {} } /// Get the level set by the environment variable `RUST_LOG`, if /// present. pub fn env_level() -> Option { let level = std::env::var("RUST_LOG").ok()?; level.parse().ok() }