Skip to main content

trace_impl

Macro trace_impl 

Source
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 the Sink trait. 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 implements Sink. 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 a MutexGuard, 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 .sink nor .sink_guard is provided, the trace is written to std::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 of PY_FORMAT, C_STYLE_FORMAT, or NO_FORMAT.

  • .error_handler = <closure>: Provides a closure to handle potential errors during tracing. The closure receives a Result<(), Error<BeginError, OutError>>. If not provided, the Result is 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.