Skip to main content

tvscreener/
logging.rs

1// Copyright 2026 tvscreener-rs contributors
2// SPDX-License-Identifier: Apache-2.0
3
4//! Process logging helpers (`tracing` + stderr subscriber install).
5
6/// Returns true when `TVSCREENER_DEBUG` is set to a truthy value (`1`, `true`, `yes`, `on`).
7#[must_use]
8pub fn env_debug_enabled() -> bool {
9    std::env::var("TVSCREENER_DEBUG").is_ok_and(|v| {
10        matches!(
11            v.trim().to_ascii_lowercase().as_str(),
12            "1" | "true" | "yes" | "on"
13        )
14    })
15}
16
17/// Installs a stderr [`tracing`] subscriber.
18///
19/// Filter resolution order:
20/// 1. `RUST_LOG` (standard [`tracing_subscriber::EnvFilter`])
21/// 2. else if [`env_debug_enabled`], `tvscreener=debug,info`
22/// 3. else `info`
23///
24/// Logs go to **stderr** so CLI/MCP stdout stays for data / protocol.
25///
26/// Requires the `cli` Cargo feature (pulled in by `mcp`, `tui`, and `apps`).
27///
28/// # Panics
29///
30/// Panics if a global subscriber was already set (call once at process start).
31#[cfg(feature = "cli")]
32pub fn init_logging() {
33    use tracing_subscriber::EnvFilter;
34
35    let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| {
36        if env_debug_enabled() {
37            EnvFilter::new("tvscreener=debug,info")
38        } else {
39            EnvFilter::new("info")
40        }
41    });
42
43    tracing_subscriber::fmt()
44        .with_env_filter(filter)
45        .with_writer(std::io::stderr)
46        .with_target(true)
47        .init();
48}
49
50#[cfg(test)]
51mod tests {
52    use super::env_debug_enabled;
53
54    #[test]
55    fn env_debug_truthy_and_falsey() {
56        let prev = std::env::var_os("TVSCREENER_DEBUG");
57        // SAFETY: test-only env mutation; this suite does not run concurrent env readers.
58        unsafe {
59            std::env::remove_var("TVSCREENER_DEBUG");
60        }
61        assert!(!env_debug_enabled());
62
63        for truthy in ["1", "true", "YES", "on"] {
64            unsafe {
65                std::env::set_var("TVSCREENER_DEBUG", truthy);
66            }
67            assert!(env_debug_enabled(), "expected truthy for {truthy}");
68        }
69        for falsey in ["0", "false", "off", "no"] {
70            unsafe {
71                std::env::set_var("TVSCREENER_DEBUG", falsey);
72            }
73            assert!(!env_debug_enabled(), "expected falsey for {falsey}");
74        }
75
76        unsafe {
77            match prev {
78                Some(v) => std::env::set_var("TVSCREENER_DEBUG", v),
79                None => std::env::remove_var("TVSCREENER_DEBUG"),
80            }
81        }
82    }
83}