use std::collections::HashMap;
use crate::level::LogLevel;
#[derive(Debug, Clone)]
pub struct LogFilter {
module_levels: HashMap<String, LogLevel>,
}
impl Default for LogFilter {
fn default() -> Self {
LogFilter {
module_levels: HashMap::new(),
}
}
}
impl LogFilter {
pub fn new() -> Self {
Self::default()
}
pub fn from_env(env_str: &str) -> Self {
let mut filter = LogFilter::new();
for entry in env_str.split(',') {
let entry = entry.trim();
if let Some(eq_pos) = entry.find('=') {
let module = entry[..eq_pos].trim().to_string();
if let Ok(level) = entry[eq_pos + 1..].trim().parse::<LogLevel>() {
filter.set_module_level(&module, level);
}
}
}
filter
}
pub fn set_module_level(&mut self, module: &str, level: LogLevel) {
self.module_levels.insert(module.to_string(), level);
}
pub fn remove_module(&mut self, module: &str) {
self.module_levels.remove(module);
}
pub fn get_effective_level(&self, module: &str) -> Option<LogLevel> {
if self.module_levels.is_empty() {
return None;
}
let mut best_match: Option<(usize, &LogLevel)> = None;
for (prefix, level) in &self.module_levels {
if module == prefix || module.starts_with(&format!("{}::", prefix)) {
let is_better = match best_match {
None => true,
Some((best_len, _)) => prefix.len() > best_len,
};
if is_better {
best_match = Some((prefix.len(), level));
}
}
}
best_match.map(|(_, level)| *level)
}
pub fn should_log(&self, module: &str, level: LogLevel) -> bool {
match self.get_effective_level(module) {
Some(effective_level) => effective_level.should_log(level),
None => true, }
}
pub fn clear(&mut self) {
self.module_levels.clear();
}
pub fn len(&self) -> usize {
self.module_levels.len()
}
pub fn is_empty(&self) -> bool {
self.module_levels.is_empty()
}
}