sqlite_wasm_reader/
logging.rs1use std::sync::Mutex;
4
5static LOGGER: Mutex<Option<Logger>> = Mutex::new(None);
6
7#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
9pub enum LogLevel {
10 Error = 0,
12 Warn = 1,
14 Info = 2,
16 Debug = 3,
18 Trace = 4,
20}
21
22impl LogLevel {
23 pub fn default() -> Self {
25 LogLevel::Info
26 }
27
28 pub fn from_str(s: &str) -> Option<Self> {
30 match s.to_lowercase().as_str() {
31 "error" => Some(LogLevel::Error),
32 "warn" | "warning" => Some(LogLevel::Warn),
33 "info" => Some(LogLevel::Info),
34 "debug" => Some(LogLevel::Debug),
35 "trace" => Some(LogLevel::Trace),
36 _ => None,
37 }
38 }
39}
40
41#[derive(Clone)]
43pub struct Logger {
44 level: LogLevel,
45}
46
47impl Logger {
48 pub fn new(level: LogLevel) -> Self {
50 Logger { level }
51 }
52
53 pub fn default() -> Self {
55 Logger::new(LogLevel::default())
56 }
57
58 pub fn set_level(&mut self, level: LogLevel) {
60 self.level = level;
61 }
62
63 pub fn level(&self) -> LogLevel {
65 self.level
66 }
67
68 pub fn log(&self, level: LogLevel, message: &str) {
70 if level <= self.level {
71 let prefix = match level {
72 LogLevel::Error => "ERROR",
73 LogLevel::Warn => "WARN",
74 LogLevel::Info => "INFO",
75 LogLevel::Debug => "DEBUG",
76 LogLevel::Trace => "TRACE",
77 };
78 eprintln!("[sqlite_wasm_reader] {}: {}", prefix, message);
79 }
80 }
81
82 pub fn error(&self, message: &str) {
84 self.log(LogLevel::Error, message);
85 }
86
87 pub fn warn(&self, message: &str) {
89 self.log(LogLevel::Warn, message);
90 }
91
92 pub fn info(&self, message: &str) {
94 self.log(LogLevel::Info, message);
95 }
96
97 pub fn debug(&self, message: &str) {
99 self.log(LogLevel::Debug, message);
100 }
101
102 pub fn trace(&self, message: &str) {
104 self.log(LogLevel::Trace, message);
105 }
106}
107
108pub fn init_logger(level: LogLevel) {
110 let mut guard = LOGGER.lock().unwrap();
111 *guard = Some(Logger::new(level));
112}
113
114pub fn init_default_logger() {
116 init_logger(LogLevel::default());
117}
118
119pub fn get_logger() -> Logger {
121 let guard = LOGGER.lock().unwrap();
122 if let Some(ref logger) = *guard {
123 logger.clone()
124 } else {
125 drop(guard);
126 init_default_logger();
127 let guard = LOGGER.lock().unwrap();
128 guard.as_ref().unwrap().clone()
129 }
130}
131
132pub fn set_log_level(level: LogLevel) {
134 let mut guard = LOGGER.lock().unwrap();
135 if let Some(ref mut logger) = *guard {
136 logger.set_level(level);
137 } else {
138 *guard = Some(Logger::new(level));
139 }
140}
141
142pub fn log_error(message: &str) {
144 get_logger().error(message);
145}
146
147pub fn log_warn(message: &str) {
148 get_logger().warn(message);
149}
150
151pub fn log_info(message: &str) {
152 get_logger().info(message);
153}
154
155pub fn log_debug(message: &str) {
156 get_logger().debug(message);
157}
158
159pub fn log_trace(message: &str) {
160 get_logger().trace(message);
161}
162
163pub fn is_enabled(level: LogLevel) -> bool {
165 level <= get_logger().level()
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171
172 #[test]
173 fn test_log_level_creation() {
174 assert_eq!(LogLevel::Error as u8, 0);
175 assert_eq!(LogLevel::Warn as u8, 1);
176 assert_eq!(LogLevel::Info as u8, 2);
177 assert_eq!(LogLevel::Debug as u8, 3);
178 assert_eq!(LogLevel::Trace as u8, 4);
179 }
180
181 #[test]
182 fn test_log_level_default() {
183 assert_eq!(LogLevel::default(), LogLevel::Info);
184 }
185
186 #[test]
187 fn test_log_level_from_str() {
188 assert_eq!(LogLevel::from_str("error"), Some(LogLevel::Error));
189 assert_eq!(LogLevel::from_str("warn"), Some(LogLevel::Warn));
190 assert_eq!(LogLevel::from_str("warning"), Some(LogLevel::Warn));
191 assert_eq!(LogLevel::from_str("info"), Some(LogLevel::Info));
192 assert_eq!(LogLevel::from_str("debug"), Some(LogLevel::Debug));
193 assert_eq!(LogLevel::from_str("trace"), Some(LogLevel::Trace));
194
195 assert_eq!(LogLevel::from_str("ERROR"), Some(LogLevel::Error));
197 assert_eq!(LogLevel::from_str("Debug"), Some(LogLevel::Debug));
198
199 assert_eq!(LogLevel::from_str("invalid"), None);
201 assert_eq!(LogLevel::from_str(""), None);
202 }
203
204 #[test]
205 fn test_log_level_comparison() {
206 assert!(LogLevel::Error < LogLevel::Warn);
207 assert!(LogLevel::Warn < LogLevel::Info);
208 assert!(LogLevel::Info < LogLevel::Debug);
209 assert!(LogLevel::Debug < LogLevel::Trace);
210
211 assert!(LogLevel::Trace > LogLevel::Debug);
212 assert!(LogLevel::Debug > LogLevel::Info);
213 assert!(LogLevel::Info > LogLevel::Warn);
214 assert!(LogLevel::Warn > LogLevel::Error);
215 }
216
217 #[test]
218 fn test_logger_creation() {
219 let logger = Logger::new(LogLevel::Debug);
220 assert_eq!(logger.level(), LogLevel::Debug);
221
222 let default_logger = Logger::default();
223 assert_eq!(default_logger.level(), LogLevel::Info);
224 }
225
226 #[test]
227 fn test_logger_level_setting() {
228 let mut logger = Logger::new(LogLevel::Info);
229 assert_eq!(logger.level(), LogLevel::Info);
230
231 logger.set_level(LogLevel::Debug);
232 assert_eq!(logger.level(), LogLevel::Debug);
233 }
234
235 #[test]
236 fn test_global_logger_initialization() {
237 init_default_logger();
239 let logger = get_logger();
240 assert_eq!(logger.level(), LogLevel::Info);
241 }
242
243 #[test]
244 fn test_global_log_level_setting() {
245 init_default_logger();
246 set_log_level(LogLevel::Debug);
247 let logger = get_logger();
248 assert_eq!(logger.level(), LogLevel::Debug);
249 }
250
251 #[test]
252 fn test_logging_functions() {
253 init_default_logger();
254 set_log_level(LogLevel::Debug);
255
256 log_error("Test error message");
258 log_warn("Test warning message");
259 log_info("Test info message");
260 log_debug("Test debug message");
261 log_trace("Test trace message");
262 }
263
264 #[test]
265 fn test_is_enabled() {
266 init_default_logger();
267 set_log_level(LogLevel::Info);
268
269 assert!(is_enabled(LogLevel::Error));
270 assert!(is_enabled(LogLevel::Warn));
271 assert!(is_enabled(LogLevel::Info));
272 assert!(!is_enabled(LogLevel::Debug));
273 assert!(!is_enabled(LogLevel::Trace));
274
275 set_log_level(LogLevel::Trace);
276 assert!(is_enabled(LogLevel::Error));
277 assert!(is_enabled(LogLevel::Warn));
278 assert!(is_enabled(LogLevel::Info));
279 assert!(is_enabled(LogLevel::Debug));
280 assert!(is_enabled(LogLevel::Trace));
281 }
282}