| 1 | //! An error report handler for panics and the [`eyre`] crate for colorful, consistent, and well |
| 2 | //! formatted error reports for all kinds of errors. |
| 3 | //! |
| 4 | //! ## TLDR |
| 5 | //! |
| 6 | //! `color_eyre` helps you build error reports that look like this: |
| 7 | //! |
| 8 | //! <pre><span style="color: #06989A"><b>color-eyre</b></span> on <span style="color: #75507B"><b> hooked</b></span> <span style="color: #CC0000"><b>[$!] </b></span>is <span style="color: #FF8700"><b>📦 v0.5.0</b></span> via <span style="color: #CC0000"><b>🦀 v1.44.0</b></span> |
| 9 | //! <span style="color: #4E9A06"><b>❯</b></span> cargo run --example custom_section |
| 10 | //! <span style="color: #4E9A06"><b> Finished</b></span> dev [unoptimized + debuginfo] target(s) in 0.04s |
| 11 | //! <span style="color: #4E9A06"><b> Running</b></span> `target/debug/examples/custom_section` |
| 12 | //! Error: |
| 13 | //! 0: <span style="color: #F15D22">Unable to read config</span> |
| 14 | //! 1: <span style="color: #F15D22">cmd exited with non-zero status code</span> |
| 15 | //! |
| 16 | //! Stderr: |
| 17 | //! cat: fake_file: No such file or directory |
| 18 | //! |
| 19 | //! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SPANTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ |
| 20 | //! |
| 21 | //! 0: <span style="color: #F15D22">custom_section::output2</span> with <span style="color: #34E2E2">self="cat" "fake_file"</span> |
| 22 | //! at <span style="color: #75507B">examples/custom_section.rs</span>:<span style="color: #75507B">14</span> |
| 23 | //! 1: <span style="color: #F15D22">custom_section::read_file</span> with <span style="color: #34E2E2">path="fake_file"</span> |
| 24 | //! at <span style="color: #75507B">examples/custom_section.rs</span>:<span style="color: #75507B">58</span> |
| 25 | //! 2: <span style="color: #F15D22">custom_section::read_config</span> |
| 26 | //! at <span style="color: #75507B">examples/custom_section.rs</span>:<span style="color: #75507B">63</span> |
| 27 | //! |
| 28 | //! <span style="color: #34E2E2">Suggestion</span>: try using a file that exists next time</pre> |
| 29 | //! |
| 30 | //! ## Setup |
| 31 | //! |
| 32 | //! Add the following to your toml file: |
| 33 | //! |
| 34 | //! ```toml |
| 35 | //! [dependencies] |
| 36 | //! color-eyre = "0.6" |
| 37 | //! ``` |
| 38 | //! |
| 39 | //! And install the panic and error report handlers: |
| 40 | //! |
| 41 | //! ```rust |
| 42 | //! use color_eyre::eyre::Result; |
| 43 | //! |
| 44 | //! fn main() -> Result<()> { |
| 45 | //! color_eyre::install()?; |
| 46 | //! |
| 47 | //! // ... |
| 48 | //! # Ok(()) |
| 49 | //! } |
| 50 | //! ``` |
| 51 | //! |
| 52 | //! ### Disabling tracing support |
| 53 | //! |
| 54 | //! If you don't plan on using `tracing_error` and `SpanTrace` you can disable the |
| 55 | //! tracing integration to cut down on unused dependencies: |
| 56 | //! |
| 57 | //! ```toml |
| 58 | //! [dependencies] |
| 59 | //! color-eyre = { version = "0.6", default-features = false } |
| 60 | //! ``` |
| 61 | //! |
| 62 | //! ### Disabling SpanTrace capture by default |
| 63 | //! |
| 64 | //! color-eyre defaults to capturing span traces. This is because `SpanTrace` |
| 65 | //! capture is significantly cheaper than `Backtrace` capture. However, like |
| 66 | //! backtraces, span traces are most useful for debugging applications, and it's |
| 67 | //! not uncommon to want to disable span trace capture by default to keep noise out |
| 68 | //! developer. |
| 69 | //! |
| 70 | //! To disable span trace capture you must explicitly set one of the env variables |
| 71 | //! that regulate `SpanTrace` capture to `"0"`: |
| 72 | //! |
| 73 | //! ```rust |
| 74 | //! if std::env::var("RUST_SPANTRACE" ).is_err() { |
| 75 | //! std::env::set_var("RUST_SPANTRACE" , "0" ); |
| 76 | //! } |
| 77 | //! ``` |
| 78 | //! |
| 79 | //! ### Improving perf on debug builds |
| 80 | //! |
| 81 | //! In debug mode `color-eyre` behaves noticably worse than `eyre`. This is caused |
| 82 | //! by the fact that `eyre` uses `std::backtrace::Backtrace` instead of |
| 83 | //! `backtrace::Backtrace`. The std version of backtrace is precompiled with |
| 84 | //! optimizations, this means that whether or not you're in debug mode doesn't |
| 85 | //! matter much for how expensive backtrace capture is, it will always be in the |
| 86 | //! 10s of milliseconds to capture. A debug version of `backtrace::Backtrace` |
| 87 | //! however isn't so lucky, and can take an order of magnitude more time to capture |
| 88 | //! a backtrace compared to its std counterpart. |
| 89 | //! |
| 90 | //! Cargo [profile |
| 91 | //! overrides](https://doc.rust-lang.org/cargo/reference/profiles.html#overrides) |
| 92 | //! can be used to mitigate this problem. By configuring your project to always |
| 93 | //! build `backtrace` with optimizations you should get the same performance from |
| 94 | //! `color-eyre` that you're used to with `eyre`. To do so add the following to |
| 95 | //! your Cargo.toml: |
| 96 | //! |
| 97 | //! ```toml |
| 98 | //! [profile.dev.package.backtrace] |
| 99 | //! opt-level = 3 |
| 100 | //! ``` |
| 101 | //! |
| 102 | //! ## Features |
| 103 | //! |
| 104 | //! ### Multiple report format verbosity levels |
| 105 | //! |
| 106 | //! `color-eyre` provides 3 different report formats for how it formats the captured `SpanTrace` |
| 107 | //! and `Backtrace`, minimal, short, and full. Take the below snippets of the output produced by [`examples/usage.rs`]: |
| 108 | //! |
| 109 | //! --- |
| 110 | //! |
| 111 | //! Running `cargo run --example usage` without `RUST_LIB_BACKTRACE` set will produce a minimal |
| 112 | //! report like this: |
| 113 | //! |
| 114 | //! <pre><span style="color: #06989A"><b>color-eyre</b></span> on <span style="color: #75507B"><b> hooked</b></span> <span style="color: #CC0000"><b>[$!] </b></span>is <span style="color: #FF8700"><b>📦 v0.5.0</b></span> via <span style="color: #CC0000"><b>🦀 v1.44.0</b></span> took <span style="color: #C4A000"><b>2s</b></span> |
| 115 | //! <span style="color: #CC0000"><b>❯</b></span> cargo run --example usage |
| 116 | //! <span style="color: #4E9A06"><b> Finished</b></span> dev [unoptimized + debuginfo] target(s) in 0.04s |
| 117 | //! <span style="color: #4E9A06"><b> Running</b></span> `target/debug/examples/usage` |
| 118 | //! <span style="color: #A1A1A1">Jul 05 19:15:58.026 </span><span style="color: #4E9A06"> INFO</span> <b>read_config</b>:<b>read_file{</b>path="fake_file"<b>}</b>: Reading file |
| 119 | //! Error: |
| 120 | //! 0: <span style="color: #F15D22">Unable to read config</span> |
| 121 | //! 1: <span style="color: #F15D22">No such file or directory (os error 2)</span> |
| 122 | //! |
| 123 | //! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SPANTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ |
| 124 | //! |
| 125 | //! 0: <span style="color: #F15D22">usage::read_file</span> with <span style="color: #34E2E2">path="fake_file"</span> |
| 126 | //! at <span style="color: #75507B">examples/usage.rs</span>:<span style="color: #75507B">32</span> |
| 127 | //! 1: <span style="color: #F15D22">usage::read_config</span> |
| 128 | //! at <span style="color: #75507B">examples/usage.rs</span>:<span style="color: #75507B">38</span> |
| 129 | //! |
| 130 | //! <span style="color: #34E2E2">Suggestion</span>: try using a file that exists next time</pre> |
| 131 | //! |
| 132 | //! <br> |
| 133 | //! |
| 134 | //! Running `RUST_LIB_BACKTRACE=1 cargo run --example usage` tells `color-eyre` to use the short |
| 135 | //! format, which additionally capture a [`backtrace::Backtrace`]: |
| 136 | //! |
| 137 | //! <pre><span style="color: #06989A"><b>color-eyre</b></span> on <span style="color: #75507B"><b> hooked</b></span> <span style="color: #CC0000"><b>[$!] </b></span>is <span style="color: #FF8700"><b>📦 v0.5.0</b></span> via <span style="color: #CC0000"><b>🦀 v1.44.0</b></span> |
| 138 | //! <span style="color: #CC0000"><b>❯</b></span> RUST_LIB_BACKTRACE=1 cargo run --example usage |
| 139 | //! <span style="color: #4E9A06"><b> Finished</b></span> dev [unoptimized + debuginfo] target(s) in 0.04s |
| 140 | //! <span style="color: #4E9A06"><b> Running</b></span> `target/debug/examples/usage` |
| 141 | //! <span style="color: #A1A1A1">Jul 05 19:16:02.853 </span><span style="color: #4E9A06"> INFO</span> <b>read_config</b>:<b>read_file{</b>path="fake_file"<b>}</b>: Reading file |
| 142 | //! Error: |
| 143 | //! 0: <span style="color: #F15D22">Unable to read config</span> |
| 144 | //! 1: <span style="color: #F15D22">No such file or directory (os error 2)</span> |
| 145 | //! |
| 146 | //! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SPANTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ |
| 147 | //! |
| 148 | //! 0: <span style="color: #F15D22">usage::read_file</span> with <span style="color: #34E2E2">path="fake_file"</span> |
| 149 | //! at <span style="color: #75507B">examples/usage.rs</span>:<span style="color: #75507B">32</span> |
| 150 | //! 1: <span style="color: #F15D22">usage::read_config</span> |
| 151 | //! at <span style="color: #75507B">examples/usage.rs</span>:<span style="color: #75507B">38</span> |
| 152 | //! |
| 153 | //! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BACKTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ |
| 154 | //! <span style="color: #34E2E2"> ⋮ 5 frames hidden ⋮ </span> |
| 155 | //! 6: <span style="color: #F15D22">usage::read_file</span><span style="color: #88807C">::haee210cb22460af3</span> |
| 156 | //! at <span style="color: #75507B">/home/jlusby/git/yaahc/color-eyre/examples/usage.rs</span>:<span style="color: #75507B">35</span> |
| 157 | //! 7: <span style="color: #F15D22">usage::read_config</span><span style="color: #88807C">::ha649ef4ec333524d</span> |
| 158 | //! at <span style="color: #75507B">/home/jlusby/git/yaahc/color-eyre/examples/usage.rs</span>:<span style="color: #75507B">40</span> |
| 159 | //! 8: <span style="color: #F15D22">usage::main</span><span style="color: #88807C">::hbe443b50eac38236</span> |
| 160 | //! at <span style="color: #75507B">/home/jlusby/git/yaahc/color-eyre/examples/usage.rs</span>:<span style="color: #75507B">11</span> |
| 161 | //! <span style="color: #34E2E2"> ⋮ 10 frames hidden ⋮ </span> |
| 162 | //! |
| 163 | //! <span style="color: #34E2E2">Suggestion</span>: try using a file that exists next time</pre> |
| 164 | //! |
| 165 | //! <br> |
| 166 | //! |
| 167 | //! Finally, running `RUST_LIB_BACKTRACE=full cargo run --example usage` tells `color-eyre` to use |
| 168 | //! the full format, which in addition to the above will attempt to include source lines where the |
| 169 | //! error originated from, assuming it can find them on the disk. |
| 170 | //! |
| 171 | //! <pre><span style="color: #06989A"><b>color-eyre</b></span> on <span style="color: #75507B"><b> hooked</b></span> <span style="color: #CC0000"><b>[$!] </b></span>is <span style="color: #FF8700"><b>📦 v0.5.0</b></span> via <span style="color: #CC0000"><b>🦀 v1.44.0</b></span> |
| 172 | //! <span style="color: #CC0000"><b>❯</b></span> RUST_LIB_BACKTRACE=full cargo run --example usage |
| 173 | //! <span style="color: #4E9A06"><b> Finished</b></span> dev [unoptimized + debuginfo] target(s) in 0.05s |
| 174 | //! <span style="color: #4E9A06"><b> Running</b></span> `target/debug/examples/usage` |
| 175 | //! <span style="color: #A1A1A1">Jul 05 19:16:06.335 </span><span style="color: #4E9A06"> INFO</span> <b>read_config</b>:<b>read_file{</b>path="fake_file"<b>}</b>: Reading file |
| 176 | //! Error: |
| 177 | //! 0: <span style="color: #F15D22">Unable to read config</span> |
| 178 | //! 1: <span style="color: #F15D22">No such file or directory (os error 2)</span> |
| 179 | //! |
| 180 | //! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SPANTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ |
| 181 | //! |
| 182 | //! 0: <span style="color: #F15D22">usage::read_file</span> with <span style="color: #34E2E2">path="fake_file"</span> |
| 183 | //! at <span style="color: #75507B">examples/usage.rs</span>:<span style="color: #75507B">32</span> |
| 184 | //! 30 │ } |
| 185 | //! 31 │ |
| 186 | //! <b> 32 > #[instrument]</b> |
| 187 | //! 33 │ fn read_file(path: &str) -> Result<(), Report> { |
| 188 | //! 34 │ info!("Reading file"); |
| 189 | //! 1: <span style="color: #F15D22">usage::read_config</span> |
| 190 | //! at <span style="color: #75507B">examples/usage.rs</span>:<span style="color: #75507B">38</span> |
| 191 | //! 36 │ } |
| 192 | //! 37 │ |
| 193 | //! <b> 38 > #[instrument]</b> |
| 194 | //! 39 │ fn read_config() -> Result<(), Report> { |
| 195 | //! 40 │ read_file("fake_file") |
| 196 | //! |
| 197 | //! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BACKTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ |
| 198 | //! <span style="color: #34E2E2"> ⋮ 5 frames hidden ⋮ </span> |
| 199 | //! 6: <span style="color: #F15D22">usage::read_file</span><span style="color: #88807C">::haee210cb22460af3</span> |
| 200 | //! at <span style="color: #75507B">/home/jlusby/git/yaahc/color-eyre/examples/usage.rs</span>:<span style="color: #75507B">35</span> |
| 201 | //! 33 │ fn read_file(path: &str) -> Result<(), Report> { |
| 202 | //! 34 │ info!("Reading file"); |
| 203 | //! <span style="color: #D3D7CF"><b> 35 > Ok(std::fs::read_to_string(path).map(drop)?)</b></span> |
| 204 | //! 36 │ } |
| 205 | //! 37 │ |
| 206 | //! 7: <span style="color: #F15D22">usage::read_config</span><span style="color: #88807C">::ha649ef4ec333524d</span> |
| 207 | //! at <span style="color: #75507B">/home/jlusby/git/yaahc/color-eyre/examples/usage.rs</span>:<span style="color: #75507B">40</span> |
| 208 | //! 38 │ #[instrument] |
| 209 | //! 39 │ fn read_config() -> Result<(), Report> { |
| 210 | //! <span style="color: #D3D7CF"><b> 40 > read_file("fake_file")</b></span> |
| 211 | //! 41 │ .wrap_err("Unable to read config") |
| 212 | //! 42 │ .suggestion("try using a file that exists next time") |
| 213 | //! 8: <span style="color: #F15D22">usage::main</span><span style="color: #88807C">::hbe443b50eac38236</span> |
| 214 | //! at <span style="color: #75507B">/home/jlusby/git/yaahc/color-eyre/examples/usage.rs</span>:<span style="color: #75507B">11</span> |
| 215 | //! 9 │ color_eyre::install()?; |
| 216 | //! 10 │ |
| 217 | //! <span style="color: #D3D7CF"><b> 11 > Ok(read_config()?)</b></span> |
| 218 | //! 12 │ } |
| 219 | //! 13 │ |
| 220 | //! <span style="color: #34E2E2"> ⋮ 10 frames hidden ⋮ </span> |
| 221 | //! |
| 222 | //! <span style="color: #34E2E2">Suggestion</span>: try using a file that exists next time</pre> |
| 223 | //! |
| 224 | //! ### Custom `Section`s for error reports via [`Section`] trait |
| 225 | //! |
| 226 | //! The `section` module provides helpers for adding extra sections to error |
| 227 | //! reports. Sections are disinct from error messages and are displayed |
| 228 | //! independently from the chain of errors. Take this example of adding sections |
| 229 | //! to contain `stderr` and `stdout` from a failed command, taken from |
| 230 | //! [`examples/custom_section.rs`]: |
| 231 | //! |
| 232 | //! ```rust |
| 233 | //! use color_eyre::{eyre::eyre, SectionExt, Section, eyre::Report}; |
| 234 | //! use std::process::Command; |
| 235 | //! use tracing::instrument; |
| 236 | //! |
| 237 | //! trait Output { |
| 238 | //! fn output2(&mut self) -> Result<String, Report>; |
| 239 | //! } |
| 240 | //! |
| 241 | //! impl Output for Command { |
| 242 | //! #[instrument] |
| 243 | //! fn output2(&mut self) -> Result<String, Report> { |
| 244 | //! let output = self.output()?; |
| 245 | //! |
| 246 | //! let stdout = String::from_utf8_lossy(&output.stdout); |
| 247 | //! |
| 248 | //! if !output.status.success() { |
| 249 | //! let stderr = String::from_utf8_lossy(&output.stderr); |
| 250 | //! Err(eyre!("cmd exited with non-zero status code" )) |
| 251 | //! .with_section(move || stdout.trim().to_string().header("Stdout:" )) |
| 252 | //! .with_section(move || stderr.trim().to_string().header("Stderr:" )) |
| 253 | //! } else { |
| 254 | //! Ok(stdout.into()) |
| 255 | //! } |
| 256 | //! } |
| 257 | //! } |
| 258 | //! ``` |
| 259 | //! |
| 260 | //! --- |
| 261 | //! |
| 262 | //! Here we have an function that, if the command exits unsuccessfully, creates a |
| 263 | //! report indicating the failure and attaches two sections, one for `stdout` and |
| 264 | //! one for `stderr`. |
| 265 | //! |
| 266 | //! Running `cargo run --example custom_section` shows us how these sections are |
| 267 | //! included in the output: |
| 268 | //! |
| 269 | //! <pre><span style="color: #06989A"><b>color-eyre</b></span> on <span style="color: #75507B"><b> hooked</b></span> <span style="color: #CC0000"><b>[$!] </b></span>is <span style="color: #FF8700"><b>📦 v0.5.0</b></span> via <span style="color: #CC0000"><b>🦀 v1.44.0</b></span> took <span style="color: #C4A000"><b>2s</b></span> |
| 270 | //! <span style="color: #CC0000"><b>❯</b></span> cargo run --example custom_section |
| 271 | //! <span style="color: #4E9A06"><b> Finished</b></span> dev [unoptimized + debuginfo] target(s) in 0.04s |
| 272 | //! <span style="color: #4E9A06"><b> Running</b></span> `target/debug/examples/custom_section` |
| 273 | //! Error: |
| 274 | //! 0: <span style="color: #F15D22">Unable to read config</span> |
| 275 | //! 1: <span style="color: #F15D22">cmd exited with non-zero status code</span> |
| 276 | //! |
| 277 | //! Stderr: |
| 278 | //! cat: fake_file: No such file or directory |
| 279 | //! |
| 280 | //! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SPANTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ |
| 281 | //! |
| 282 | //! 0: <span style="color: #F15D22">custom_section::output2</span> with <span style="color: #34E2E2">self="cat" "fake_file"</span> |
| 283 | //! at <span style="color: #75507B">examples/custom_section.rs</span>:<span style="color: #75507B">14</span> |
| 284 | //! 1: <span style="color: #F15D22">custom_section::read_file</span> with <span style="color: #34E2E2">path="fake_file"</span> |
| 285 | //! at <span style="color: #75507B">examples/custom_section.rs</span>:<span style="color: #75507B">58</span> |
| 286 | //! 2: <span style="color: #F15D22">custom_section::read_config</span> |
| 287 | //! at <span style="color: #75507B">examples/custom_section.rs</span>:<span style="color: #75507B">63</span> |
| 288 | //! |
| 289 | //! <span style="color: #34E2E2">Suggestion</span>: try using a file that exists next time</pre> |
| 290 | //! |
| 291 | //! Only the `Stderr:` section actually gets included. The `cat` command fails, |
| 292 | //! so stdout ends up being empty and is skipped in the final report. This gives |
| 293 | //! us a short and concise error report indicating exactly what was attempted and |
| 294 | //! how it failed. |
| 295 | //! |
| 296 | //! ### Aggregating multiple errors into one report |
| 297 | //! |
| 298 | //! It's not uncommon for programs like batched task runners or parsers to want |
| 299 | //! to return an error with multiple sources. The current version of the error |
| 300 | //! trait does not support this use case very well, though there is [work being |
| 301 | //! done](https://github.com/rust-lang/rfcs/pull/2895) to improve this. |
| 302 | //! |
| 303 | //! For now however one way to work around this is to compose errors outside the |
| 304 | //! error trait. `color-eyre` supports such composition in its error reports via |
| 305 | //! the `Section` trait. |
| 306 | //! |
| 307 | //! For an example of how to aggregate errors check out [`examples/multiple_errors.rs`]. |
| 308 | //! |
| 309 | //! ### Custom configuration for `color-backtrace` for setting custom filters and more |
| 310 | //! |
| 311 | //! The pretty printing for backtraces and span traces isn't actually provided by |
| 312 | //! `color-eyre`, but instead comes from its dependencies [`color-backtrace`] and |
| 313 | //! [`color-spantrace`]. `color-backtrace` in particular has many more features |
| 314 | //! than are exported by `color-eyre`, such as customized color schemes, panic |
| 315 | //! hooks, and custom frame filters. The custom frame filters are particularly |
| 316 | //! useful when combined with `color-eyre`, so to enable their usage we provide |
| 317 | //! the `install` fn for setting up a custom `BacktracePrinter` with custom |
| 318 | //! filters installed. |
| 319 | //! |
| 320 | //! For an example of how to setup custom filters, check out [`examples/custom_filter.rs`]. |
| 321 | //! |
| 322 | //! [`eyre`]: https://docs.rs/eyre |
| 323 | //! [`tracing-error`]: https://docs.rs/tracing-error |
| 324 | //! [`color-backtrace`]: https://docs.rs/color-backtrace |
| 325 | //! [`eyre::EyreHandler`]: https://docs.rs/eyre/*/eyre/trait.EyreHandler.html |
| 326 | //! [`backtrace::Backtrace`]: https://docs.rs/backtrace/*/backtrace/struct.Backtrace.html |
| 327 | //! [`tracing_error::SpanTrace`]: https://docs.rs/tracing-error/*/tracing_error/struct.SpanTrace.html |
| 328 | //! [`color-spantrace`]: https://github.com/yaahc/color-spantrace |
| 329 | //! [`Section`]: https://docs.rs/color-eyre/*/color_eyre/trait.Section.html |
| 330 | //! [`eyre::Report`]: https://docs.rs/eyre/*/eyre/struct.Report.html |
| 331 | //! [`eyre::Result`]: https://docs.rs/eyre/*/eyre/type.Result.html |
| 332 | //! [`Handler`]: https://docs.rs/color-eyre/*/color_eyre/struct.Handler.html |
| 333 | //! [`examples/usage.rs`]: https://github.com/yaahc/color-eyre/blob/master/examples/usage.rs |
| 334 | //! [`examples/custom_filter.rs`]: https://github.com/yaahc/color-eyre/blob/master/examples/custom_filter.rs |
| 335 | //! [`examples/custom_section.rs`]: https://github.com/yaahc/color-eyre/blob/master/examples/custom_section.rs |
| 336 | //! [`examples/multiple_errors.rs`]: https://github.com/yaahc/color-eyre/blob/master/examples/multiple_errors.rs |
| 337 | #![doc (html_root_url = "https://docs.rs/color-eyre/0.6.3" )] |
| 338 | #![cfg_attr (docsrs, feature(doc_cfg))] |
| 339 | #![warn ( |
| 340 | missing_docs, |
| 341 | rustdoc::missing_doc_code_examples, |
| 342 | rust_2018_idioms, |
| 343 | unreachable_pub, |
| 344 | bad_style, |
| 345 | dead_code, |
| 346 | improper_ctypes, |
| 347 | non_shorthand_field_patterns, |
| 348 | no_mangle_generic_items, |
| 349 | overflowing_literals, |
| 350 | path_statements, |
| 351 | patterns_in_fns_without_body, |
| 352 | unused, |
| 353 | unused_allocation, |
| 354 | unused_comparisons, |
| 355 | unused_parens, |
| 356 | while_true |
| 357 | )] |
| 358 | #![allow (clippy::try_err)] |
| 359 | |
| 360 | use std::sync::Arc; |
| 361 | |
| 362 | use backtrace::Backtrace; |
| 363 | pub use eyre; |
| 364 | #[doc (hidden)] |
| 365 | pub use eyre::Report; |
| 366 | #[doc (hidden)] |
| 367 | pub use eyre::Result; |
| 368 | pub use owo_colors; |
| 369 | use section::help::HelpInfo; |
| 370 | #[doc (hidden)] |
| 371 | pub use section::Section as Help; |
| 372 | pub use section::{IndentedSection, Section, SectionExt}; |
| 373 | #[cfg (feature = "capture-spantrace" )] |
| 374 | use tracing_error::SpanTrace; |
| 375 | #[doc (hidden)] |
| 376 | pub use Handler as Context; |
| 377 | |
| 378 | pub mod config; |
| 379 | mod fmt; |
| 380 | mod handler; |
| 381 | pub(crate) mod private; |
| 382 | pub mod section; |
| 383 | mod writers; |
| 384 | |
| 385 | /// A custom handler type for [`eyre::Report`] which provides colorful error |
| 386 | /// reports and [`tracing-error`] support. |
| 387 | /// |
| 388 | /// # Details |
| 389 | /// |
| 390 | /// This type is not intended to be used directly, prefer using it via the |
| 391 | /// [`color_eyre::Report`] and [`color_eyre::Result`] type aliases. |
| 392 | /// |
| 393 | /// [`eyre::Report`]: https://docs.rs/eyre/*/eyre/struct.Report.html |
| 394 | /// [`tracing-error`]: https://docs.rs/tracing-error |
| 395 | /// [`color_eyre::Report`]: type.Report.html |
| 396 | /// [`color_eyre::Result`]: type.Result.html |
| 397 | pub struct Handler { |
| 398 | filters: Arc<[Box<config::FilterCallback>]>, |
| 399 | backtrace: Option<Backtrace>, |
| 400 | suppress_backtrace: bool, |
| 401 | #[cfg (feature = "capture-spantrace" )] |
| 402 | span_trace: Option<SpanTrace>, |
| 403 | sections: Vec<HelpInfo>, |
| 404 | display_env_section: bool, |
| 405 | #[cfg (feature = "track-caller" )] |
| 406 | display_location_section: bool, |
| 407 | #[cfg (feature = "issue-url" )] |
| 408 | issue_url: Option<String>, |
| 409 | #[cfg (feature = "issue-url" )] |
| 410 | issue_metadata: |
| 411 | std::sync::Arc<Vec<(String, Box<dyn std::fmt::Display + Send + Sync + 'static>)>>, |
| 412 | #[cfg (feature = "issue-url" )] |
| 413 | issue_filter: std::sync::Arc<config::IssueFilterCallback>, |
| 414 | theme: crate::config::Theme, |
| 415 | #[cfg (feature = "track-caller" )] |
| 416 | location: Option<&'static std::panic::Location<'static>>, |
| 417 | } |
| 418 | |
| 419 | /// The kind of type erased error being reported |
| 420 | #[cfg (feature = "issue-url" )] |
| 421 | #[cfg_attr (docsrs, doc(cfg(feature = "issue-url" )))] |
| 422 | pub enum ErrorKind<'a> { |
| 423 | /// A non recoverable error aka `panic!` |
| 424 | NonRecoverable(&'a dyn std::any::Any), |
| 425 | /// A recoverable error aka `impl std::error::Error` |
| 426 | Recoverable(&'a (dyn std::error::Error + 'static)), |
| 427 | } |
| 428 | |
| 429 | /// Install the default panic and error report hooks |
| 430 | /// |
| 431 | /// # Details |
| 432 | /// |
| 433 | /// This function must be called to enable the customization of `eyre::Report` |
| 434 | /// provided by `color-eyre`. This function should be called early, ideally |
| 435 | /// before any errors could be encountered. |
| 436 | /// |
| 437 | /// Only the first install will succeed. Calling this function after another |
| 438 | /// report handler has been installed will cause an error. **Note**: This |
| 439 | /// function _must_ be called before any `eyre::Report`s are constructed to |
| 440 | /// prevent the default handler from being installed. |
| 441 | /// |
| 442 | /// Installing a global theme in `color_spantrace` manually (by calling |
| 443 | /// `color_spantrace::set_theme` or `color_spantrace::colorize` before |
| 444 | /// `install` is called) will result in an error if this function is called. |
| 445 | /// |
| 446 | /// # Examples |
| 447 | /// |
| 448 | /// ```rust |
| 449 | /// use color_eyre::eyre::Result; |
| 450 | /// |
| 451 | /// fn main() -> Result<()> { |
| 452 | /// color_eyre::install()?; |
| 453 | /// |
| 454 | /// // ... |
| 455 | /// # Ok(()) |
| 456 | /// } |
| 457 | /// ``` |
| 458 | pub fn install() -> Result<(), crate::eyre::Report> { |
| 459 | config::HookBuilder::default().install() |
| 460 | } |
| 461 | |