use std::sync::{Arc, Mutex, RwLock};
use super::Context;
use super::Target;
use super::Level;
#[derive(Clone)]
pub struct Logger {
target: Arc<Mutex<Box<Target + 'static>>>,
level: Arc<RwLock<Level>>,
context: Arc<Context>,
}
impl Logger {
pub fn new<T>(target: T, context: Context) -> Self
where
T: Target + 'static,
{
Self {
target: Arc::new(Mutex::new(Box::new(target))),
level: Arc::new(RwLock::new(Level::Trace)),
context: Arc::new(context),
}
}
pub fn set_level<L>(&self, level: L)
where
L: Into<Level>,
{
*self.level.write().unwrap() = level.into();
}
pub fn set_target<T>(&self, target: T)
where
T: Target + 'static,
{
*self.target.lock().unwrap() = Box::new(target);
}
pub fn ctx(&self, context: Context) -> Self {
Self {
target: self.target.clone(),
level: self.level.clone(),
context: Arc::new(self.context.merge(context)),
}
}
pub fn error(&self, message: &str) {
self.log(Level::Error, message);
}
pub fn warn(&self, message: &str) {
self.log(Level::Warn, message);
}
pub fn info(&self, message: &str) {
self.log(Level::Info, message);
}
pub fn verbose(&self, message: &str) {
self.log(Level::Verbose, message);
}
pub fn debug(&self, message: &str) {
self.log(Level::Debug, message);
}
pub fn trace(&self, message: &str) {
self.log(Level::Trace, message);
}
pub fn log<L>(&self, level: L, message: &str)
where
L: Into<Level>,
{
let level = level.into();
if level > *self.level.read().unwrap() {
return;
}
self
.target
.lock()
.unwrap()
.log(level, message, &self.context);
}
}
unsafe impl Send for Logger {}
unsafe impl Sync for Logger {}