Attaching errors to events

In Rust, errors are typically communicated through the Error trait. If you attach a property with the err well-known property to an event, it will automatically try capture it using its Error implementation:

#![allow(unused)]
fn main() {
extern crate emit;
fn write_to_file(bytes: &[u8]) -> std::io::Result<()> { Err(std::io::Error::new(std::io::ErrorKind::Other, "the file is in an invalid state")) }
if let Err(err) = write_to_file(b"Hello") {
    emit::warn!("file write failed: {err}");
}
}
Event {
    mdl: "emit_sample",
    tpl: "file write failed: {err}",
    extent: Some(
        "2024-10-02T21:14:40.566303000Z",
    ),
    props: {
        "err": Custom {
            kind: Other,
            error: "the file is in an invalid state",
        },
        "lvl": warn,
    },
}

Emitters may treat the err property specially when receiving diagnostic events, such as by displaying them more prominently.

You can also use the #[as_error] attribute on a property to capture it using its Error implementation.

Mapping error types

Attaching errors to events requires they're either &str, &(dyn std::error::Error + 'static), or impl std::error::Error. Error types like anyhow::Error don't satisfy these requirements so need to be mapped. Since property values are expressions, you can do this in any number of ways. As an example, the emit::err::as_ref function can be used to convert an anyhow::Error into an impl std::error::Error:

#![allow(unused)]
fn main() {
extern crate anyhow;
extern crate emit;
fn write_to_file(bytes: &[u8]) -> Result<(), anyhow::Error> { Err(anyhow::Error::msg("the file is in an invalid state")) }
if let Err(err) = write_to_file(b"Hello") {
    emit::warn!("file write failed: {err: emit::err::as_ref(&err)}");
}
}

Errors on spans

The #[span] macro can automatically capture errors from fallible functions. See Fallible functions for details.