use std::sync::{Arc, Mutex, OnceLock};
use crate::config::Config;
use crate::level::LogLevel;
use crate::writer::Writer;
use crate::filter::LogFilter;
pub struct Logger {
level: Mutex<LogLevel>,
writer: Arc<Writer>,
filter: Mutex<LogFilter>,
}
static LOGGER: OnceLock<Arc<Logger>> = OnceLock::new();
impl Logger {
pub fn get_instance() -> Arc<Self> {
LOGGER.get_or_init(|| {
let config = Config::default();
let writer = Arc::new(Writer::new(config.clone()));
Arc::new(Logger {
level: Mutex::new(config.level),
writer,
filter: Mutex::new(config.filter),
})
}).clone()
}
pub fn init_with_config(config: Config) -> Result<(), &'static str> {
LOGGER.set({
let writer = Arc::new(Writer::new(config.clone()));
Arc::new(Logger {
level: Mutex::new(config.level),
writer,
filter: Mutex::new(config.filter),
})
}).map_err(|_| "Logger is already initialized")
}
pub fn set_level(&self, level: LogLevel) {
*self.level.lock().unwrap() = level;
}
pub fn get_level(&self) -> LogLevel {
*self.level.lock().unwrap()
}
pub fn filter(&self) -> std::sync::MutexGuard<'_, LogFilter> {
self.filter.lock().unwrap()
}
pub fn set_module_level(&self, module: &str, level: LogLevel) {
self.filter.lock().unwrap().set_module_level(module, level);
}
pub fn remove_module_level(&self, module: &str) {
self.filter.lock().unwrap().remove_module(module);
}
pub fn set_console_enabled(&self, enabled: bool) {
self.writer.set_console_enabled(enabled);
}
pub fn set_console_colors(&self, enabled: bool) {
self.writer.set_console_colors(enabled);
}
pub fn flush(&self) {
self.writer.flush();
}
pub fn trace(&self, message: &str) {
self.log(LogLevel::Trace, message);
}
pub fn trace_target(&self, target: &str, message: &str) {
self.log_with_target(LogLevel::Trace, target, message);
}
pub fn debug(&self, message: &str) {
self.log(LogLevel::Debug, message);
}
pub fn debug_target(&self, target: &str, message: &str) {
self.log_with_target(LogLevel::Debug, target, message);
}
pub fn info(&self, message: &str) {
self.log(LogLevel::Info, message);
}
pub fn info_target(&self, target: &str, message: &str) {
self.log_with_target(LogLevel::Info, target, message);
}
pub fn warn(&self, message: &str) {
self.log(LogLevel::Warn, message);
}
pub fn warn_target(&self, target: &str, message: &str) {
self.log_with_target(LogLevel::Warn, target, message);
}
pub fn error(&self, message: &str) {
self.log(LogLevel::Error, message);
}
pub fn error_target(&self, target: &str, message: &str) {
self.log_with_target(LogLevel::Error, target, message);
}
pub fn critical(&self, message: &str) {
self.log(LogLevel::Critical, message);
}
pub fn critical_target(&self, target: &str, message: &str) {
self.log_with_target(LogLevel::Critical, target, message);
}
fn log(&self, level: LogLevel, message: &str) {
if self.get_level().should_log(level) {
self.writer.write(level, message);
}
}
fn log_with_target(&self, level: LogLevel, target: &str, message: &str) {
if !self.filter.lock().unwrap().should_log(target, level) {
return;
}
if self.get_level().should_log(level) {
self.writer.write(level, message);
}
}
}