use chrono::Local;
use once_cell::sync::Lazy;
use std::sync::{Arc, Mutex};
static LOGS: Lazy<Arc<Mutex<Vec<String>>>> = Lazy::new(|| Arc::new(Mutex::new(Vec::new())));
static LOG_LEVEL: Lazy<Arc<Mutex<LogLevel>>> = Lazy::new(|| Arc::new(Mutex::new(LogLevel::Info)));
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum LogLevel {
Debug,
Info,
Warning,
Error,
}
impl LogLevel {
fn prefix(&self) -> &'static str {
match self {
LogLevel::Debug => "đ",
LogLevel::Info => "âšī¸",
LogLevel::Warning => "â ī¸",
LogLevel::Error => "â",
}
}
}
pub fn set_log_level(level: LogLevel) {
if let Ok(mut current_level) = LOG_LEVEL.lock() {
*current_level = level;
}
}
pub fn get_log_level() -> LogLevel {
if let Ok(level) = LOG_LEVEL.lock() {
*level
} else {
LogLevel::Info
}
}
pub fn log(level: LogLevel, message: &str) {
let timestamp = Local::now().format("%H:%M:%S").to_string();
let formatted = format!("[{}] {} {}", timestamp, level.prefix(), message);
if let Ok(mut logs) = LOGS.lock() {
logs.push(formatted.clone());
}
if let Ok(current_level) = LOG_LEVEL.lock() {
if level >= *current_level {
match level {
LogLevel::Error | LogLevel::Warning => eprintln!("{}", formatted),
_ => println!("{}", formatted),
}
}
}
}
pub fn get_logs() -> Vec<String> {
if let Ok(logs) = LOGS.lock() {
logs.clone()
} else {
let timestamp = Local::now().format("%H:%M:%S").to_string();
vec![format!("[{}] â Error accessing logs", timestamp)]
}
}
#[allow(dead_code)]
pub fn clear_logs() {
if let Ok(mut logs) = LOGS.lock() {
logs.clear();
}
}
#[allow(dead_code)]
pub fn debug(message: &str) {
log(LogLevel::Debug, message);
}
pub fn info(message: &str) {
log(LogLevel::Info, message);
}
pub fn warning(message: &str) {
log(LogLevel::Warning, message);
}
pub fn error(message: &str) {
log(LogLevel::Error, message);
}