1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
use log::{LevelFilter, Record, Log, Metadata, Level, SetLoggerError}; use colored::*; use chrono::Local; pub use log::{info, warn, error, debug, trace}; pub struct BasicLog { output_level: LevelFilter, } pub struct LoggerSettings { enable_debug: bool, enable_trace: bool, } impl LoggerSettings { pub fn new() -> Self { Self { enable_debug: false, enable_trace: false, } } pub fn enable_debug(mut self) -> Self { self.enable_debug = true; self } pub fn enable_trace(mut self) -> Self { self.enable_trace = true; self } } impl Default for LoggerSettings { fn default() -> Self { Self::new() } } impl BasicLog { fn set_settings(logger: &mut BasicLog, s: LoggerSettings) { logger.output_level = { if s.enable_trace { LevelFilter::Trace } else if s.enable_debug { LevelFilter::Debug } else { logger.output_level } }; } #[must_use = "Must initialise logger: .init()"] pub fn new() -> Self { Self { output_level: LevelFilter::Info, } } #[must_use = "Must initialise logger: .init()"] pub fn new_with_settings<F>(s: F) -> Self where F: FnOnce(LoggerSettings) -> LoggerSettings { let mut logger = Self::default(); Self::set_settings(&mut logger, s(LoggerSettings::default())); logger } pub fn new_with_struct(s: LoggerSettings) -> Self { let mut logger = Self::default(); Self::set_settings(&mut logger, s); logger } pub fn init(self) -> Result<(), SetLoggerError> { log::set_max_level(self.output_level); log::set_boxed_logger(Box::new(self))?; Ok(()) } } impl Default for BasicLog { fn default() -> Self { Self::new() } } impl Log for BasicLog { fn enabled(&self, metadata: &Metadata) -> bool { metadata.level().to_level_filter() <= self.output_level } fn log(&self, rec: &Record) { use Level::*; let log_type = match rec.level() { Error => "ERROR".bright_red(), Warn => "WARN".bright_yellow(), Info => "INFO".bright_blue(), Debug => "DEBUG".green(), Trace => "trace".bright_purple(), }; let time = Local::now() .format("%d %B %Y %H:%M:%S,%3f"); println!("{log_type:<5} | {time} - {msg}", log_type = log_type, time = time, msg = rec.args() ) } fn flush(&self) { } } #[cfg(test)] mod tests { use crate::BasicLog; use log::SetLoggerError; #[test] fn it_works() { assert_eq!(2 + 2, 4); } #[test] fn create_logger() -> Result<(), SetLoggerError> { BasicLog::new().init()?; Ok(()) } #[test] fn set_settings() { use crate::LoggerSettings; let mut logger = BasicLog::new(); let s = LoggerSettings::default().enable_debug(); BasicLog::set_settings(&mut logger, s); assert_eq!(logger.output_level, log::LevelFilter::Debug); } }