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 | )] |
216 | mod backtrace; |
217 | #[cfg (feature = "traced-error" )] |
218 | mod error; |
219 | mod layer; |
220 | |
221 | pub use self::backtrace::{SpanTrace, SpanTraceStatus}; |
222 | #[cfg (feature = "traced-error" )] |
223 | pub use self::error::{ExtractSpanTrace, InstrumentError, InstrumentResult, TracedError}; |
224 | pub use self::layer::ErrorLayer; |
225 | |
226 | #[cfg (feature = "traced-error" )] |
227 | #[cfg_attr (docsrs, doc(cfg(feature = "traced-error" )))] |
228 | pub 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 | |