use std::time::SystemTime; use log::{Level, LevelFilter, Metadata, Record, SetLoggerError}; use time::format_description::FormatItem; use time::formatting::Formattable; use time::macros::format_description; use time::OffsetDateTime; const LOG_DATETIME_FORMAT: &[FormatItem] = format_description!( "[year]-[month]-[day] [hour]:[minute]:[second] [offset_hour \ sign:mandatory]:[offset_minute]:[offset_second]" ); #[derive(Clone, Copy)] pub struct SimpleLogger { pub level: Level, } fn time_format(dt: T, format: &(impl Formattable + ?Sized)) -> String where T: Into, { dt.into().format(format).unwrap() } impl log::Log for SimpleLogger { fn enabled(&self, metadata: &Metadata) -> bool { metadata.level() <= self.level } fn log(&self, record: &Record) { if self.enabled(record.metadata()) { println!( "{} {:5} {}:{}: {}", time_format(SystemTime::now(), &LOG_DATETIME_FORMAT), record.level(), record.file().unwrap(), record.line().unwrap(), record.args() ); } } fn flush(&self) {} } pub fn init(level: Level) -> Result<(), SetLoggerError> { log::set_boxed_logger(Box::new(SimpleLogger { level })) .map(|()| log::set_max_level(LevelFilter::Trace)) }