use anyhow::{Context, Result};
use std::fs;
use std::path::PathBuf;
use tracing_subscriber::{EnvFilter, fmt, prelude::*, registry};
pub fn init_debug_logging(debug_enabled: bool) -> Result<Option<PathBuf>> {
if !debug_enabled {
return Ok(None);
}
let log_path = get_log_path()?;
if let Some(parent) = log_path.parent() {
fs::create_dir_all(parent)
.with_context(|| format!("Failed to create log directory: {}", parent.display()))?;
}
let file = fs::OpenOptions::new()
.create(true)
.append(true)
.open(&log_path)
.with_context(|| format!("Failed to open log file: {}", log_path.display()));
match file {
Ok(log_file) => {
let subscriber = registry()
.with(
fmt::layer()
.with_writer(log_file)
.with_ansi(false)
.with_target(false)
.with_thread_ids(false)
.with_file(false)
.with_line_number(false),
)
.with(EnvFilter::new("sedx=info"));
tracing::subscriber::set_global_default(subscriber)
.map_err(|e| anyhow::anyhow!("Failed to set tracing subscriber: {}", e))?;
Ok(Some(log_path))
}
Err(e) => {
eprintln!("Warning: Could not create log file: {}", e);
Ok(None)
}
}
}
fn get_log_path() -> Result<PathBuf> {
let var_log_path = PathBuf::from("/var/log/sedx.log");
if can_write_to_var_log() {
return Ok(var_log_path);
}
let home_dir =
dirs::home_dir().ok_or_else(|| anyhow::anyhow!("Cannot determine home directory"))?;
let sedx_dir = home_dir.join(".sedx");
Ok(sedx_dir.join("sedx.log"))
}
fn can_write_to_var_log() -> bool {
let test_file = "/var/log/.sedx_test_write";
match fs::write(test_file, b"") {
Ok(_) => {
let _ = fs::remove_file(test_file);
true
}
Err(_) => false,
}
}
pub fn get_current_log_path() -> PathBuf {
if can_write_to_var_log() {
PathBuf::from("/var/log/sedx.log")
} else {
dirs::home_dir()
.map(|h| h.join(".sedx/sedx.log"))
.unwrap_or_else(|| PathBuf::from("~/.sedx/sedx.log"))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_current_log_path() {
let path = get_current_log_path();
#[allow(clippy::cmp_owned)]
let is_var_log = path == PathBuf::from("/var/log/sedx.log");
assert!(
is_var_log || path.ends_with(".sedx/sedx.log"),
"Log path should be either /var/log/sedx.log or in .sedx directory, got: {}",
path.display()
);
}
#[test]
fn test_init_debug_logging_disabled() {
let result = init_debug_logging(false);
assert!(result.is_ok());
assert_eq!(
result.unwrap(),
None,
"Should return None when debug is disabled"
);
}
#[test]
fn test_can_write_to_var_log() {
let _can_write = can_write_to_var_log();
}
}