use colored::Colorize;
use once_cell::sync::Lazy;
use std::sync::Arc;
use tokio::sync::{mpsc, Mutex};
struct LogMessage {
text: String,
level: Level,
}
pub fn get_prefix(level: Level) -> String {
return match level {
Level::INFO => "[INFO]:".white().to_string(),
Level::DEBUG => "[DEBUG]:".bright_cyan().to_string(),
Level::ERROR => "[ERROR]:".red().to_string(),
Level::WARNING => "[WARNING]:".yellow().to_string(),
Level::CRITICAL => "[CRITICAL]:".magenta().to_string(),
};
}
static LOGGER: Lazy<Arc<Mutex<Option<mpsc::Sender<LogMessage>>>>> = Lazy::new(|| Arc::new(Mutex::new(None)));
pub async fn init(buffer_size: usize) {
let (tx, mut rx) = mpsc::channel::<LogMessage>(buffer_size);
let mut logger = LOGGER.lock().await;
*logger = Some(tx);
tokio::spawn(async move {
while let Some(message) = rx.recv().await {
match message.level {
Level::INFO => println!("{} {}", get_prefix(message.level), message.text.white()),
Level::DEBUG => println!(
"{}: {}",
get_prefix(message.level),
message.text.bright_cyan()
),
Level::ERROR => println!("{} {}", get_prefix(message.level), message.text.red()),
Level::WARNING => {
println!("{} {}", get_prefix(message.level), message.text.yellow())
}
Level::CRITICAL => {
println!("{} {}", get_prefix(message.level), message.text.magenta())
}
}
}
});
}
pub async fn shutdown() {
let mut logger = LOGGER.lock().await;
*logger = None;
}
pub async fn log(text: &str, level: Level) {
if let Some(sender) = &*LOGGER.lock().await {
let _ = sender
.send(LogMessage {
text: text.to_owned(),
level,
})
.await;
} else {
let final_text = match level {
Level::INFO => text.white(),
Level::DEBUG => text.blue(),
Level::ERROR => text.red(),
Level::WARNING => text.yellow(),
Level::CRITICAL => text.magenta(),
};
println!("{}: {}", get_prefix(level), final_text);
}
}
#[macro_export]
macro_rules! debug {
($($arg:tt)*) => {
$crate::log(&format!($($arg)*), $crate::Level::DEBUG).await
};
}
#[macro_export]
macro_rules! info {
($($arg:tt)*) => {
$crate::log(&format!($($arg)*), $crate::Level::INFO).await
};
}
#[macro_export]
macro_rules! error {
($($arg:tt)*) => {
$crate::log(&format!($($arg)*), $crate::Level::ERROR).await
};
}
#[macro_export]
macro_rules! warning {
($($arg:tt)*) => {
$crate::log(&format!($($arg)*), $crate::Level::WARNING).await
};
}
#[macro_export]
macro_rules! critical {
($($arg:tt)*) => {
$crate::log(&format!($($arg)*), $crate::Level::CRITICAL).await
};
}
#[derive(Debug, Clone, Copy)]
pub enum Level {
INFO,
ERROR,
DEBUG,
WARNING,
CRITICAL,
}