macro_rules! trace_impl {
($($fmt:literal)+ $(, $($types:ty : $args:expr),+)? $(, .section = $section:literal)? $(, .sink_guard = $sink_guard:expr)? $(, .sink = $sink:expr)? $(, .error_handler = $error_handler:expr)? $(, .formatter=$formatter:expr)?) => { ... };
}Expand description
The core macro for emitting a trace.
trace_impl! is the main macro that trace! and traceln! are built on.
The format string is the concatenation of all string literals before the first comma. After that come the values to be emitted, along with their types, e.g.:
trace_impl!("{} + {}" " = {}", i32: 1, i32: 2, i32: 3);A type can be made traceable by implementing the Trace trait for it.
ยงCustomization
trace_impl! supports several customization options, passed after the trace arguments:
-
.sink = <variable>: Specifies a sink to write the trace output to. The macro will mutably borrow the value for the duration of the call. It must implement theSinktrait. For example one could capture trace output in a buffer like so:let mut buf = Vec::new(); trace_impl!("Hello", .sink = buf); // `buf` is still owned and contains the trace output assert!(!buf.is_empty()); -
.sink_guard = <expr>: Specifies a sink that will be consumed by the macro. Like with.sink=the expression has to evaluate to a value that implementsSink. This value is moved into the macro and dropped at the end of the scope. This is ideal for sinks that manage a resource, like aMutexGuard, as it ensures the resource is released correctly.let sink = Mutex::new(Vec::new()); trace_impl!("Hello", .sink_guard = sink.lock().unwrap()); // The mutex is unlocked here as the guard has been dropped.By default, if neither
.sinknor.sink_guardis provided, the trace is written tostd::io::stdout().lock(). -
.section = "<section_name>": Specifies the ELF section where the format string and metadata are stored. Defaults to.emtrace. -
.formatter = <expr>: Specifies how the format string should be interpreted by the consumer of the trace data. It can be one ofPY_FORMAT,C_STYLE_FORMAT, orNO_FORMAT. -
.error_handler = <closure>: Provides a closure to handle potential errors during tracing. The closure receives aResult<(), Error<BeginError, OutError>>. If not provided, theResultis returned from the macro expansion.trace_impl!("Hello", .error_handler = |res: Result<(), Error<_, _>>| { if res.is_err() { // Handle error } });
The macro returns the output of the provided error handler.