refactor: Made the creation of the log directories a bit more fault tolerant

This commit is contained in:
2025-09-12 13:07:49 -06:00
parent a6d22c8843
commit cb30cac47b
2 changed files with 54 additions and 35 deletions
+3 -1
View File
@@ -108,7 +108,9 @@ enum Commands {
} }
fn main() -> Result<()> { fn main() -> Result<()> {
log4rs::init_config(utils::init_logging_config())?; if let Err(e) = log4rs::init_config(utils::init_logging_config()) {
eprintln!("Failed to initialize logging: {e}");
}
panic::set_hook(Box::new(|info| { panic::set_hook(Box::new(|info| {
panic_hook(info); panic_hook(info);
})); }));
+44 -27
View File
@@ -1,4 +1,5 @@
use log::LevelFilter; use log::LevelFilter;
use log4rs::append::console::ConsoleAppender;
use log4rs::append::file::FileAppender; use log4rs::append::file::FileAppender;
use log4rs::config::{Appender, Root}; use log4rs::config::{Appender, Root};
use log4rs::encode::pattern::PatternEncoder; use log4rs::encode::pattern::PatternEncoder;
@@ -6,40 +7,60 @@ use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
pub fn init_logging_config() -> log4rs::Config { pub fn init_logging_config() -> log4rs::Config {
let logfile = FileAppender::builder() let encoder = Box::new(PatternEncoder::new(
.encoder(Box::new(PatternEncoder::new(
"{d(%Y-%m-%d %H:%M:%S%.3f)(utc)} <{i}> [{l}] {f}:{L} - {m}{n}", "{d(%Y-%m-%d %H:%M:%S%.3f)(utc)} <{i}> [{l}] {f}:{L} - {m}{n}",
))) ));
.build(get_log_path())
.unwrap();
log4rs::Config::builder() // Prefer file logging, but fall back to console if we cannot create/open the file.
.appender(Appender::builder().build("logfile", Box::new(logfile))) let file_appender = FileAppender::builder()
.encoder(encoder.clone())
.build(get_log_path());
match file_appender {
Ok(file) => log4rs::Config::builder()
.appender(Appender::builder().build("logfile", Box::new(file)))
.build( .build(
Root::builder() Root::builder()
.appender("logfile") .appender("logfile")
.build(LevelFilter::Debug), .build(LevelFilter::Debug),
) )
.unwrap(),
Err(e) => {
eprintln!(
"File logging disabled ({}). Falling back to console logging.",
e
);
let console = ConsoleAppender::builder().encoder(encoder).build();
log4rs::Config::builder()
.appender(Appender::builder().build("console", Box::new(console)))
.build(
Root::builder()
.appender("console")
.build(LevelFilter::Debug),
)
.unwrap() .unwrap()
}
}
} }
pub fn get_log_path() -> PathBuf { pub fn get_log_path() -> PathBuf {
let mut log_path = if cfg!(target_os = "linux") { // Use a cache directory on all platforms; fall back to temp dir as a last resort.
dirs::cache_dir().unwrap_or_else(|| PathBuf::from("~/.cache")) let base_dir = dirs::cache_dir().unwrap_or_else(std::env::temp_dir);
} else if cfg!(target_os = "macos") { let log_dir = base_dir.join("gman");
dirs::home_dir().unwrap().join("Library/Logs")
// Best-effort: create the directory; if it fails, write directly into temp dir.
let dir = if let Err(e) = fs::create_dir_all(&log_dir) {
eprintln!(
"Failed to create log directory '{}': {}",
log_dir.display(),
e
);
std::env::temp_dir()
} else { } else {
dirs::data_local_dir().unwrap_or_else(|| PathBuf::from("C:\\Logs")) log_dir
}; };
log_path.push("gman"); dir.join("gman.log")
if let Err(e) = fs::create_dir_all(&log_path) {
eprintln!("Failed to create log directory: {e:?}");
}
log_path.push("gman.log");
log_path
} }
#[cfg(test)] #[cfg(test)]
@@ -49,12 +70,8 @@ mod tests {
#[test] #[test]
fn test_get_log_path() { fn test_get_log_path() {
let log_path = get_log_path(); let log_path = get_log_path();
if cfg!(target_os = "linux") { assert!(log_path.ends_with("gman.log"));
assert!(log_path.ends_with(".cache/gman/gman.log")); // Parent directory may be cache dir or temp dir; ensure it is a valid path component.
} else if cfg!(target_os = "macos") { assert!(log_path.parent().is_some());
assert!(log_path.ends_with("Library/Logs/gman/gman.log"));
} else if cfg!(target_os = "windows") {
assert!(log_path.ends_with("Logs\\gman\\gman.log"));
}
} }
} }