use std::sync::Arc;
use arc_swap::ArcSwap;
use once_cell::sync::Lazy;
pub fn configure(filter: log::LevelFilter, logger: Box<dyn log::Log>) {
set_boxed_logger(logger);
set_max_level(filter);
}
pub fn set_boxed_logger(logger: Box<dyn log::Log>) {
HANDLE.inner.swap(Arc::new(logger));
}
pub fn set_max_level(filter: log::LevelFilter) {
log::set_max_level(filter);
}
static HANDLE: Lazy<Handle> = Lazy::new(|| {
let handle = Handle {
inner: Arc::new(ArcSwap::new(Arc::new(Box::new(NopLogger)))),
};
if let Err(_) = log::set_boxed_logger(Box::new(handle.clone())) {
log::error!("Failed to set global logger (a logger was set previously).")
};
handle
});
#[derive(Clone)]
struct Handle {
inner: Arc<ArcSwap<Box<dyn log::Log>>>,
}
impl log::Log for Handle {
fn enabled(&self, metadata: &log::Metadata) -> bool {
self.inner.load().enabled(metadata)
}
fn log(&self, record: &log::Record) {
self.inner.load().log(record)
}
fn flush(&self) {
self.inner.load().flush()
}
}
struct NopLogger;
impl log::Log for NopLogger {
fn enabled(&self, _: &log::Metadata) -> bool {
false
}
fn log(&self, _: &log::Record) {}
fn flush(&self) {}
}