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