1extern crate chrono;
18extern crate env_logger;
19extern crate log;
20
21use anstyle::Color;
22use chrono::Local;
23use env_logger::{fmt::style::AnsiColor, Builder};
24use log::LevelFilter;
25use std::io::Write;
26
27pub trait SetupLogging {
30 fn set_logging_level(self) -> LevelFilter;
38 fn enable_logging(&self);
48}
49
50fn set_builder(loglevel: LevelFilter) {
51 let _ = Builder::new()
52 .format(|buf, record| {
53 let time_style = anstyle::Style::new()
54 .fg_color(Some((159, 80, 1).into()))
55 .bold();
56
57 let level_style = match record.level() {
58 log::Level::Info => anstyle::Style::new()
59 .fg_color(Some(Color::from(AnsiColor::Green)))
60 .bold(),
61 log::Level::Debug => anstyle::Style::new()
62 .fg_color(Some(Color::from(AnsiColor::Cyan)))
63 .bold(),
64 log::Level::Trace => anstyle::Style::new()
65 .fg_color(Some(Color::from(AnsiColor::Magenta)))
66 .bold(),
67 log::Level::Error => anstyle::Style::new()
68 .fg_color(Some(Color::from(AnsiColor::Red)))
69 .bold(),
70 log::Level::Warn => anstyle::Style::new()
71 .fg_color(Some(Color::from(AnsiColor::Yellow)))
72 .bold(),
73 };
74
75 let level = format!("{level_style}{: <5}{level_style:#}", record.level());
76 let time = format!(
77 "{time_style}{}{time_style:#}",
78 Local::now().format("%Y-%m-%dT%H:%M:%S")
79 );
80 writeln!(buf, "[{}][{}]{}", level, time, record.args())
81 })
82 .filter(None, loglevel)
83 .try_init();
84}
85
86impl SetupLogging for &str {
87 fn set_logging_level(self) -> LevelFilter {
88 match self.to_lowercase().as_str() {
89 "error" => LevelFilter::Error,
90 "warn" => LevelFilter::Warn,
91 "info" => LevelFilter::Info,
92 "debug" => LevelFilter::Debug,
93 "trace" => LevelFilter::Trace,
94 _ => LevelFilter::Info,
95 }
96 }
97
98 fn enable_logging(&self) {
99 let loglevel = self.set_logging_level();
100 set_builder(loglevel);
101 }
102}
103
104impl SetupLogging for String {
105 fn set_logging_level(self) -> LevelFilter {
106 match self.to_lowercase().as_str() {
107 "error" => LevelFilter::Error,
108 "warn" => LevelFilter::Warn,
109 "info" => LevelFilter::Info,
110 "debug" => LevelFilter::Debug,
111 "trace" => LevelFilter::Trace,
112 _ => LevelFilter::Info,
113 }
114 }
115
116 fn enable_logging(&self) {
117 let loglevel = self.clone().set_logging_level();
119 set_builder(loglevel);
120 }
121}
122
123impl SetupLogging for usize {
124 fn set_logging_level(self) -> LevelFilter {
125 match self {
126 1 => LevelFilter::Error,
127 2 => LevelFilter::Warn,
128 3 => LevelFilter::Info,
129 4 => LevelFilter::Debug,
130 5 => LevelFilter::Trace,
131 _ => LevelFilter::Info,
132 }
133 }
134
135 fn enable_logging(&self) {
136 let loglevel = self.set_logging_level();
137 set_builder(loglevel);
138 }
139}
140
141impl SetupLogging for u8 {
142 fn set_logging_level(self) -> LevelFilter {
143 match self {
144 1 => LevelFilter::Error,
145 2 => LevelFilter::Warn,
146 3 => LevelFilter::Info,
147 4 => LevelFilter::Debug,
148 5 => LevelFilter::Trace,
149 _ => LevelFilter::Info,
150 }
151 }
152
153 fn enable_logging(&self) {
154 let loglevel = self.set_logging_level();
155 set_builder(loglevel);
156 }
157}
158
159#[cfg(test)]
160mod test {
161 use super::*;
162
163 #[test]
164 fn test_set_logging_level() {
165 let info_level: u8 = 0;
166 let debug_level: u8 = 1;
167 let trace_level: u8 = 2;
168 let stupid_levels: u8 = 255;
169 let info_level_logging: LevelFilter = info_level.set_logging_level();
170 let debug_level_logging: LevelFilter = debug_level.set_logging_level();
171 let trace_level_logging: LevelFilter = trace_level.set_logging_level();
172 let stupid_levels_logging: LevelFilter = stupid_levels.set_logging_level();
173 assert_eq!(info_level_logging, LevelFilter::Info);
174 assert_eq!(debug_level_logging, LevelFilter::Debug);
175 assert_eq!(trace_level_logging, LevelFilter::Trace);
176 assert_eq!(stupid_levels_logging, LevelFilter::Trace);
177 }
178}