use std::path::PathBuf;
use tracing_appender::non_blocking::WorkerGuard;
use tracing_subscriber::EnvFilter;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
fn log_dir() -> anyhow::Result<PathBuf> {
if let Ok(dir) = std::env::var("SEVAL_LOG_DIR") {
return Ok(PathBuf::from(dir));
}
let base = directories::BaseDirs::new()
.ok_or_else(|| anyhow::anyhow!("could not determine home directory"))?;
Ok(base.home_dir().join(".seval").join("logs"))
}
pub fn init_logging() -> anyhow::Result<WorkerGuard> {
let dir = log_dir()?;
std::fs::create_dir_all(&dir)?;
let file_appender = tracing_appender::rolling::daily(&dir, "seval.log");
let (non_blocking, guard) = tracing_appender::non_blocking(file_appender);
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
tracing_subscriber::registry()
.with(env_filter)
.with(
tracing_subscriber::fmt::layer()
.with_writer(non_blocking)
.with_ansi(false)
.with_file(true)
.with_line_number(true),
)
.init();
Ok(guard)
}
#[cfg(test)]
mod tests {
use std::io::Read;
use tempfile::TempDir;
#[test]
fn log_dir_ends_with_seval_logs() {
let dir = super::log_dir().expect("should resolve home directory");
assert!(dir.ends_with(".seval/logs"), "unexpected log dir: {dir:?}");
}
#[test]
fn writes_log_to_file() {
let tmp = TempDir::new().unwrap();
let file_appender = tracing_appender::rolling::daily(tmp.path(), "test.log");
let (non_blocking, guard) = tracing_appender::non_blocking(file_appender);
let subscriber = tracing_subscriber::fmt()
.with_writer(non_blocking)
.with_ansi(false)
.finish();
tracing::subscriber::with_default(subscriber, || {
tracing::info!("hello from test");
});
drop(guard);
let mut found = false;
for entry in std::fs::read_dir(tmp.path()).unwrap() {
let entry = entry.unwrap();
let mut contents = String::new();
std::fs::File::open(entry.path())
.unwrap()
.read_to_string(&mut contents)
.unwrap();
if contents.contains("hello from test") {
found = true;
assert!(
!contents.contains("\x1b["),
"log should not contain ANSI codes"
);
}
}
assert!(found, "expected log file containing 'hello from test'");
}
}