• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.49+][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 //! [`in_current_span()`]: InstrumentResult#tymethod.in_current_span
161 //! [span]: mod@tracing::span
162 //! [events]: tracing::Event
163 //! [`Subscriber`]: tracing::Subscriber
164 //! [subscriber layer]: tracing_subscriber::layer::Layer
165 //! [`tracing`]: tracing
166 //!
167 //! ## Supported Rust Versions
168 //!
169 //! Tracing is built against the latest stable release. The minimum supported
170 //! version is 1.49. The current Tracing version is not guaranteed to build on
171 //! Rust versions earlier than the minimum supported version.
172 //!
173 //! Tracing follows the same compiler support policies as the rest of the Tokio
174 //! project. The current stable Rust compiler and the three most recent minor
175 //! versions before it will always be supported. For example, if the current
176 //! stable compiler version is 1.45, the minimum supported version will not be
177 //! increased past 1.42, three minor versions prior. Increasing the minimum
178 //! supported compiler version is not considered a semver breaking change as
179 //! long as doing so complies with this policy.
180 //!
181 #![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))]
182 #![doc(html_root_url = "https://docs.rs/tracing-error/0.2.0")]
183 #![doc(
184     html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
185     issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
186 )]
187 #![warn(
188     missing_debug_implementations,
189     missing_docs,
190     rust_2018_idioms,
191     unreachable_pub,
192     bad_style,
193     const_err,
194     dead_code,
195     improper_ctypes,
196     non_shorthand_field_patterns,
197     no_mangle_generic_items,
198     overflowing_literals,
199     path_statements,
200     patterns_in_fns_without_body,
201     private_in_public,
202     unconditional_recursion,
203     unused,
204     unused_allocation,
205     unused_comparisons,
206     unused_parens,
207     while_true
208 )]
209 mod backtrace;
210 #[cfg(feature = "traced-error")]
211 mod error;
212 mod layer;
213 
214 pub use self::backtrace::{SpanTrace, SpanTraceStatus};
215 #[cfg(feature = "traced-error")]
216 pub use self::error::{ExtractSpanTrace, InstrumentError, InstrumentResult, TracedError};
217 pub use self::layer::ErrorLayer;
218 
219 #[cfg(feature = "traced-error")]
220 #[cfg_attr(docsrs, doc(cfg(feature = "traced-error")))]
221 pub mod prelude {
222     //! The `tracing-error` prelude.
223     //!
224     //! This brings into scope the `InstrumentError`, `InstrumentResult`, and `ExtractSpanTrace`
225     //! extension traits. These traits allow attaching `SpanTrace`s to errors and
226     //! subsequently retrieving them from `dyn Error` trait objects.
227 
228     // apparently `as _` reexpoorts now generate `unreachable_pub` linting? which
229     // seems wrong to me...
230     #![allow(unreachable_pub)]
231     pub use crate::{ExtractSpanTrace as _, InstrumentError as _, InstrumentResult as _};
232 }
233