use crate::{Dispatcher, Level};
use std::{
collections::BTreeMap,
error::Error,
sync::{atomic::AtomicU8, OnceLock, RwLock},
};
pub static GLOBAL_FILTER: AtomicU8 = AtomicU8::new(Level::Info as u8);
pub static MODULE_FILTERS: RwLock<BTreeMap<String, Level>> = RwLock::new(BTreeMap::new());
pub fn set_module_filter(module: &str, level: Level) -> Result<(), Box<dyn Error>> {
MODULE_FILTERS.write()?.insert(module.to_string(), level);
Ok(())
}
static GLOBAL_LOGGER: OnceLock<Box<dyn Dispatcher + Send + Sync>> = OnceLock::new();
pub fn init(dispatcher: Box<dyn Dispatcher + Send + Sync>) -> Result<(), Box<dyn Dispatcher + Send + Sync>> {
cirious_codex_term::init_term();
GLOBAL_LOGGER.set(dispatcher)
}
pub fn get_logger() -> Option<&'static (dyn Dispatcher + Send + Sync)> {
GLOBAL_LOGGER.get().map(std::convert::AsRef::as_ref)
}
#[macro_export]
#[doc(hidden)]
macro_rules! __log_internal {
($level:expr, $($arg:tt)+) => {
{
let current_level = $level as u8;
let module = module_path!();
let allowed = if let Ok(filters) = $crate::log::MODULE_FILTERS.read() {
if let Some(mod_level) = filters.get(module) {
current_level >= (*mod_level as u8)
} else {
current_level >= $crate::log::GLOBAL_FILTER.load(std::sync::atomic::Ordering::Relaxed)
}
} else {
current_level >= $crate::log::GLOBAL_FILTER.load(std::sync::atomic::Ordering::Relaxed)
};
if allowed {
if let Some(logger) = $crate::get_logger() {
let record = $crate::format::Record {
level: $level,
args: format!($($arg)+),
file: file!(),
line: line!(),
module_path: module,
timestamp: std::time::SystemTime::now(),
};
let _ = logger.dispatch(&record);
}
}
}
};
}
#[macro_export]
macro_rules! error { ($($arg:tt)+) => { $crate::__log_internal!($crate::level::Level::Error, $($arg)+); } }
#[macro_export]
macro_rules! warn { ($($arg:tt)+) => { $crate::__log_internal!($crate::level::Level::Warn, $($arg)+); } }
#[macro_export]
macro_rules! info { ($($arg:tt)+) => { $crate::__log_internal!($crate::level::Level::Info, $($arg)+); } }
#[macro_export]
macro_rules! debug { ($($arg:tt)+) => { $crate::__log_internal!($crate::level::Level::Debug, $($arg)+); } }
#[macro_export]
macro_rules! trace { ($($arg:tt)+) => { $crate::__log_internal!($crate::level::Level::Trace, $($arg)+); } }