1use chrono::Local;
7use crossterm::style::{self, Color, ResetColor, SetForegroundColor};
8
9#[derive(Debug, PartialEq, Eq, Copy, Clone)]
11pub enum LogLevel {
12 Info,
13 Warn,
14 Error,
15 Debug,
16 Critical,
17}
18
19pub fn log_message(level: LogLevel, message: &str, module_name: Option<&str>) -> String {
40 let now = Local::now();
41 let timestamp = now.format("%H:%M:%S").to_string();
42
43 let (level_str, color) = match level {
44 LogLevel::Info => ("INFO", Color::Green),
45 LogLevel::Warn => ("WARN", Color::Yellow),
46 LogLevel::Error => ("ERROR", Color::Red),
47 LogLevel::Debug => ("DEBUG", Color::DarkGrey),
48 LogLevel::Critical => ("CRITICAL", Color::AnsiValue(5)),
49 };
50
51 let module_prefix = module_name.map_or_else(String::new, |name| format!("{}/", name));
52
53 match level {
54 LogLevel::Info | LogLevel::Warn | LogLevel::Error | LogLevel::Critical => {
55 format!(
56 "[{}] {}[{}{}{}{}{}]{} {}{}",
57 timestamp,
58 style::Attribute::Bold,
59 module_prefix,
60 SetForegroundColor(color),
61 level_str,
62 ResetColor,
63 style::Attribute::Bold,
64 ResetColor,
65 message,
66 ResetColor
67 )
68 }
69 LogLevel::Debug => {
70 format!(
71 "{}{}[{}] [{}{}] {}{}{}",
72 SetForegroundColor(color),
73 style::Attribute::Italic,
74 timestamp,
75 module_prefix,
76 level_str,
77 style::Attribute::Italic,
78 message,
79 ResetColor,
80 )
81 }
82 }
83}
84
85pub fn format_multiline_message(
89 level: LogLevel,
90 message: &str,
91 module_name: Option<&str>,
92) -> String {
93 if !message.contains('\n') {
94 return log_message(level, message, module_name);
95 }
96
97 message
98 .lines()
99 .map(|line| log_message(level, line, module_name))
100 .collect::<Vec<String>>()
101 .join("\n")
102}
103
104#[macro_export]
115macro_rules! get_info {
116 ($message:expr) => {
117 $crate::logger::format_multiline_message($crate::logger::LogLevel::Info, $message, None)
118 };
119 ($message:expr, $module_name:expr) => {
120 $crate::logger::format_multiline_message(
121 $crate::logger::LogLevel::Info,
122 $message,
123 Some($module_name),
124 )
125 };
126}
127
128#[macro_export]
139macro_rules! get_warn {
140 ($message:expr) => {
141 $crate::logger::format_multiline_message($crate::logger::LogLevel::Warn, $message, None)
142 };
143 ($message:expr, $module_name:expr) => {
144 $crate::logger::format_multiline_message(
145 $crate::logger::LogLevel::Warn,
146 $message,
147 Some($module_name),
148 )
149 };
150}
151
152#[macro_export]
163macro_rules! get_error {
164 ($message:expr) => {
165 $crate::logger::format_multiline_message($crate::logger::LogLevel::Error, $message, None)
166 };
167 ($message:expr, $module_name:expr) => {
168 $crate::logger::format_multiline_message(
169 $crate::logger::LogLevel::Error,
170 $message,
171 Some($module_name),
172 )
173 };
174}
175
176#[macro_export]
187macro_rules! get_debug {
188 ($message:expr) => {
189 $crate::logger::format_multiline_message($crate::logger::LogLevel::Debug, $message, None)
190 };
191 ($message:expr, $module_name:expr) => {
192 $crate::logger::format_multiline_message(
193 $crate::logger::LogLevel::Debug,
194 $message,
195 Some($module_name),
196 )
197 };
198}
199
200#[macro_export]
211macro_rules! get_critical {
212 ($message:expr) => {
213 $crate::logger::format_multiline_message($crate::logger::LogLevel::Critical, $message, None)
214 };
215 ($message:expr, $module_name:expr) => {
216 $crate::logger::format_multiline_message(
217 $crate::logger::LogLevel::Critical,
218 $message,
219 Some($module_name),
220 )
221 };
222}