asupersync/
tracing_compat.rs1#[cfg(feature = "tracing-integration")]
30pub use tracing::{
31 Instrument, Level, Span, debug, debug_span, error, error_span, event, info, info_span, span,
32 trace, trace_span, warn, warn_span,
33};
34
35#[cfg(feature = "proc-macros")]
36pub use asupersync_macros::instrument;
37
38#[cfg(not(feature = "tracing-integration"))]
40mod noop {
41 #[macro_export]
47 macro_rules! trace {
48 ($($arg:tt)*) => {};
49 }
50
51 #[macro_export]
53 macro_rules! debug {
54 ($($arg:tt)*) => {};
55 }
56
57 #[macro_export]
59 macro_rules! info {
60 ($($arg:tt)*) => {};
61 }
62
63 #[macro_export]
65 macro_rules! warn {
66 ($($arg:tt)*) => {};
67 }
68
69 #[macro_export]
71 macro_rules! error {
72 ($($arg:tt)*) => {};
73 }
74
75 #[macro_export]
77 macro_rules! event {
78 ($($arg:tt)*) => {};
79 }
80
81 #[macro_export]
83 macro_rules! span {
84 ($($arg:tt)*) => {
85 $crate::tracing_compat::NoopSpan
86 };
87 }
88
89 #[macro_export]
91 macro_rules! trace_span {
92 ($($arg:tt)*) => {
93 $crate::tracing_compat::NoopSpan
94 };
95 }
96
97 #[macro_export]
99 macro_rules! debug_span {
100 ($($arg:tt)*) => {
101 $crate::tracing_compat::NoopSpan
102 };
103 }
104
105 #[macro_export]
107 macro_rules! info_span {
108 ($($arg:tt)*) => {
109 $crate::tracing_compat::NoopSpan
110 };
111 }
112
113 #[macro_export]
115 macro_rules! warn_span {
116 ($($arg:tt)*) => {
117 $crate::tracing_compat::NoopSpan
118 };
119 }
120
121 #[macro_export]
123 macro_rules! error_span {
124 ($($arg:tt)*) => {
125 $crate::tracing_compat::NoopSpan
126 };
127 }
128
129 pub use crate::{
131 debug, debug_span, error, error_span, event, info, info_span, span, trace, trace_span,
132 warn, warn_span,
133 };
134}
135
136#[cfg(not(feature = "tracing-integration"))]
137pub use noop::*;
138
139#[cfg(not(feature = "tracing-integration"))]
145#[derive(Debug, Clone, Copy)]
146pub struct NoopSpan;
147
148#[cfg(not(feature = "tracing-integration"))]
149impl NoopSpan {
150 #[inline]
152 #[must_use]
153 pub fn enter(&self) -> NoopGuard {
154 NoopGuard
155 }
156
157 #[inline]
159 #[must_use]
160 pub fn entered(self) -> Self {
161 self
162 }
163
164 #[inline]
166 #[must_use]
167 pub fn or_current(self) -> Self {
168 self
169 }
170
171 #[inline]
173 pub fn follows_from(&self, _span: &Self) {}
174
175 #[inline]
177 #[must_use]
178 pub fn is_disabled(&self) -> bool {
179 true
180 }
181
182 #[inline]
184 pub fn record<V>(&self, _field: &str, _value: V) {}
185
186 #[inline]
188 #[must_use]
189 pub fn current() -> Self {
190 Self
191 }
192
193 #[inline]
195 #[must_use]
196 pub fn none() -> Self {
197 Self
198 }
199}
200
201#[cfg(not(feature = "tracing-integration"))]
203#[derive(Debug)]
204pub struct NoopGuard;
205
206#[cfg(not(feature = "tracing-integration"))]
208#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
209pub struct Level;
210
211#[cfg(not(feature = "tracing-integration"))]
212impl Level {
213 pub const TRACE: Self = Self;
215 pub const DEBUG: Self = Self;
217 pub const INFO: Self = Self;
219 pub const WARN: Self = Self;
221 pub const ERROR: Self = Self;
223}
224
225#[cfg(not(feature = "tracing-integration"))]
227pub type Span = NoopSpan;
228
229#[cfg(not(feature = "tracing-integration"))]
234pub trait Instrument: Sized {
235 #[must_use]
237 fn instrument(self, _span: NoopSpan) -> Self {
238 self
239 }
240
241 #[must_use]
243 fn in_current_span(self) -> Self {
244 self
245 }
246}
247
248#[cfg(not(feature = "tracing-integration"))]
249impl<T> Instrument for T {}
250
251#[cfg(test)]
252mod tests {
253 #![allow(
254 clippy::pedantic,
255 clippy::nursery,
256 clippy::expect_fun_call,
257 clippy::map_unwrap_or,
258 clippy::cast_possible_wrap,
259 clippy::future_not_send
260 )]
261 use super::*;
262 use crate::test_utils::init_test_logging;
263 #[cfg(feature = "proc-macros")]
264 use futures_lite::future::block_on;
265
266 fn init_test(test_name: &str) {
267 init_test_logging();
268 crate::test_phase!(test_name);
269 }
270
271 #[cfg(feature = "proc-macros")]
272 #[super::instrument]
273 fn instrumented_sync_add(task_id: u32, label: &str) -> usize {
274 usize::try_from(task_id).expect("task_id fits usize") + label.len()
275 }
276
277 #[cfg(feature = "proc-macros")]
278 struct InstrumentedWorker;
279
280 #[cfg(feature = "proc-macros")]
281 impl InstrumentedWorker {
282 #[super::instrument(level = "debug", skip(self))]
283 fn tick(&self, value: usize) -> usize {
284 value + 1
285 }
286 }
287
288 #[cfg(feature = "proc-macros")]
289 #[super::instrument(name = "instrumented_async_len", level = "trace", skip(secret))]
290 async fn instrumented_async_len(secret: String, visible: usize) -> usize {
291 visible + secret.len()
292 }
293
294 #[test]
295 fn test_noop_macros_compile() {
296 init_test("test_noop_macros_compile");
297 trace!("trace message");
299 debug!("debug message");
300 info!("info message");
301 warn!("warn message");
302 error!("error message");
303
304 trace!(field = "value", "trace with field");
305 debug!(count = 42, "debug with field");
306 info!(name = "test", "info with field");
307 crate::test_complete!("test_noop_macros_compile");
308 }
309
310 #[test]
311 fn test_noop_span_compile() {
312 init_test("test_noop_span_compile");
313 let span = span!(Level::INFO, "test_span");
314 let _guard = span.enter();
315
316 let span2 = info_span!("info_span");
317 let _entered = span2.entered();
318
319 let span3 = debug_span!("debug_span", task_id = 42);
320 span3.record("field", "value");
321 crate::test_complete!("test_noop_span_compile");
322 }
323
324 #[test]
325 fn test_noop_level_constants() {
326 init_test("test_noop_level_constants");
327 crate::test_complete!("test_noop_level_constants");
330 }
331
332 #[test]
333 fn test_noop_span_methods() {
334 init_test("test_noop_span_methods");
335 #[cfg(not(feature = "tracing-integration"))]
336 {
337 let span = NoopSpan;
338 let disabled = span.is_disabled();
339 crate::assert_with_log!(disabled, "noop span should be disabled", true, disabled);
340
341 let current = NoopSpan::current();
342 let none = NoopSpan::none();
343 let _ = current.or_current();
344 none.follows_from(&span);
345 }
346 crate::test_complete!("test_noop_span_methods");
347 }
348
349 #[test]
350 fn noop_guard_debug() {
351 #[cfg(not(feature = "tracing-integration"))]
352 {
353 let guard = NoopGuard;
354 let dbg = format!("{guard:?}");
355 assert!(dbg.contains("NoopGuard"), "{dbg}");
356 }
357 }
358
359 #[test]
360 fn noop_span_debug_clone_copy() {
361 #[cfg(not(feature = "tracing-integration"))]
362 {
363 let span = NoopSpan;
364 let dbg = format!("{span:?}");
365 assert!(dbg.contains("NoopSpan"), "{dbg}");
366
367 let copied = span;
368 let cloned = span;
369 assert!(copied.is_disabled());
370 assert!(cloned.is_disabled());
371 }
372 }
373
374 #[test]
375 fn level_equality_and_ordering() {
376 #[cfg(not(feature = "tracing-integration"))]
377 {
378 assert_eq!(Level::TRACE, Level::DEBUG);
380 assert_eq!(Level::INFO, Level::WARN);
381 assert_eq!(Level::WARN, Level::ERROR);
382
383 assert!(Level::TRACE <= Level::ERROR);
385
386 let dbg = format!("{:?}", Level::INFO);
388 assert!(dbg.contains("Level"), "{dbg}");
389
390 let l = Level::INFO;
392 let copied = l;
393 let cloned = l;
394 assert_eq!(copied, cloned);
395 }
396 }
397
398 #[test]
399 fn span_type_alias_works() {
400 #[cfg(not(feature = "tracing-integration"))]
401 {
402 let span: Span = NoopSpan::current();
403 let _guard = span.enter();
404 }
405 }
406
407 #[test]
408 fn all_span_macros_compile() {
409 #[cfg(not(feature = "tracing-integration"))]
410 {
411 let _ = trace_span!("t");
412 let _ = debug_span!("d");
413 let _ = info_span!("i");
414 let _ = warn_span!("w");
415 let _ = error_span!("e");
416 }
417 }
418
419 #[test]
420 fn instrument_trait_noop() {
421 #[cfg(not(feature = "tracing-integration"))]
422 {
423 let fut = async { 42 };
424 let instrumented = fut.instrument(NoopSpan);
425 drop(async { 1 }.in_current_span());
427 drop(instrumented);
428 }
429 }
430
431 #[cfg(feature = "proc-macros")]
432 #[test]
433 fn instrument_attribute_wraps_sync_functions() {
434 init_test("instrument_attribute_wraps_sync_functions");
435 let value = instrumented_sync_add(7, "abc");
436 crate::assert_with_log!(value == 10, "sync result", 10usize, value);
437 crate::test_complete!("instrument_attribute_wraps_sync_functions");
438 }
439
440 #[cfg(feature = "proc-macros")]
441 #[test]
442 fn instrument_attribute_wraps_methods() {
443 init_test("instrument_attribute_wraps_methods");
444 let worker = InstrumentedWorker;
445 let value = worker.tick(9);
446 crate::assert_with_log!(value == 10, "method result", 10usize, value);
447 crate::test_complete!("instrument_attribute_wraps_methods");
448 }
449
450 #[cfg(feature = "proc-macros")]
451 #[test]
452 fn instrument_attribute_wraps_async_functions() {
453 init_test("instrument_attribute_wraps_async_functions");
454 let value = block_on(instrumented_async_len("secret".to_string(), 4));
455 crate::assert_with_log!(value == 10, "async result", 10usize, value);
456 crate::test_complete!("instrument_attribute_wraps_async_functions");
457 }
458}