embassy_ha/
log.rs

1//! Logging abstraction that works with both defmt and tracing.
2//!
3//! This module provides logging macros that can use either `defmt` (for embedded targets)
4//! or `tracing` (for desktop/testing) depending on the enabled cargo features.
5//!
6//! ## Features
7//!
8//! - `defmt`: Use defmt for logging
9//! - `tracing`: Use tracing for logging
10//! - Neither: Logging is compiled out (no-op)
11//!
12//! ## Usage
13//!
14//! ```rust,ignore
15//! use crate::log::{trace, debug, info, warn, error};
16//!
17//! info!("Application started");
18//! debug!("Value: {}", 42);
19//! warn!("Something unexpected: {:?}", some_value);
20//! ```
21
22// Re-export Format trait when using defmt
23#[cfg(feature = "defmt")]
24pub use defmt::Format;
25
26// For tracing or no logging, we provide a stub Format trait
27#[allow(unused)]
28#[cfg(not(feature = "defmt"))]
29pub trait Format {}
30
31// When using defmt, also provide Debug2Format for std types
32#[cfg(feature = "defmt")]
33pub use defmt::Debug2Format;
34
35// For tracing or no logging, Debug2Format is a passthrough
36#[allow(non_snake_case)]
37#[cfg(not(feature = "defmt"))]
38#[inline]
39pub fn Debug2Format<T>(value: &T) -> &T {
40    value
41}
42
43// Logging macros that dispatch to the appropriate backend or no-op
44// If both features are enabled, defmt takes precedence
45
46#[macro_export]
47macro_rules! trace {
48    ($($arg:tt)*) => {
49        #[cfg(feature = "defmt")]
50        defmt::trace!($($arg)*);
51
52        #[cfg(all(feature = "tracing", not(feature = "defmt")))]
53        tracing::trace!($($arg)*);
54
55        #[cfg(not(any(feature = "defmt", feature = "tracing")))]
56        { let _ = format_args!($($arg)*); } // no-op, format_args! borrows without moving
57    };
58}
59
60#[macro_export]
61macro_rules! debug {
62    ($($arg:tt)*) => {
63        #[cfg(feature = "defmt")]
64        defmt::debug!($($arg)*);
65
66        #[cfg(all(feature = "tracing", not(feature = "defmt")))]
67        tracing::debug!($($arg)*);
68
69        #[cfg(not(any(feature = "defmt", feature = "tracing")))]
70        { let _ = format_args!($($arg)*); } // no-op, format_args! borrows without moving
71    };
72}
73
74#[macro_export]
75macro_rules! info {
76    ($($arg:tt)*) => {
77        #[cfg(feature = "defmt")]
78        defmt::info!($($arg)*);
79
80        #[cfg(all(feature = "tracing", not(feature = "defmt")))]
81        tracing::info!($($arg)*);
82
83        #[cfg(not(any(feature = "defmt", feature = "tracing")))]
84        { let _ = format_args!($($arg)*); } // no-op, format_args! borrows without moving
85    };
86}
87
88#[macro_export]
89macro_rules! warn {
90    ($($arg:tt)*) => {
91        #[cfg(feature = "defmt")]
92        defmt::warn!($($arg)*);
93
94        #[cfg(all(feature = "tracing", not(feature = "defmt")))]
95        tracing::warn!($($arg)*);
96
97        #[cfg(not(any(feature = "defmt", feature = "tracing")))]
98        { let _ = format_args!($($arg)*); } // no-op, format_args! borrows without moving
99    };
100}
101
102#[macro_export]
103macro_rules! error {
104    ($($arg:tt)*) => {
105        #[cfg(feature = "defmt")]
106        defmt::error!($($arg)*);
107
108        #[cfg(all(feature = "tracing", not(feature = "defmt")))]
109        tracing::error!($($arg)*);
110
111        #[cfg(not(any(feature = "defmt", feature = "tracing")))]
112        { let _ = format_args!($($arg)*); } // no-op, format_args! borrows without moving
113    };
114}
115
116// Re-export the macros at the module level for easier use
117#[allow(unused)]
118pub use crate::{debug, error, info, trace, warn};