2025-08-29 19:09:09 +02:00

103 lines
2.5 KiB
Rust

use std::time::{SystemTime, UNIX_EPOCH};
pub const INFO: usize = 0;
pub const DEBUG: usize = 1;
pub const WARNING: usize = 2;
pub const ERROR: usize = 3;
pub const FATAL: usize = 4;
pub const LOG_LEVEL: [&str; 5] = [
"INFO",
"DEBUG",
"WARN",
"ERROR",
"FATAL",
];
pub fn current_timestamp() -> String {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default();
let total_seconds = now.as_secs();
let seconds_in_day = total_seconds % 86400; // Seconds within current day
let hours = seconds_in_day / 3600;
let minutes = (seconds_in_day % 3600) / 60;
let seconds = seconds_in_day % 60;
format!("{:02}:{:02}:{:02}", hours, minutes, seconds)
}
/// Creates a formatted log message string and returns it
///
/// log_levels are:
/// - INFO
/// - DEBUG
/// - WARNING
/// - ERROR
/// - FATAL
///
/// Returns a formatted string ready for display or further processing.
#[macro_export]
macro_rules! msg {
($level:expr, $($arg:tt)*) => {{
let formatted_msg = format!($($arg)*);
format!(
"[{:<5}] [{:<15}:{:<4}] {}\n",
$crate::LOG_LEVEL[$level].to_string(),
{ std::path::Path::new(file!()).file_name().unwrap().to_str().unwrap_or(file!()) },
line!(),
formatted_msg
)
}};
}
/// Creates a formatted log message and prints it to stdout
///
/// log_levels are:
/// - INFO
/// - DEBUG
/// - WARNING
/// - ERROR
/// - FATAL
///
/// FATAL will cause the thread to panic and stop execution.
#[macro_export]
macro_rules! log {
($level:expr, $($arg:tt)*) => {{
let log_message = $crate::msg!($level, $($arg)*);
println!("{}", log_message);
// Handle FATAL level panic
if $level == $crate::FATAL {
panic!("Fatal error encountered: {}", format!($($arg)*));
}
}};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_msg_macro() {
let info_msg = msg!(INFO, "Test info message");
assert!(info_msg.contains("INFO"));
assert!(info_msg.contains("Test info message"));
let error_msg = msg!(ERROR, "Test error: {}", 42);
assert!(error_msg.contains("ERROR"));
assert!(error_msg.contains("Test error: 42"));
}
#[test]
fn test_timestamp() {
let ts = current_timestamp();
assert!(ts.contains(":"));
// Should be in HH:MM:SS format
assert_eq!(ts.len(), 8);
}
}