Skip to main content

ftui_core/
logging.rs

1#![forbid(unsafe_code)]
2
3//! Logging and tracing support.
4//!
5//! This module provides re-exports of tracing macros when the `tracing` feature is enabled.
6//! When the feature is disabled, no-op macros are provided for compatibility.
7
8#[cfg(feature = "tracing")]
9pub use tracing::{
10    debug, debug_span, error, error_span, info, info_span, trace, trace_span, warn, warn_span,
11};
12
13// When tracing is not enabled, provide no-op macros
14#[cfg(not(feature = "tracing"))]
15mod noop_macros {
16    /// No-op debug macro when tracing is disabled.
17    #[macro_export]
18    macro_rules! debug {
19        ($($arg:tt)*) => {};
20    }
21
22    /// No-op debug_span macro when tracing is disabled.
23    #[macro_export]
24    macro_rules! debug_span {
25        ($($arg:tt)*) => {
26            $crate::logging::NoopSpan
27        };
28    }
29
30    /// No-op error macro when tracing is disabled.
31    #[macro_export]
32    macro_rules! error {
33        ($($arg:tt)*) => {};
34    }
35
36    /// No-op error_span macro when tracing is disabled.
37    #[macro_export]
38    macro_rules! error_span {
39        ($($arg:tt)*) => {
40            $crate::logging::NoopSpan
41        };
42    }
43
44    /// No-op info macro when tracing is disabled.
45    #[macro_export]
46    macro_rules! info {
47        ($($arg:tt)*) => {};
48    }
49
50    /// No-op info_span macro when tracing is disabled.
51    #[macro_export]
52    macro_rules! info_span {
53        ($($arg:tt)*) => {
54            $crate::logging::NoopSpan
55        };
56    }
57
58    /// No-op trace macro when tracing is disabled.
59    #[macro_export]
60    macro_rules! trace {
61        ($($arg:tt)*) => {};
62    }
63
64    /// No-op trace_span macro when tracing is disabled.
65    #[macro_export]
66    macro_rules! trace_span {
67        ($($arg:tt)*) => {
68            $crate::logging::NoopSpan
69        };
70    }
71
72    /// No-op warn macro when tracing is disabled.
73    #[macro_export]
74    macro_rules! warn {
75        ($($arg:tt)*) => {};
76    }
77
78    /// No-op warn_span macro when tracing is disabled.
79    #[macro_export]
80    macro_rules! warn_span {
81        ($($arg:tt)*) => {
82            $crate::logging::NoopSpan
83        };
84    }
85}
86
87// Note: Macros are exported at crate root via #[macro_export],
88// so we don't need to re-export noop_macros::* here.
89
90/// A no-op span guard for when tracing is disabled.
91#[cfg(not(feature = "tracing"))]
92pub struct NoopSpan;
93
94#[cfg(not(feature = "tracing"))]
95impl NoopSpan {
96    /// Enter the no-op span (does nothing).
97    pub fn enter(&self) -> NoopGuard {
98        NoopGuard
99    }
100}
101
102/// A no-op span guard.
103#[cfg(not(feature = "tracing"))]
104pub struct NoopGuard;
105
106#[cfg(test)]
107#[cfg(not(feature = "tracing"))]
108mod tests {
109    use super::*;
110    // Import #[macro_export] macros from crate root
111    use crate::{
112        debug, debug_span, error, error_span, info, info_span, trace, trace_span, warn, warn_span,
113    };
114
115    #[test]
116    fn noop_span_enter_returns_guard() {
117        let span = NoopSpan;
118        let _guard = span.enter();
119    }
120
121    #[test]
122    fn noop_span_enter_multiple_times() {
123        let span = NoopSpan;
124        let _g1 = span.enter();
125        let _g2 = span.enter();
126        let _g3 = span.enter();
127    }
128
129    #[test]
130    fn noop_guard_drops_silently() {
131        let span = NoopSpan;
132        {
133            let _guard = span.enter();
134        }
135        // Guard dropped without issue
136    }
137
138    #[test]
139    fn noop_macros_compile_and_are_silent() {
140        // These should all compile to nothing
141        debug!("test message");
142        info!("test {}", 42);
143        warn!("warning {val}", val = "test");
144        error!("error");
145        trace!("trace");
146    }
147
148    #[test]
149    fn noop_span_macros_return_noop_span() {
150        let span = debug_span!("test_span");
151        let _guard = span.enter();
152
153        let span2 = info_span!("other_span", key = "value");
154        let _guard2 = span2.enter();
155    }
156
157    #[test]
158    fn noop_span_macros_all_levels() {
159        let _s1 = debug_span!("d");
160        let _s2 = error_span!("e");
161        let _s3 = info_span!("i");
162        let _s4 = trace_span!("t");
163        let _s5 = warn_span!("w");
164    }
165
166    #[test]
167    fn entered_pattern() {
168        // Common pattern: let _span = span!(...).entered()
169        // NoopSpan doesn't have .entered(), it uses .enter()
170        // Verify the pattern works
171        let _guard = debug_span!("my_span").enter();
172    }
173}