From 25a6d780f97f9c1001cfe6aa1cbc7423dc6b7171 Mon Sep 17 00:00:00 2001 From: kayu0514 Date: Tue, 11 Nov 2025 21:58:55 +0900 Subject: [PATCH] Fixend : log #14 --- src/lib.rs | 176 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 121 insertions(+), 55 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f3aceb2..08977c8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,12 @@ -use notify_rust::Notification; +use backtrace::Backtrace; use chrono::{Local, NaiveDate}; +use notify_rust::Notification; use std::env; use std::fs; use std::io::Write; -use backtrace::Backtrace; -use std::sync::mpsc::{channel, Sender}; -use std::thread; use std::panic; +use std::sync::mpsc::{Sender, channel}; +use std::thread; pub struct VersaLog { enum_mode: String, @@ -44,12 +44,25 @@ static RESET: &str = "\x1b[0m"; static VALID_MODES: &[&str] = &["simple", "simple2", "detailed", "file"]; static VALID_SAVE_LEVELS: &[&str] = &["INFO", "ERROR", "WARNING", "DEBUG", "CRITICAL"]; -pub fn NewVersaLog(enum_mode: &str, show_file: bool, show_tag: bool, tag: &str, enable_all: bool, notice: bool, all_save: bool, save_levels: Vec, catch_exceptions: bool) -> VersaLog { +pub fn NewVersaLog( + enum_mode: &str, + show_file: bool, + show_tag: bool, + tag: &str, + enable_all: bool, + notice: bool, + all_save: bool, + save_levels: Vec, + catch_exceptions: bool, +) -> VersaLog { let mode = enum_mode.to_lowercase(); let tag = tag.to_string(); - + if !VALID_MODES.contains(&enum_mode) { - panic!("Invalid mode '{}' specified. Valid modes are: simple, simple2, detailed, file", enum_mode); + panic!( + "Invalid mode '{}' specified. Valid modes are: simple, simple2, detailed, file", + enum_mode + ); } let mut showFile = show_file; @@ -75,7 +88,10 @@ pub fn NewVersaLog(enum_mode: &str, show_file: bool, show_tag: bool, tag: &str, } else { for level in &savelevels { if !VALID_SAVE_LEVELS.contains(&level.as_str()) { - panic!("Invalid saveLevels specified. Valid levels are: {:?}", VALID_SAVE_LEVELS); + panic!( + "Invalid saveLevels specified. Valid levels are: {:?}", + VALID_SAVE_LEVELS + ); } } } @@ -102,7 +118,9 @@ pub fn NewVersaLog(enum_mode: &str, show_file: bool, show_tag: bool, tag: &str, } }); Some(tx) - } else { None }; + } else { + None + }; VersaLog { enum_mode: enum_mode.to_string(), @@ -121,32 +139,54 @@ pub fn NewVersaLog(enum_mode: &str, show_file: bool, show_tag: bool, tag: &str, } pub fn NewVersaLogSimple(enum_mode: &str, tag: &str) -> VersaLog { - NewVersaLog(enum_mode, false, false, tag, false, false, false, Vec::new(), false) + NewVersaLog( + enum_mode, + false, + false, + tag, + false, + false, + false, + Vec::new(), + false, + ) } pub fn NewVersaLogSimple2(enum_mode: &str, tag: &str, enable_all: bool) -> VersaLog { - NewVersaLog(enum_mode, false, false, tag, enable_all, false, false, Vec::new(), false) + NewVersaLog( + enum_mode, + false, + false, + tag, + enable_all, + false, + false, + Vec::new(), + false, + ) } impl VersaLog { pub fn log(&self, msg: String, level: String, tags: &[&str]) { let level = level.to_uppercase(); - - let color = COLORS.iter() + + let color = COLORS + .iter() .find(|(l, _)| *l == level) .map(|(_, c)| *c) .unwrap_or(""); - let symbol = SYMBOLS.iter() + let symbol = SYMBOLS + .iter() .find(|(l, _)| *l == level) .map(|(_, s)| *s) .unwrap_or(""); - + let caller = if self.showFile || self.enum_mode == "file" { self.get_caller() } else { String::new() }; - + let final_tag = if !tags.is_empty() && !tags[0].is_empty() { tags[0].to_string() } else if self.showTag && !self.tag.is_empty() { @@ -154,12 +194,15 @@ impl VersaLog { } else { String::new() }; - + let (output, plain) = match self.enum_mode.as_str() { "simple" => { if self.showFile { if !final_tag.is_empty() { - let output = format!("[{}][{}]{}{}{} {}", caller, final_tag, color, symbol, RESET, msg); + let output = format!( + "[{}][{}]{}{}{} {}", + caller, final_tag, color, symbol, RESET, msg + ); let plain = format!("[{}][{}]{} {}", caller, final_tag, symbol, msg); (output, plain) } else { @@ -178,16 +221,25 @@ impl VersaLog { (output, plain) } } - }, + } "simple2" => { let timestamp = self.get_time(); if self.showFile { if !final_tag.is_empty() { - let output = format!("[{}] [{}][{}]{}{}{} {}", timestamp, caller, final_tag, color, symbol, RESET, msg); - let plain = format!("[{}] [{}][{}]{} {}", timestamp, caller, final_tag, symbol, msg); + let output = format!( + "[{}] [{}][{}]{}{}{} {}", + timestamp, caller, final_tag, color, symbol, RESET, msg + ); + let plain = format!( + "[{}] [{}][{}]{} {}", + timestamp, caller, final_tag, symbol, msg + ); (output, plain) } else { - let output = format!("[{}] [{}]{}{}{} {}", timestamp, caller, color, symbol, RESET, msg); + let output = format!( + "[{}] [{}]{}{}{} {}", + timestamp, caller, color, symbol, RESET, msg + ); let plain = format!("[{}] [{}]{} {}", timestamp, caller, symbol, msg); (output, plain) } @@ -196,39 +248,39 @@ impl VersaLog { let plain = format!("[{}] {} {}", timestamp, symbol, msg); (output, plain) } - }, + } "file" => { let output = format!("[{}]{}{}[{}]{}", caller, color, level, RESET, msg); let plain = format!("[{}][{}] {}", caller, level, msg); (output, plain) - }, + } _ => { let timestamp = self.get_time(); - let mut output = format!("[{}]{}{}[{}]", timestamp, color, level, RESET); + let mut output = format!("[{}]{}{}[{}]{}", timestamp, color, level, RESET); let mut plain = format!("[{}][{}]", timestamp, level); - + if !final_tag.is_empty() { output.push_str(&format!("[{}]", final_tag)); plain.push_str(&format!("[{}]", final_tag)); } - + if self.showFile { output.push_str(&format!("[{}]", caller)); plain.push_str(&format!("[{}]", caller)); } - + output.push_str(&format!(" : {}", msg)); plain.push_str(&format!(" : {}", msg)); - + (output, plain) } }; - + if !self.silent { println!("{}", output); } self.save_log(plain, level.clone()); - + if self.notice && (level == "ERROR" || level == "CRITICAL") { let _ = Notification::new() .summary(&format!("{} Log notice", level)) @@ -255,7 +307,12 @@ impl VersaLog { let mut details = String::new(); if let Some(loc) = info.location() { - details.push_str(&format!("at {}:{}:{}\n", loc.file(), loc.line(), loc.column())); + details.push_str(&format!( + "at {}:{}:{}\n", + loc.file(), + loc.line(), + loc.column() + )); } let bt = Backtrace::new(); details.push_str(&format!("{:?}", bt)); @@ -265,27 +322,29 @@ impl VersaLog { } pub fn handle_exception(&self, exc_type: &str, exc_value: &str, exc_traceback: &str) { - let tb_str = format!("Exception Type: {}\nException Value: {}\nTraceback:\n{}", - exc_type, exc_value, exc_traceback); + let tb_str = format!( + "Exception Type: {}\nException Value: {}\nTraceback:\n{}", + exc_type, exc_value, exc_traceback + ); self.Critical_no_tag(&format!("Unhandled exception:\n{}", tb_str)); } - + pub fn Info(&self, msg: &str, tags: &[&str]) { self.log(msg.to_string(), "INFO".to_string(), tags); } - + pub fn Error(&self, msg: &str, tags: &[&str]) { self.log(msg.to_string(), "ERROR".to_string(), tags); } - + pub fn Warning(&self, msg: &str, tags: &[&str]) { self.log(msg.to_string(), "WARNING".to_string(), tags); } - + pub fn Debug(&self, msg: &str, tags: &[&str]) { self.log(msg.to_string(), "DEBUG".to_string(), tags); } - + pub fn Critical(&self, msg: &str, tags: &[&str]) { self.log(msg.to_string(), "CRITICAL".to_string(), tags); } @@ -293,39 +352,39 @@ impl VersaLog { pub fn info(&self, msg: &str, tags: &[&str]) { self.Info(msg, tags); } - + pub fn error(&self, msg: &str, tags: &[&str]) { self.Error(msg, tags); } - + pub fn warning(&self, msg: &str, tags: &[&str]) { self.Warning(msg, tags); } - + pub fn debug(&self, msg: &str, tags: &[&str]) { self.Debug(msg, tags); } - + pub fn critical(&self, msg: &str, tags: &[&str]) { self.Critical(msg, tags); } - + pub fn Info_no_tag(&self, msg: &str) { self.log(msg.to_string(), "INFO".to_string(), &[]); } - + pub fn Error_no_tag(&self, msg: &str) { self.log(msg.to_string(), "ERROR".to_string(), &[]); } - + pub fn Warning_no_tag(&self, msg: &str) { self.log(msg.to_string(), "WARNING".to_string(), &[]); } - + pub fn Debug_no_tag(&self, msg: &str) { self.log(msg.to_string(), "DEBUG".to_string(), &[]); } - + pub fn Critical_no_tag(&self, msg: &str) { self.log(msg.to_string(), "CRITICAL".to_string(), &[]); } @@ -333,7 +392,7 @@ impl VersaLog { fn get_time(&self) -> String { Local::now().format("%Y-%m-%d %H:%M:%S").to_string() } - + fn get_caller(&self) -> String { let bt = Backtrace::new(); if let Some(frame) = bt.frames().get(3) { @@ -349,28 +408,35 @@ impl VersaLog { } "unknown:0".to_string() } - + fn cleanup_old_logs(&self, days: i64) { let cwd = env::current_dir().unwrap_or_else(|_| env::current_dir().unwrap()); let log_dir = cwd.join("log"); - + if !log_dir.exists() { return; } let now = Local::now().naive_local().date(); - + if let Ok(entries) = fs::read_dir(&log_dir) { for entry in entries { if let Ok(entry) = entry { let path = entry.path(); if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("log") { if let Some(file_name) = path.file_name().and_then(|n| n.to_str()) { - if let Ok(file_date) = NaiveDate::parse_from_str(&file_name.replace(".log", ""), "%Y-%m-%d") { + if let Ok(file_date) = NaiveDate::parse_from_str( + &file_name.replace(".log", ""), + "%Y-%m-%d", + ) { if (now - file_date).num_days() >= days { if let Err(e) = fs::remove_file(&path) { if !self.silent { - println!("[LOG CLEANUP WARNING] {} cannot be removed: {}", path.display(), e); + println!( + "[LOG CLEANUP WARNING] {} cannot be removed: {}", + path.display(), + e + ); } } else if !self.silent { println!("[LOG CLEANUP] removed: {}", path.display()); @@ -422,4 +488,4 @@ impl VersaLog { self.cleanup_old_logs(7); } } -} \ No newline at end of file +}