error_field

Function error_field 

Source
pub fn error_field<E, TMarker>(error: &E) -> Box<dyn Value + '_>
where E: AsTracingValue<TMarker>,
Expand description

Emit an error as a tracing event with its full source chain intact.

This utility provides a streamlined way to emit errors as tracing event fields and their full source-chain without verbose conversion to &dyn std::error::Error trait objects.

§Why this exists

To emit errors as fields in tracing events in the way tracing intended (that is, via tracing::Value for dyn std::error::Error), one can either use error = &error as &dyn std::error::Error for typed errors, or alternatively error = AsRef::<std::error::Error::as_ref(&error) for dynamic errors such eyre::Report. Both are verbose and not nice to use. Many users instead just reach for the sigils % or ?. But % uses the Display formatting for a type, skipping its source chain. And ? uses Debug, which can leak implementation details, is hard to read, and can break formatting (in the case of eyre) – and its inconsistent.

The error_field utility allows treating both errors the same way, while making use of the tracing machinery.

§Notes on the implementation

[tracing::Value] is implemented for E: dyn std::error::Error, but actually using it requires a verbose error as &dyn std::error::Error for types that actually implement that trait. Or worse, AsRef::<dyn std::error::Error>::as_ref(&eyre_report) for eyre::Report, which by itself does not implement the trait.

Right now the implementation requires an additional heap allocation of the type-erased error object. Because usually errors are not handled in the hot path of an application this should be an acceptable performance hit.

§Examples

use eyre::WrapErr;
use tempo_telemetry_util::error_field;
let read_error: Result<(), std::io::Error> = Err(std::io::ErrorKind::NotFound.into());
if let Err(error) = Err::<(), _>(std::io::Error::from(std::io::ErrorKind::NotFound))
    .wrap_err("failed opening config")
    .wrap_err("failed to start server")
{
    tracing::error!(
        error = error_field(&error),
    );
}

This will print (using the standard tracing_subscriber::fmt::init() formatting subscriber):

2025-08-08T14:38:17.541852Z ERROR tempo_telemetry_util: error=failed starting server error.sources=[failed opening config, entity not found]