mabi_core/logging/macros.rs
1//! Logging and tracing macros.
2//!
3//! This module provides convenient macros for structured logging and tracing.
4
5/// Create a span for tracing protocol requests.
6///
7/// This macro creates a structured span with standard fields for request tracing.
8///
9/// # Example
10///
11/// ```rust,ignore
12/// use mabi_core::trace_request;
13///
14/// async fn handle_request() {
15/// let _span = trace_request!("modbus", "read_registers");
16/// // ... request handling
17/// }
18/// ```
19#[macro_export]
20macro_rules! trace_request {
21 ($protocol:expr, $operation:expr) => {
22 tracing::info_span!(
23 "request",
24 protocol = $protocol,
25 operation = $operation,
26 request_id = %uuid::Uuid::new_v4(),
27 )
28 };
29 ($protocol:expr, $operation:expr, $($field:tt)*) => {
30 tracing::info_span!(
31 "request",
32 protocol = $protocol,
33 operation = $operation,
34 request_id = %uuid::Uuid::new_v4(),
35 $($field)*
36 )
37 };
38}
39
40/// Create a span for tracing device operations.
41///
42/// # Example
43///
44/// ```rust,ignore
45/// use mabi_core::trace_device;
46///
47/// async fn device_tick(device_id: &str) {
48/// let _span = trace_device!(device_id, "tick");
49/// // ... device processing
50/// }
51/// ```
52#[macro_export]
53macro_rules! trace_device {
54 ($device_id:expr, $operation:expr) => {
55 tracing::debug_span!(
56 "device",
57 device_id = $device_id,
58 operation = $operation,
59 )
60 };
61 ($device_id:expr, $operation:expr, $($field:tt)*) => {
62 tracing::debug_span!(
63 "device",
64 device_id = $device_id,
65 operation = $operation,
66 $($field)*
67 )
68 };
69}
70
71/// Log a successful operation with timing.
72///
73/// # Example
74///
75/// ```rust,ignore
76/// use mabi_core::trace_success;
77/// use std::time::Instant;
78///
79/// let start = Instant::now();
80/// // ... operation
81/// trace_success!("read", start);
82/// ```
83#[macro_export]
84macro_rules! trace_success {
85 ($operation:expr, $start:expr) => {
86 tracing::info!(
87 operation = $operation,
88 duration_us = $start.elapsed().as_micros() as u64,
89 "Operation completed"
90 );
91 };
92 ($operation:expr, $start:expr, $($field:tt)*) => {
93 tracing::info!(
94 operation = $operation,
95 duration_us = $start.elapsed().as_micros() as u64,
96 $($field)*,
97 "Operation completed"
98 );
99 };
100}
101
102/// Log a failed operation with error details.
103///
104/// # Example
105///
106/// ```rust,ignore
107/// use mabi_core::trace_error;
108///
109/// match result {
110/// Ok(_) => {},
111/// Err(e) => trace_error!("read", e),
112/// }
113/// ```
114#[macro_export]
115macro_rules! trace_error {
116 ($operation:expr, $error:expr) => {
117 tracing::error!(
118 operation = $operation,
119 error = %$error,
120 "Operation failed"
121 );
122 };
123 ($operation:expr, $error:expr, $($field:tt)*) => {
124 tracing::error!(
125 operation = $operation,
126 error = %$error,
127 $($field)*,
128 "Operation failed"
129 );
130 };
131}
132
133/// Create a span for protocol message handling.
134///
135/// # Example
136///
137/// ```rust,ignore
138/// use mabi_core::trace_message;
139///
140/// let _span = trace_message!("modbus", "request", unit_id = 1);
141/// ```
142#[macro_export]
143macro_rules! trace_message {
144 ($protocol:expr, $direction:expr) => {
145 tracing::debug_span!(
146 "message",
147 protocol = $protocol,
148 direction = $direction,
149 )
150 };
151 ($protocol:expr, $direction:expr, $($field:tt)*) => {
152 tracing::debug_span!(
153 "message",
154 protocol = $protocol,
155 direction = $direction,
156 $($field)*
157 )
158 };
159}
160
161/// Log a connection event.
162///
163/// # Example
164///
165/// ```rust,ignore
166/// use mabi_core::trace_connection;
167///
168/// trace_connection!("modbus", "connected", peer = %addr);
169/// ```
170#[macro_export]
171macro_rules! trace_connection {
172 ($protocol:expr, $event:expr) => {
173 tracing::info!(
174 protocol = $protocol,
175 event = $event,
176 "Connection event"
177 );
178 };
179 ($protocol:expr, $event:expr, $($field:tt)*) => {
180 tracing::info!(
181 protocol = $protocol,
182 event = $event,
183 $($field)*,
184 "Connection event"
185 );
186 };
187}
188
189/// Log a state change with before/after values.
190///
191/// # Example
192///
193/// ```rust,ignore
194/// use mabi_core::trace_state_change;
195///
196/// trace_state_change!("engine", "stopped", "running");
197/// ```
198#[macro_export]
199macro_rules! trace_state_change {
200 ($component:expr, $from:expr, $to:expr) => {
201 tracing::info!(
202 component = $component,
203 from_state = $from,
204 to_state = $to,
205 "State changed"
206 );
207 };
208 ($component:expr, $from:expr, $to:expr, $($field:tt)*) => {
209 tracing::info!(
210 component = $component,
211 from_state = $from,
212 to_state = $to,
213 $($field)*,
214 "State changed"
215 );
216 };
217}
218
219/// Log a metric observation.
220///
221/// # Example
222///
223/// ```rust,ignore
224/// use mabi_core::trace_metric;
225///
226/// trace_metric!("request_duration_ms", 42.5, protocol = "modbus");
227/// ```
228#[macro_export]
229macro_rules! trace_metric {
230 ($name:expr, $value:expr) => {
231 tracing::debug!(
232 metric_name = $name,
233 metric_value = $value,
234 "Metric observation"
235 );
236 };
237 ($name:expr, $value:expr, $($field:tt)*) => {
238 tracing::debug!(
239 metric_name = $name,
240 metric_value = $value,
241 $($field)*,
242 "Metric observation"
243 );
244 };
245}
246
247/// Create a span for engine tick processing.
248///
249/// # Example
250///
251/// ```rust,ignore
252/// use mabi_core::trace_tick;
253///
254/// let _span = trace_tick!(42, device_count = 100);
255/// ```
256#[macro_export]
257macro_rules! trace_tick {
258 ($tick_num:expr) => {
259 tracing::trace_span!(
260 "tick",
261 tick = $tick_num,
262 )
263 };
264 ($tick_num:expr, $($field:tt)*) => {
265 tracing::trace_span!(
266 "tick",
267 tick = $tick_num,
268 $($field)*
269 )
270 };
271}
272
273/// Log entering a critical section or important function.
274///
275/// # Example
276///
277/// ```rust,ignore
278/// use mabi_core::trace_enter;
279///
280/// fn process_batch() {
281/// trace_enter!("process_batch", batch_size = 100);
282/// // ...
283/// }
284/// ```
285#[macro_export]
286macro_rules! trace_enter {
287 ($name:expr) => {
288 tracing::debug!(function = $name, "Entering");
289 };
290 ($name:expr, $($field:tt)*) => {
291 tracing::debug!(function = $name, $($field)*, "Entering");
292 };
293}
294
295/// Log exiting a critical section or important function.
296///
297/// # Example
298///
299/// ```rust,ignore
300/// use mabi_core::trace_exit;
301///
302/// fn process_batch() {
303/// // ...
304/// trace_exit!("process_batch", processed = 100);
305/// }
306/// ```
307#[macro_export]
308macro_rules! trace_exit {
309 ($name:expr) => {
310 tracing::debug!(function = $name, "Exiting");
311 };
312 ($name:expr, $($field:tt)*) => {
313 tracing::debug!(function = $name, $($field)*, "Exiting");
314 };
315}
316
317#[cfg(test)]
318mod tests {
319 // Macro tests would require initializing the tracing subscriber
320 // which can only be done once per process.
321 // These tests verify that the macros compile correctly.
322
323 #[test]
324 fn test_macros_compile() {
325 // This test just verifies the macros are syntactically correct
326 // by checking they can be expanded without errors
327 }
328}