Skip to main content

dicom_viewer/
logging.rs

1//! `tracing` setup writing a daily-rolled log to `logs/` next to the binary.
2//!
3//! Two layers are installed:
4//!
5//! * a non-blocking file writer producing `dicom-viewer.log.<YYYY-MM-DD>`
6//!   files (no ANSI colour, with target prefix);
7//! * the standard `tracing-subscriber` `fmt::layer` for stderr (so
8//!   `cargo run` shows the logs).
9//!
10//! The filter respects `RUST_LOG`, defaulting to
11//! `info,wgpu_core=warn,wgpu_hal=warn,naga=warn` when unset.
12
13use anyhow::Result;
14use tracing_appender::non_blocking::WorkerGuard;
15use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
16
17use crate::config::Paths;
18
19/// Initialise global tracing.
20///
21/// Returns a [`WorkerGuard`]; the caller **must keep it alive** for the
22/// process lifetime, otherwise buffered log lines may be dropped on exit.
23///
24/// # Errors
25/// Filesystem failures setting up the rolling file appender.
26pub fn init(paths: &Paths) -> Result<WorkerGuard> {
27    let file_appender = tracing_appender::rolling::daily(&paths.logs_dir, "dicom-viewer.log");
28    let (file_writer, guard) = tracing_appender::non_blocking(file_appender);
29
30    let env_filter = EnvFilter::try_from_default_env()
31        .unwrap_or_else(|_| EnvFilter::new("info,wgpu_core=warn,wgpu_hal=warn,naga=warn"));
32
33    let file_layer = fmt::layer()
34        .with_writer(file_writer)
35        .with_ansi(false)
36        .with_target(true);
37
38    let stderr_layer = fmt::layer().with_writer(std::io::stderr).with_target(false);
39
40    tracing_subscriber::registry()
41        .with(env_filter)
42        .with(file_layer)
43        .with(stderr_layer)
44        .init();
45
46    Ok(guard)
47}