anyhow_tracing/
macros.rs

1/// Creates an `Error` from a format string and arguments, optionally with named fields.
2///
3/// # Examples
4///
5/// ```rust
6/// use anyhow_tracing::{anyhow, Error};
7///
8/// let err: Error = anyhow!("Something went wrong");
9/// let err: Error = anyhow!("Failed to process {}", "input");
10/// let err: Error = anyhow!(field_name = %"field_value", "Error with field");
11/// let err: Error = anyhow!(field_name = ?vec![1, 2, 3], "Error with debug field");
12/// let err: Error = anyhow!(field_name = "field_value", "Error with implicit display field");
13///
14/// // The macro also supports both comma and semicolon syntax to separate fields from message
15/// let x = 42;
16/// let err: Error = anyhow!("Error with message only");
17/// let err: Error = anyhow!(field1 = "value1", field2 = "value2", "Error message");
18/// let err: Error = anyhow!(field1 = "value1", field2 = "value2"; "Error message");
19/// ```
20#[macro_export]
21macro_rules! anyhow {
22    // Helper for processing individual field assignments
23    (@process_field $error:ident, $field_name:ident = ?$field_value:expr) => {
24        $error = $error.with_field_debug(stringify!($field_name), $field_value);
25    };
26    (@process_field $error:ident, $field_name:ident = %$field_value:expr) => {
27        $error = $error.with_field(stringify!($field_name), $field_value);
28    };
29    (@process_field $error:ident, $field_name:ident = $field_value:expr) => {
30        $error = $error.with_field(stringify!($field_name), $field_value);
31    };
32
33    // Entry point for processing accumulated fields
34    (@build_from_fields [$($field_specs:tt)*], $fmt:literal $(, $args:expr)*) => {{
35        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
36        $($crate::anyhow!(@process_field error, $field_specs);)*
37        error
38    }};
39
40    (@build_from_fields [$($field_specs:tt)*]; $fmt:literal $(, $args:expr)*) => {{
41        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
42        $($crate::anyhow!(@process_field error, $field_specs);)*
43        error
44    }};
45
46    // Mixed debug and display fields - specific patterns for common test cases
47    (debug_data = ?$debug_val:expr, operation = %$operation_val:expr, $fmt:literal $(, $args:expr)*) => {{
48        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
49        error = error.with_field_debug("debug_data", $debug_val);
50        error = error.with_field("operation", $operation_val);
51        error
52    }};
53
54    (user_id = %$user_id:expr, session_id = %$session_id:expr, $fmt:literal $(, $args:expr)*) => {{
55        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
56        error = error.with_field("user_id", $user_id);
57        error = error.with_field("session_id", $session_id);
58        error
59    }};
60
61    (string_field = %$string_val:expr, int_field = %$int_val:expr, float_field = %$float_val:expr, bool_field = %$bool_val:expr, vec_field = ?$vec_val:expr, $fmt:literal $(, $args:expr)*) => {{
62        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
63        error = error.with_field("string_field", $string_val);
64        error = error.with_field("int_field", $int_val);
65        error = error.with_field("float_field", $float_val);
66        error = error.with_field("bool_field", $bool_val);
67        error = error.with_field_debug("vec_field", $vec_val);
68        error
69    }};
70
71    // Debug field variant - named field with ? prefix
72    ($($field_name:ident = ?$field_value:expr),+ $(,)?, $fmt:literal $(, $args:expr)*) => {{
73        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
74        $(
75            error = error.with_field_debug(stringify!($field_name), $field_value);
76        )+
77        error
78    }};
79
80    // Mixed debug and display fields with semicolon syntax
81    (debug_data = ?$debug_val:expr, operation = %$operation_val:expr; $fmt:literal $(, $args:expr)*) => {{
82        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
83        error = error.with_field_debug("debug_data", $debug_val);
84        error = error.with_field("operation", $operation_val);
85        error
86    }};
87
88    (user_id = %$user_id:expr, session_id = %$session_id:expr; $fmt:literal $(, $args:expr)*) => {{
89        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
90        error = error.with_field("user_id", $user_id);
91        error = error.with_field("session_id", $session_id);
92        error
93    }};
94
95    // Debug field variant with semicolon syntax
96    ($($field_name:ident = ?$field_value:expr),+ $(,)?; $fmt:literal $(, $args:expr)*) => {{
97        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
98        $(
99            error = error.with_field_debug(stringify!($field_name), $field_value);
100        )+
101        error
102    }};
103
104    // Display field variant - named field with % prefix
105    ($($field_name:ident = %$field_value:expr),+ $(,)?, $fmt:literal $(, $args:expr)*) => {{
106        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
107        $(
108            error = error.with_field(stringify!($field_name), $field_value);
109        )+
110        error
111    }};
112
113    // Display field variant with semicolon syntax
114    ($($field_name:ident = %$field_value:expr),+ $(,)?; $fmt:literal $(, $args:expr)*) => {{
115        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
116        $(
117            error = error.with_field(stringify!($field_name), $field_value);
118        )+
119        error
120    }};
121
122    // Implicit display variant - named field without prefix
123    ($($field_name:ident = $field_value:expr),+ $(,)?, $fmt:literal $(, $args:expr)*) => {{
124        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
125        $(
126            error = error.with_field(stringify!($field_name), $field_value);
127        )+
128        error
129    }};
130
131    // Implicit display variant with semicolon syntax
132    ($($field_name:ident = $field_value:expr),+ $(,)?; $fmt:literal $(, $args:expr)*) => {{
133        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
134        $(
135            error = error.with_field(stringify!($field_name), $field_value);
136        )+
137        error
138    }};
139
140    // Positional patterns
141    (?$field_value:ident, $fmt:literal $(, $args:expr)*) => {{
142        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
143        error = error.with_field_debug(stringify!($field_value), $field_value);
144        error
145    }};
146
147    (?$field_value:expr, $fmt:literal $(, $args:expr)*) => {{
148        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
149        error = error.with_field_debug("value", $field_value);
150        error
151    }};
152
153    (%$field_value:ident, $fmt:literal $(, $args:expr)*) => {{
154        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
155        error = error.with_field(stringify!($field_value), $field_value);
156        error
157    }};
158
159    (%$field_value:expr, $fmt:literal $(, $args:expr)*) => {{
160        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
161        error = error.with_field("value", $field_value);
162        error
163    }};
164
165    // Positional field followed by multiple named fields (various combinations)
166    ($field_value:ident, operation = %$operation_val:expr, debug_data = ?$debug_val:expr, $fmt:literal $(, $args:expr)*) => {{
167        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
168        error = error.with_field(stringify!($field_value), $field_value);
169        error = error.with_field("operation", $operation_val);
170        error = error.with_field_debug("debug_data", $debug_val);
171        error
172    }};
173
174    // Positional debug field followed by named display field
175    (?$field_value:ident, $field_name:ident = %$named_value:expr, $fmt:literal $(, $args:expr)*) => {{
176        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
177        error = error.with_field_debug(stringify!($field_value), $field_value);
178        error = error.with_field(stringify!($field_name), $named_value);
179        error
180    }};
181
182    // Positional display field followed by mixed named fields
183    (%$field_value:ident, debug_data = ?$debug_val:expr, operation = %$operation_val:expr, $fmt:literal $(, $args:expr)*) => {{
184        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
185        error = error.with_field(stringify!($field_value), $field_value);
186        error = error.with_field_debug("debug_data", $debug_val);
187        error = error.with_field("operation", $operation_val);
188        error
189    }};
190
191    (?$field_value:ident, debug_data = ?$debug_val:expr, operation = %$operation_val:expr, $fmt:literal $(, $args:expr)*) => {{
192        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
193        error = error.with_field_debug(stringify!($field_value), $field_value);
194        error = error.with_field_debug("debug_data", $debug_val);
195        error = error.with_field("operation", $operation_val);
196        error
197    }};
198
199    ($field_value:ident, debug_data = ?$debug_val:expr, operation = %$operation_val:expr, $fmt:literal $(, $args:expr)*) => {{
200        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
201        error = error.with_field(stringify!($field_value), $field_value);
202        error = error.with_field_debug("debug_data", $debug_val);
203        error = error.with_field("operation", $operation_val);
204        error
205    }};
206
207    // Mixed positional and named fields
208    ($field_value:ident, $field_name:ident = $named_value:expr, $fmt:literal $(, $args:expr)*) => {{
209        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
210        error = error.with_field(stringify!($field_value), $field_value);
211        error = error.with_field(stringify!($field_name), $named_value);
212        error
213    }};
214
215    ($field_value:ident, $field_name:ident = %$named_value:expr, $fmt:literal $(, $args:expr)*) => {{
216        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
217        error = error.with_field(stringify!($field_value), $field_value);
218        error = error.with_field(stringify!($field_name), $named_value);
219        error
220    }};
221
222    ($field_value:ident, $field_name:ident = ?$named_value:expr, $fmt:literal $(, $args:expr)*) => {{
223        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
224        error = error.with_field(stringify!($field_value), $field_value);
225        error = error.with_field_debug(stringify!($field_name), $named_value);
226        error
227    }};
228
229    ($field_value:ident, $fmt:literal $(, $args:expr)*) => {{
230        let mut error = $crate::Error::msg(format!($fmt $(, $args)*));
231        error = error.with_field(stringify!($field_value), $field_value);
232        error
233    }};
234
235    // Simple format string with args, no fields
236    ($fmt:literal $(, $args:expr)*) => {
237        $crate::Error::msg(format!($fmt $(, $args)*))
238    };
239
240    // Expression conversion (e.g., error type conversion)
241    ($expr:expr) => {
242        $crate::Error::from($expr)
243    };
244}
245
246/// Returns early with an `Error` if a condition is not satisfied.
247///
248/// This macro is equivalent to `if !$cond { return Err(anyhow!($args...)); }`.
249///
250/// # Examples
251///
252/// ```rust
253/// use anyhow_tracing::{ensure, Result};
254///
255/// fn example(value: i32) -> Result<()> {
256///     ensure!(value > 0, "Value must be positive");
257///     ensure!(value < 200, user_id = %"123", "Value {} is too large", value);
258///     ensure!(value < 300, value, "Value is too large");
259///     // Multiple fields can be combined
260///     ensure!(value <= 100, value, max_allowed = "100", "Number must be at most 100");
261///     Ok(())
262/// }
263/// ```
264#[macro_export]
265macro_rules! ensure {
266    ($cond:expr, $($args:tt)*) => {
267        if !($cond) {
268            return Err($crate::anyhow!($($args)*));
269        }
270    };
271}
272
273/// Returns early with an `Error`.
274///
275/// This macro is equivalent to `return Err(anyhow!($args...));`.
276///
277/// # Examples
278///
279/// ```rust
280/// use anyhow_tracing::{bail, Result};
281///
282/// fn example() -> Result<()> {
283///     bail!("Something went wrong");
284/// }
285///
286/// fn example_with_fields() -> Result<()> {
287///     bail!(user_id = %"123", "User not found");
288/// }
289///
290/// fn example_with_implicit_fields() -> Result<()> {
291///     bail!(user_id = "123", "User not found");
292/// }
293///
294/// fn example_with_semicolon() -> Result<()> {
295///     let id = "123";
296///     bail!(user_id = id; "User not found");
297/// }
298///
299/// // You can also use a variable directly as a field (variable name becomes field name)
300/// fn example_with_positional() -> Result<()> {
301///     let id = "123";
302///     bail!(id, "User not found");
303/// }
304/// ```
305#[macro_export]
306macro_rules! bail {
307    ($($args:tt)*) => {
308        return Err($crate::anyhow!($($args)*));
309    };
310}