fstdout_logger/config/
mod.rs1use log::LevelFilter;
7use std::collections::HashMap;
8
9#[derive(Debug, Clone)]
19pub struct ModuleFilters {
20 filters: HashMap<String, LevelFilter>,
22 default_level: LevelFilter,
24}
25
26impl Default for ModuleFilters {
27 fn default() -> Self {
28 Self {
29 filters: HashMap::new(),
30 default_level: LevelFilter::Info,
31 }
32 }
33}
34
35impl ModuleFilters {
36 pub fn new(default_level: LevelFilter) -> Self {
38 Self {
39 filters: HashMap::new(),
40 default_level,
41 }
42 }
43
44 pub fn from_env() -> Self {
52 let rust_log = std::env::var("RUST_LOG").unwrap_or_default();
53 Self::parse(&rust_log)
54 }
55
56 pub fn parse(s: &str) -> Self {
58 let mut filters = HashMap::new();
59 let mut default_level = LevelFilter::Info;
60
61 if s.is_empty() {
62 return Self {
63 filters,
64 default_level,
65 };
66 }
67
68 for part in s.split(',') {
70 let part = part.trim();
71 if part.is_empty() {
72 continue;
73 }
74
75 if let Some((module, level_str)) = part.split_once('=') {
77 let module = module.trim();
78 let level_str = level_str.trim();
79
80 if let Some(level) = parse_level_filter(level_str) {
81 filters.insert(module.to_string(), level);
82 }
83 } else {
84 if let Some(level) = parse_level_filter(part) {
86 default_level = level;
87 }
88 }
89 }
90
91 Self {
92 filters,
93 default_level,
94 }
95 }
96
97 pub fn add_filter(&mut self, module: impl Into<String>, level: LevelFilter) {
99 self.filters.insert(module.into(), level);
100 }
101
102 pub fn level_for(&self, module_path: &str) -> LevelFilter {
109 if let Some(&level) = self.filters.get(module_path) {
111 return level;
112 }
113
114 let mut matching_filters: Vec<_> = self
116 .filters
117 .iter()
118 .filter(|(path, _)| module_path.starts_with(path.as_str()))
119 .collect();
120
121 matching_filters.sort_by_key(|(path, _)| std::cmp::Reverse(path.len()));
122
123 if let Some(&(_, &level)) = matching_filters.first() {
124 return level;
125 }
126
127 self.default_level
129 }
130
131 pub fn default_level(&self) -> LevelFilter {
133 self.default_level
134 }
135
136 pub fn set_default_level(&mut self, level: LevelFilter) {
138 self.default_level = level;
139 }
140}
141
142fn parse_level_filter(s: &str) -> Option<LevelFilter> {
144 match s.to_lowercase().as_str() {
145 "off" => Some(LevelFilter::Off),
146 "error" => Some(LevelFilter::Error),
147 "warn" => Some(LevelFilter::Warn),
148 "info" => Some(LevelFilter::Info),
149 "debug" => Some(LevelFilter::Debug),
150 "trace" => Some(LevelFilter::Trace),
151 _ => None,
152 }
153}
154
155fn parse_log_level_env() -> Option<LevelFilter> {
165 let level_str = std::env::var("LOG_LEVEL").ok()?;
166 let level = level_str.parse::<u8>().ok()?;
167 Some(match level {
168 0 => LevelFilter::Off,
169 1 => LevelFilter::Error,
170 2 => LevelFilter::Warn,
171 3 => LevelFilter::Info,
172 4 => LevelFilter::Debug,
173 _ => LevelFilter::Trace,
174 })
175}
176
177#[derive(Debug, Clone)]
179pub struct LoggerConfig {
180 pub show_file_info: bool,
182
183 pub show_date_in_stdout: bool,
185
186 pub use_colors: bool,
188
189 pub level: LevelFilter,
191
192 pub module_filters: ModuleFilters,
194}
195
196impl Default for LoggerConfig {
197 fn default() -> Self {
208 Self {
209 show_file_info: true,
210 show_date_in_stdout: false,
211 use_colors: true,
212 level: LevelFilter::Info,
213 module_filters: ModuleFilters::new(LevelFilter::Info),
214 }
215 }
216}
217
218impl LoggerConfig {
219 pub fn new() -> Self {
220 Self::default()
221 }
222
223 pub fn builder() -> LoggerConfigBuilder {
224 LoggerConfigBuilder::default()
225 }
226
227 pub fn from_env() -> Self {
235 let module_filters = ModuleFilters::from_env();
236
237 let level = if let Some(log_level) = parse_log_level_env() {
239 log_level
240 } else {
241 module_filters.default_level()
242 };
243
244 Self {
245 show_file_info: true,
246 show_date_in_stdout: false,
247 use_colors: true,
248 level,
249 module_filters,
250 }
251 }
252
253 pub fn production() -> Self {
254 Self {
255 show_file_info: false,
256 show_date_in_stdout: false,
257 use_colors: true,
258 level: LevelFilter::Info,
259 module_filters: ModuleFilters::new(LevelFilter::Info),
260 }
261 }
262
263 pub fn development() -> Self {
264 Self {
265 show_file_info: true,
266 show_date_in_stdout: false,
267 use_colors: true,
268 level: LevelFilter::Debug,
269 module_filters: ModuleFilters::new(LevelFilter::Debug),
270 }
271 }
272}
273
274#[derive(Debug, Default)]
275pub struct LoggerConfigBuilder {
276 config: LoggerConfig,
277}
278
279impl LoggerConfigBuilder {
280 pub fn show_file_info(mut self, show: bool) -> Self {
281 self.config.show_file_info = show;
282 self
283 }
284
285 pub fn show_date_in_stdout(mut self, show: bool) -> Self {
286 self.config.show_date_in_stdout = show;
287 self
288 }
289
290 pub fn use_colors(mut self, use_colors: bool) -> Self {
291 self.config.use_colors = use_colors;
292 self
293 }
294
295 pub fn level(mut self, level: LevelFilter) -> Self {
296 self.config.level = level;
297 self.config.module_filters.set_default_level(level);
299 self
300 }
301
302 pub fn module_filters(mut self, filters: ModuleFilters) -> Self {
303 self.config.module_filters = filters;
304 self
305 }
306
307 pub fn filter_module(mut self, module: impl Into<String>, level: LevelFilter) -> Self {
324 self.config.module_filters.add_filter(module, level);
325 self
326 }
327
328 pub fn build(self) -> LoggerConfig {
329 self.config
330 }
331}