auths_telemetry/logging.rs
1use tracing_subscriber::{EnvFilter, layer::SubscriberExt, util::SubscriberInitExt};
2
3/// Initialises the global tracing subscriber.
4///
5/// Reads `RUST_LOG` if set; falls back to `log_level`. Uses `.try_init()` so
6/// a second call (e.g. in tests) is a silent no-op rather than a panic.
7///
8/// Args:
9/// * `log_level`: Fallback log level string (e.g. `"info"`).
10/// * `json`: When `true`, emits structured JSON (machine-readable).
11/// When `false`, emits plain text (human-readable).
12///
13/// Usage:
14/// ```ignore
15/// auths_telemetry::init_tracing(&config.log_level, false);
16/// ```
17pub fn init_tracing(log_level: &str, json: bool) {
18 if json {
19 let _ = tracing_subscriber::registry()
20 .with(EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(log_level)))
21 .with(tracing_subscriber::fmt::layer().json())
22 .try_init();
23 } else {
24 let _ = tracing_subscriber::registry()
25 .with(EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(log_level)))
26 .with(tracing_subscriber::fmt::layer())
27 .try_init();
28 }
29}
30
31/// Initialises the global tracing subscriber with structured JSON output.
32///
33/// Thin wrapper around `init_tracing(log_level, true)` for backward compatibility.
34///
35/// Args:
36/// * `log_level`: Fallback log level string (e.g. `"info"`).
37///
38/// Usage:
39/// ```ignore
40/// auths_telemetry::init_json_tracing(&config.log_level);
41/// ```
42pub fn init_json_tracing(log_level: &str) {
43 init_tracing(log_level, true);
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 // These tests verify idempotency: calling init_tracing or init_json_tracing
51 // multiple times must never panic (the global subscriber is set only once).
52
53 #[test]
54 fn init_tracing_plain_is_idempotent() {
55 // First call installs the subscriber; subsequent calls are silent no-ops.
56 init_tracing("info", false);
57 init_tracing("debug", false); // must not panic
58 init_tracing("warn", false); // must not panic
59 }
60
61 #[test]
62 fn init_tracing_json_is_idempotent() {
63 init_tracing("info", true);
64 init_tracing("debug", true); // must not panic
65 }
66
67 #[test]
68 fn init_json_tracing_is_idempotent() {
69 init_json_tracing("info");
70 init_json_tracing("info"); // must not panic
71 }
72
73 #[test]
74 fn init_json_tracing_delegates_to_init_tracing() {
75 // Both should complete without error; the global subscriber is idempotent.
76 init_json_tracing("warn");
77 init_tracing("warn", true);
78 }
79}