1use std::sync::atomic::{AtomicBool, Ordering};
8
9static DEBUG_ENABLED: AtomicBool = AtomicBool::new(false);
10
11pub fn init() {
13 let enabled = cfg!(debug_assertions) || std::env::var("SPIKARD_DEBUG").is_ok() || std::env::var("DEBUG").is_ok();
14
15 eprintln!(
16 "[spikard-http::debug] init() called, cfg!(debug_assertions)={}, DEBUG={}, enabled={}",
17 cfg!(debug_assertions),
18 std::env::var("DEBUG").is_ok(),
19 enabled
20 );
21
22 DEBUG_ENABLED.store(enabled, Ordering::Relaxed);
23
24 if enabled {
25 eprintln!("[spikard-http] Debug logging enabled");
26 }
27}
28
29#[inline]
31pub fn is_enabled() -> bool {
32 DEBUG_ENABLED.load(Ordering::Relaxed)
33}
34
35#[macro_export]
37macro_rules! debug_log {
38 ($($arg:tt)*) => {
39 if $crate::debug::is_enabled() {
40 eprintln!("[spikard-http] {}", format!($($arg)*));
41 }
42 };
43}
44
45#[macro_export]
47macro_rules! debug_log_module {
48 ($module:expr, $($arg:tt)*) => {
49 if $crate::debug::is_enabled() {
50 eprintln!("[spikard-http::{}] {}", $module, format!($($arg)*));
51 }
52 };
53}
54
55#[macro_export]
57macro_rules! debug_log_value {
58 ($name:expr, $value:expr) => {
59 if $crate::debug::is_enabled() {
60 eprintln!("[spikard-http] {} = {:?}", $name, $value);
61 }
62 };
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use std::sync::Mutex;
69 use std::sync::atomic::Ordering;
70
71 static FLAG_LOCK: Mutex<()> = Mutex::new(());
72
73 struct DebugFlagGuard {
74 previous_flag: bool,
75 previous_env: Option<String>,
76 }
77
78 impl Drop for DebugFlagGuard {
79 fn drop(&mut self) {
80 DEBUG_ENABLED.store(self.previous_flag, Ordering::Relaxed);
81 if let Some(prev) = &self.previous_env {
82 unsafe { std::env::set_var("SPIKARD_DEBUG", prev) };
83 } else {
84 unsafe { std::env::remove_var("SPIKARD_DEBUG") };
85 }
86 }
87 }
88
89 #[test]
90 fn init_enables_debug_when_requested() {
91 let _lock = FLAG_LOCK.lock().unwrap();
92 let previous = DEBUG_ENABLED.load(Ordering::Relaxed);
93 let previous_env = std::env::var("SPIKARD_DEBUG").ok();
94 let _guard = DebugFlagGuard {
95 previous_flag: previous,
96 previous_env,
97 };
98
99 unsafe { std::env::set_var("SPIKARD_DEBUG", "1") };
100
101 init();
102
103 assert!(is_enabled(), "init should enable debug in test builds");
104 }
105
106 #[test]
107 fn macros_respect_debug_flag() {
108 let _lock = FLAG_LOCK.lock().unwrap();
109 let previous = DEBUG_ENABLED.load(Ordering::Relaxed);
110 let previous_env = std::env::var("SPIKARD_DEBUG").ok();
111 let _guard = DebugFlagGuard {
112 previous_flag: previous,
113 previous_env,
114 };
115
116 DEBUG_ENABLED.store(false, Ordering::Relaxed);
117 debug_log!("should not print while disabled");
118 debug_log_module!("middleware", "disabled branch");
119 debug_log_value!("key", 1_u8);
120 assert!(!is_enabled());
121
122 DEBUG_ENABLED.store(true, Ordering::Relaxed);
123 debug_log!("now printing {}", 2);
124 debug_log_module!("router", "enabled branch");
125 debug_log_value!("value", 3_i32);
126 assert!(is_enabled());
127 }
128}