Skip to main content

shunt/
logging.rs

1use anyhow::Result;
2use std::path::Path;
3use tracing_appender::non_blocking::WorkerGuard;
4use tracing_subscriber::layer::SubscriberExt;
5use tracing_subscriber::util::SubscriberInitExt;
6use tracing_subscriber::{EnvFilter, Layer};
7
8/// Initialise logging: JSON lines to file + human-readable to stderr.
9///
10/// Returns a `WorkerGuard` that must be kept alive for the duration of the
11/// process — dropping it flushes and closes the log file writer.
12pub fn setup(log_file: &Path, level: &str) -> Result<WorkerGuard> {
13    if let Some(parent) = log_file.parent() {
14        std::fs::create_dir_all(parent)?;
15    }
16
17    let file_appender = tracing_appender::rolling::daily(
18        log_file.parent().unwrap_or(Path::new(".")),
19        log_file.file_name().unwrap_or(std::ffi::OsStr::new("proxy.log")),
20    );
21    let (non_blocking, guard) = tracing_appender::non_blocking(file_appender);
22
23    let filter = EnvFilter::try_from_default_env()
24        .unwrap_or_else(|_| EnvFilter::new(level));
25
26    let file_layer = tracing_subscriber::fmt::layer()
27        .json()
28        .with_writer(non_blocking)
29        .with_filter(filter.clone());
30
31    let stderr_layer = tracing_subscriber::fmt::layer()
32        .with_target(false)
33        .with_filter(filter);
34
35    tracing_subscriber::registry()
36        .with(file_layer)
37        .with(stderr_layer)
38        .init();
39
40    Ok(guard)
41}