1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
//! Utilities for enriching error handling with [`tracing`] diagnostic //! information. //! //! # Overview //! //! [`tracing`] is a framework for instrumenting Rust programs to collect //! scoped, structured, and async-aware diagnostics. This crate provides //! integrations between [`tracing`] instrumentation and Rust error handling. It //! enables enriching error types with diagnostic information from `tracing` //! [span] contexts, formatting those contexts when errors are displayed, and //! automatically generate `tracing` [events] when errors occur. //! //! The crate provides the following: //! //! * [`SpanTrace`], a captured trace of the current `tracing` [span] context //! //! * [`ErrorLayer`], a [subscriber layer] which enables capturing `SpanTrace`s //! //! **Note**: This crate is currently experimental. //! //! *Compiler support: requires `rustc` 1.39+* //! //! ## Feature Flags //! //! - `traced-error` - Enables the [`TracedError`] type and related Traits //! - [`InstrumentResult`] and [`InstrumentError`] extension traits, which //! provide an [`in_current_span()`] method for bundling errors with a //! [`SpanTrace`]. //! - [`ExtractSpanTrace`] extension trait, for extracting `SpanTrace`s from //! behind `dyn Error` trait objects. //! //! ## Usage //! //! `tracing-error` provides the [`SpanTrace`] type, which captures the current //! `tracing` span context when it is constructed and allows it to be displayed //! at a later time. //! //! For example: //! //! ```rust //! use std::{fmt, error::Error}; //! use tracing_error::SpanTrace; //! //! #[derive(Debug)] //! pub struct MyError { //! context: SpanTrace, //! // ... //! } //! //! impl fmt::Display for MyError { //! fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { //! // ... format other parts of the error ... //! //! self.context.fmt(f)?; //! //! // ... format other error context information, cause chain, etc ... //! # Ok(()) //! } //! } //! //! impl Error for MyError {} //! //! impl MyError { //! pub fn new() -> Self { //! Self { //! context: SpanTrace::capture(), //! // ... other error information ... //! } //! } //! } //! ``` //! //! This crate also provides the [`InstrumentResult`] and [`InstrumentError`] //! traits, which can be used to wrap errors with a [`TracedError`] which //! bundles the inner error with a [`SpanTrace`]. //! //! ```rust //! # use std::error::Error; //! use tracing_error::prelude::*; //! //! # fn fake_main() -> Result<(), Box<dyn Error>> { //! std::fs::read_to_string("myfile.txt").in_current_span()?; //! # Ok(()) //! # } //! ``` //! //! Once an error has been wrapped with with a [`TracedError`] the [`SpanTrace`] //! can be extracted one of 3 ways: either via [`TracedError`]'s //! `Display`/`Debug` implementations, or via the [`ExtractSpanTrace`] trait. //! //! For example, here is how one might print the errors but specialize the //! printing when the error is a placeholder for a wrapping [`SpanTrace`]: //! //! ```rust //! use std::error::Error; //! use tracing_error::ExtractSpanTrace as _; //! //! fn print_extracted_spantraces(error: &(dyn Error + 'static)) { //! let mut error = Some(error); //! let mut ind = 0; //! //! eprintln!("Error:"); //! //! while let Some(err) = error { //! if let Some(spantrace) = err.span_trace() { //! eprintln!("found a spantrace:\n{}", spantrace); //! } else { //! eprintln!("{:>4}: {}", ind, err); //! } //! //! error = err.source(); //! ind += 1; //! } //! } //! //! ``` //! //! Whereas here, we can still display the content of the `SpanTraces` without //! any special casing by simply printing all errors in our error chain. //! //! ```rust //! use std::error::Error; //! //! fn print_naive_spantraces(error: &(dyn Error + 'static)) { //! let mut error = Some(error); //! let mut ind = 0; //! //! eprintln!("Error:"); //! //! while let Some(err) = error { //! eprintln!("{:>4}: {}", ind, err); //! error = err.source(); //! ind += 1; //! } //! } //! ``` //! //! Applications that wish to use `tracing-error`-enabled errors should //! construct an [`ErrorLayer`] and add it to their [`Subscriber`] in order to //! enable capturing [`SpanTrace`]s. For example: //! //! ```rust //! use tracing_error::ErrorLayer; //! use tracing_subscriber::prelude::*; //! //! fn main() { //! let subscriber = tracing_subscriber::Registry::default() //! // any number of other subscriber layers may be added before or //! // after the `ErrorLayer`... //! .with(ErrorLayer::default()); //! //! // set the subscriber as the default for the application //! tracing::subscriber::set_global_default(subscriber); //! } //! ``` //! //! [`SpanTrace`]: struct.SpanTrace.html //! [`ErrorLayer`]: struct.ErrorLayer.html //! [`TracedError`]: struct.TracedError.html //! [`InstrumentResult`]: trait.InstrumentResult.html //! [`InstrumentError`]: trait.InstrumentError.html //! [`ExtractSpanTrace`]: trait.ExtractSpanTrace.html //! [`in_current_span()`]: trait.InstrumentResult.html#tymethod.in_current_span //! [span]: https://docs.rs/tracing/latest/tracing/span/index.html //! [events]: https://docs.rs/tracing/latest/tracing/struct.Event.html //! [`Subscriber`]: https://docs.rs/tracing/latest/tracing/trait.Subscriber.html //! [subscriber layer]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/layer/trait.Layer.html //! [`tracing`]: https://docs.rs/tracing //! [`std::error::Error`]: https://doc.rust-lang.org/stable/std/error/trait.Error.html #![cfg_attr(docsrs, feature(doc_cfg))] #![doc(html_root_url = "https://docs.rs/tracing-error/0.1.2")] #![warn( missing_debug_implementations, missing_docs, rust_2018_idioms, unreachable_pub, bad_style, const_err, dead_code, improper_ctypes, non_shorthand_field_patterns, no_mangle_generic_items, overflowing_literals, path_statements, patterns_in_fns_without_body, private_in_public, unconditional_recursion, unused, unused_allocation, unused_comparisons, unused_parens, while_true )] mod backtrace; #[cfg(feature = "traced-error")] mod error; mod layer; pub use self::backtrace::{SpanTrace, SpanTraceStatus}; #[cfg(feature = "traced-error")] pub use self::error::{ExtractSpanTrace, InstrumentError, InstrumentResult, TracedError}; pub use self::layer::ErrorLayer; #[cfg(feature = "traced-error")] #[cfg_attr(docsrs, doc(cfg(feature = "traced-error")))] pub mod prelude { //! The `tracing-error` prelude. //! //! This brings into scope the `InstrumentError, `InstrumentResult`, and `ExtractSpanTrace` //! extension traits. These traits allow attaching `SpanTrace`s to errors and //! subsequently retrieving them from `dyn Error` trait objects. pub use crate::{ExtractSpanTrace as _, InstrumentError as _, InstrumentResult as _}; }