Skip to main content

aria2_core/
log.rs

1use std::sync::OnceLock;
2use tracing::Level;
3use tracing_subscriber::{
4    EnvFilter,
5    fmt::{self, format::FmtSpan},
6    layer::{Layer, SubscriberExt},
7    util::SubscriberInitExt,
8};
9
10static LOG_GUARD: OnceLock<Vec<tracing_appender::non_blocking::WorkerGuard>> = OnceLock::new();
11
12fn parse_log_level(level_str: &str) -> Level {
13    match level_str.to_lowercase().as_str() {
14        "debug" => Level::DEBUG,
15        "info" | "notice" => Level::INFO,
16        "warn" => Level::WARN,
17        "error" => Level::ERROR,
18        _ => Level::INFO,
19    }
20}
21
22pub fn init_logging(
23    log_level: &str,
24    console_log_level: &str,
25    log_file: Option<&str>,
26    log_backup_count: usize,
27) {
28    let file_level = parse_log_level(log_level);
29    let console_level = parse_log_level(console_log_level);
30
31    let enable_file_logging = log_file.is_some_and(|f| f != "-");
32
33    if enable_file_logging {
34        let path = log_file.unwrap();
35        let p = std::path::Path::new(path);
36        let dir = p
37            .parent()
38            .map(|d| d.to_string_lossy().to_string())
39            .unwrap_or_else(|| ".".to_string());
40        let stem = p
41            .file_name()
42            .map(|n| n.to_string_lossy().to_string())
43            .unwrap_or_else(|| "aria2.log".to_string());
44
45        use tracing_appender::non_blocking;
46        use tracing_appender::rolling::Rotation;
47        let file_appender = tracing_appender::rolling::Builder::new()
48            .rotation(Rotation::DAILY)
49            .filename_prefix(&stem)
50            .max_log_files(log_backup_count)
51            .build(&dir)
52            .unwrap_or_else(|_| tracing_appender::rolling::daily(&dir, &stem));
53        let (non_blocking, guard) = non_blocking(file_appender);
54        let _ = LOG_GUARD.set(vec![guard]);
55
56        let file_filter = EnvFilter::from_default_env()
57            .add_directive(file_level.into())
58            .add_directive("hyper=warn".parse().unwrap())
59            .add_directive("reqwest=warn".parse().unwrap());
60
61        let console_filter = EnvFilter::from_default_env()
62            .add_directive(console_level.into())
63            .add_directive("hyper=warn".parse().unwrap())
64            .add_directive("reqwest=warn".parse().unwrap());
65
66        let console_layer = fmt::layer()
67            .with_span_events(FmtSpan::CLOSE)
68            .with_target(false)
69            .with_filter(console_filter);
70
71        let file_layer = fmt::Layer::new()
72            .with_span_events(FmtSpan::CLOSE)
73            .with_target(false)
74            .with_writer(non_blocking)
75            .with_filter(file_filter);
76
77        let _ = tracing_subscriber::registry()
78            .with(console_layer)
79            .with(file_layer)
80            .try_init();
81    } else {
82        let env_filter = EnvFilter::from_default_env()
83            .add_directive(console_level.into())
84            .add_directive("hyper=warn".parse().unwrap())
85            .add_directive("reqwest=warn".parse().unwrap());
86
87        let _ = tracing_subscriber::registry()
88            .with(env_filter)
89            .with(
90                fmt::layer()
91                    .with_span_events(FmtSpan::CLOSE)
92                    .with_target(false),
93            )
94            .try_init();
95    }
96
97    tracing::info!("Log system initialization complete");
98}