#[cfg(feature = "time")]
pub use chrono::Local;
pub use colored::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Level {
Info,
Warn,
Error,
Running,
Success,
User,
Account,
Card,
Transaction,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SubLevel {
None,
User,
Account,
Card,
Transaction,
}
pub fn log_message(level: Level, sub_level: SubLevel, msg: &str) {
use colored::Colorize;
let level_str = match level {
Level::Info => "Info",
Level::Warn => "Warn",
Level::Error => "Error",
Level::Running => "Running",
Level::Success => "Success",
Level::User => "User",
Level::Account => "Account",
Level::Card => "Card",
Level::Transaction => "Tx",
};
let level_colored = match level {
Level::Info | Level::Running | Level::Success => level_str.bright_green().bold(),
Level::Warn => level_str.bright_yellow().bold(),
Level::Error => level_str.bright_red().bold(),
Level::User => level_str.bright_blue().bold(),
Level::Account => level_str.bright_cyan().bold(),
Level::Card => level_str.bright_magenta().bold(),
Level::Transaction => level_str.bright_purple().bold(),
};
let sub_level_colored = match sub_level {
SubLevel::None => "".clear(),
SubLevel::User => "User".bright_blue().bold(),
SubLevel::Account => "Account".bright_blue().bold(),
SubLevel::Card => "Card".bright_blue().bold(),
SubLevel::Transaction => "Tx".bright_blue().bold(),
};
#[cfg(feature = "time")]
let time_str = chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string();
#[cfg(feature = "time")]
let prefix_len = time_str.len() + 1 + 17 + 1;
#[cfg(not(feature = "time"))]
let prefix_len = 18;
let mut lines = msg.lines();
if let Some(first) = lines.next() {
#[cfg(feature = "time")]
let mut output = format!("{} {:>8} {:<8} {}", time_str, level_colored, sub_level_colored, first);
#[cfg(not(feature = "time"))]
let mut output = format!("{:>8} {:<8} {}", level_colored, sub_level_colored, first);
let indent = " ".repeat(prefix_len);
for line in lines {
output.push_str("\n");
output.push_str(&indent);
output.push_str(line);
}
if level == Level::Error {
eprintln!("{}", output);
} else {
println!("{}", output);
}
}
}
#[macro_export]
macro_rules! logger {
($level:expr, $sub_level:expr, $fmt:literal, $($arg:tt)*) => {{
$crate::log_message($level, $sub_level, &format!($fmt, $($arg)*))
}};
($level:expr, $sub_level:expr, $fmt:literal) => {{
$crate::log_message($level, $sub_level, $fmt)
}};
($level:expr, $fmt:literal, $($arg:tt)*) => {{
$crate::log_message($level, $crate::SubLevel::None, &format!($fmt, $($arg)*))
}};
($level:expr, $fmt:literal) => {{
$crate::log_message($level, $crate::SubLevel::None, $fmt)
}};
($fmt:literal, $($arg:tt)*) => {{
$crate::log_message($crate::Level::Info, $crate::SubLevel::None, &format!($fmt, $($arg)*))
}};
($fmt:literal) => {{
$crate::log_message($crate::Level::Info, $crate::SubLevel::None, $fmt)
}};
}
#[cfg(test)]
mod tests {
use crate::{Level, SubLevel};
#[test]
fn test_logger() {
logger!("This is a test info message");
logger!(Level::Info, SubLevel::Account, "This is an explicit info message with Account sublevel");
logger!(Level::Error, SubLevel::User, "This is an error message with User sublevel");
}
}