shell_tunnel/logging.rs
1//! Logging initialization and configuration.
2
3use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
4
5/// Initialize the logging system.
6///
7/// Uses the `RUST_LOG` environment variable for filtering. If not set,
8/// defaults to `shell_tunnel=info`.
9///
10/// Diagnostics go to stderr, which leaves stdout for the things a caller wants
11/// to read: the public URL, the API key, the command to try. Sharing one stream
12/// means `shell-tunnel --tunnel | grep "Public URL"` picks up log lines instead.
13///
14/// # Panics
15///
16/// Panics if called more than once, or if another tracing subscriber
17/// has already been set.
18pub fn init() {
19 let filter =
20 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("shell_tunnel=info"));
21
22 tracing_subscriber::registry()
23 .with(filter)
24 .with(
25 tracing_subscriber::fmt::layer()
26 .compact()
27 .with_writer(std::io::stderr),
28 )
29 .init();
30}
31
32/// Try to initialize the logging system.
33///
34/// Returns `Ok(())` if successful, or `Err` if logging has already been
35/// initialized.
36pub fn try_init() -> Result<(), tracing_subscriber::util::TryInitError> {
37 let filter =
38 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("shell_tunnel=info"));
39
40 tracing_subscriber::registry()
41 .with(filter)
42 .with(
43 tracing_subscriber::fmt::layer()
44 .compact()
45 .with_writer(std::io::stderr),
46 )
47 .try_init()
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[test]
55 fn test_try_init_idempotent() {
56 // First call may or may not succeed depending on test order
57 let _ = try_init();
58 // Second call should return error (already initialized)
59 // or succeed if this is the first test to run
60 let _ = try_init();
61 // Either way, we shouldn't panic
62 }
63
64 #[test]
65 fn test_logging_works() {
66 // Ensure we can emit log messages without panicking
67 let _ = try_init();
68
69 tracing::info!("test info message");
70 tracing::debug!("test debug message");
71 tracing::warn!("test warn message");
72 tracing::error!("test error message");
73 // If we get here without panicking, the test passes
74 }
75}