Skip to main content

evo_common/
logging.rs

1use std::env;
2use std::path::PathBuf;
3use tracing_appender::non_blocking::WorkerGuard;
4use tracing_subscriber::EnvFilter;
5use tracing_subscriber::fmt;
6use tracing_subscriber::prelude::*;
7
8const DEFAULT_LOG_DIR: &str = "./logs";
9const ENV_LOG_DIR: &str = "EVO_LOG_DIR";
10
11pub fn log_dir() -> PathBuf {
12    env::var(ENV_LOG_DIR)
13        .map(PathBuf::from)
14        .unwrap_or_else(|_| PathBuf::from(DEFAULT_LOG_DIR))
15}
16
17pub fn init_logging(component: &str) -> WorkerGuard {
18    let dir = log_dir();
19    std::fs::create_dir_all(&dir).expect("Failed to create log directory");
20
21    let file_appender = tracing_appender::rolling::daily(&dir, format!("{component}.log"));
22    let (non_blocking, guard) = tracing_appender::non_blocking(file_appender);
23
24    let file_layer = fmt::layer()
25        .json()
26        .with_writer(non_blocking)
27        .with_target(true)
28        .with_thread_ids(true)
29        .with_file(true)
30        .with_line_number(true);
31
32    let stdout_layer = fmt::layer().with_target(true).with_thread_ids(false);
33
34    let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
35
36    tracing_subscriber::registry()
37        .with(filter)
38        .with(file_layer)
39        .with(stdout_layer)
40        .init();
41
42    guard
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn default_log_dir() {
51        unsafe { env::remove_var(ENV_LOG_DIR) };
52        assert_eq!(log_dir(), PathBuf::from("./logs"));
53    }
54
55    #[test]
56    fn custom_log_dir() {
57        unsafe { env::set_var(ENV_LOG_DIR, "/tmp/evo-test-logs") };
58        assert_eq!(log_dir(), PathBuf::from("/tmp/evo-test-logs"));
59        unsafe { env::remove_var(ENV_LOG_DIR) };
60    }
61}