First Setup
This commit is contained in:
commit
02e552cddd
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vlogger"
|
||||||
|
version = "0.1.0"
|
||||||
6
Cargo.toml
Normal file
6
Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "vlogger"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
11
README.md
Normal file
11
README.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Simple Logger
|
||||||
|
|
||||||
|
A lightweight logging utility for Rust with both printing and string formatting capabilities.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Two macros**: `log!` for immediate printing, `msg!` for string formatting
|
||||||
|
- **Color support**: ANSI color codes for terminal output
|
||||||
|
- **Multiple log levels**: INFO, DEBUG, WARNING, ERROR, FATAL
|
||||||
|
- **No external dependencies**: Uses only standard library
|
||||||
|
- **File/line info**: DEBUG, WARNING, ERROR, and FATAL levels include source location
|
||||||
177
src/lib.rs
Normal file
177
src/lib.rs
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
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",
|
||||||
|
"WARNING",
|
||||||
|
"ERROR",
|
||||||
|
"FATAL",
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn colored(text: &str, color: &str) -> String {
|
||||||
|
// For terminals: use ANSI escape codes
|
||||||
|
let ansi_code = match color {
|
||||||
|
"black" => "30",
|
||||||
|
"red" => "31",
|
||||||
|
"green" => "32",
|
||||||
|
"yellow" => "33",
|
||||||
|
"blue" => "34",
|
||||||
|
"purple" => "35",
|
||||||
|
"cyan" => "36",
|
||||||
|
"white" => "37",
|
||||||
|
_ => "0", // default no color
|
||||||
|
};
|
||||||
|
format!("\x1b[{ansi_code}m{text}\x1b[0m")
|
||||||
|
}
|
||||||
|
|
||||||
|
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)*);
|
||||||
|
match $level {
|
||||||
|
$crate::INFO => {
|
||||||
|
format!(
|
||||||
|
"[{}] {} | {}",
|
||||||
|
$crate::colored($crate::LOG_LEVEL[$level], "green"),
|
||||||
|
$crate::current_timestamp(),
|
||||||
|
formatted_msg
|
||||||
|
)
|
||||||
|
},
|
||||||
|
$crate::DEBUG => {
|
||||||
|
format!(
|
||||||
|
"[{}] [{}:{}] {} | {}",
|
||||||
|
$crate::LOG_LEVEL[$level],
|
||||||
|
file!(),
|
||||||
|
line!(),
|
||||||
|
$crate::current_timestamp(),
|
||||||
|
formatted_msg
|
||||||
|
)
|
||||||
|
},
|
||||||
|
$crate::WARNING => {
|
||||||
|
format!(
|
||||||
|
"[{}] [{}:{}] {} | {}",
|
||||||
|
$crate::colored($crate::LOG_LEVEL[$level], "yellow"),
|
||||||
|
file!(),
|
||||||
|
line!(),
|
||||||
|
$crate::current_timestamp(),
|
||||||
|
formatted_msg
|
||||||
|
)
|
||||||
|
},
|
||||||
|
$crate::ERROR => {
|
||||||
|
format!(
|
||||||
|
"[{}] [{}:{}] {} | {}",
|
||||||
|
$crate::colored($crate::LOG_LEVEL[$level], "red"),
|
||||||
|
file!(),
|
||||||
|
line!(),
|
||||||
|
$crate::current_timestamp(),
|
||||||
|
formatted_msg
|
||||||
|
)
|
||||||
|
},
|
||||||
|
$crate::FATAL => {
|
||||||
|
format!(
|
||||||
|
"[{}] [{}:{}] {} | {}",
|
||||||
|
$crate::colored($crate::LOG_LEVEL[$level], "red"),
|
||||||
|
file!(),
|
||||||
|
line!(),
|
||||||
|
$crate::current_timestamp(),
|
||||||
|
formatted_msg
|
||||||
|
)
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
format!(
|
||||||
|
"[{}] {} {}",
|
||||||
|
$crate::LOG_LEVEL[$crate::ERROR],
|
||||||
|
"logging error: log_level value invalid:",
|
||||||
|
$level
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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_colored() {
|
||||||
|
let red_text = colored("error", "red");
|
||||||
|
assert!(red_text.contains("\x1b[31m"));
|
||||||
|
assert!(red_text.contains("error"));
|
||||||
|
assert!(red_text.contains("\x1b[0m"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_timestamp() {
|
||||||
|
let ts = current_timestamp();
|
||||||
|
assert!(ts.contains(":"));
|
||||||
|
// Should be in HH:MM:SS format
|
||||||
|
assert_eq!(ts.len(), 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user