eyre-rs / color-eyre Goto Github PK
View Code? Open in Web Editor NEWCustom hooks for colorful human oriented error reports via panics and the eyre crate
License: Other
Custom hooks for colorful human oriented error reports via panics and the eyre crate
License: Other
minimal.rs breaks if sneeze within 2 miles of it. It is sensitive to the line numbers of its source file, adding or removing lines anywhere almost always breaks it, additionally it is sensitive to any changes in coloration for the output format. Fixing the test universally requires manually copying and pasting output from a terminal in a way that preserves ansi codes. We should design a new way to test the output from color-eyre and eyre
in general that is more configurable and less fragile.
I love color-eyre
when developing locally; it is so incredibly helpful! But the colors are a problem when deploying to prod where, for example, Cloudwatch logs for AWS Lambda functions just include raw ANSI escape sequences. I'm working around that right now by using this code in my setup function:
if std::env::var("NO_COLOR") == Err(std::env::VarError::NotPresent) {
color_eyre::install()?;
} else {
color_eyre::config::HookBuilder::new()
.theme(color_eyre::config::Theme::new())
.install()?;
}
and making sure our prod deployments include NO_COLOR=1
.
I'd love to see either:
HookBuilder::blank()
selecting either the default dark theme or the blank theme based on the presence of NO_COLOR
I'm sure you've already seen this, but I found https://no-color.org/ helpful
I'm sorry I don't have the time right now to write up a draft PR for you.
Not sure why this happens as I always thought Windows terminal supports ANSI escape codes. Here is an example output:
$ cargo run
Error:
0: ←[91mMisformatted label definition file. Make sure the file is valid json!←[0m
1: ←[91mmissing field `templates` at line 104 column 1←[0m
Location:
←[35mC:$HOME\.cargo\registry\src\github.com-1ecc6299db9ec823\gh-labels-cli-0.1.8\src\file.rs←[0m:←[35m53←[0m
Backtrace omitted.
Run with RUST_BACKTRACE=1 environment variable to display it.
Run with RUST_BACKTRACE=full to include source snippets.
Windows Terminal Preview
Version: 1.7.572.0
rustc 1.50.0 (cb75ad5db 2021-02-10)
color-eyre 0.5.10
eyre 0.6.5
Currently the panic and error report handlers leverage pre-existing implementations of spantrace and backtrace printing, these impls either print the backtrace or spantrace if it was captured or print a help msg if it was omitted explaining how to enable it.
The application panicked (crashed). Message: called `Option::unwrap()` on a `None` value Location: zebra-state/src/lib.rs:40 Backtrace omitted. Run with RUST_BACKTRACE=1 environment variable to display it. Run with RUST_BACKTRACE=full to include source snippets. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SPANTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0: zebra_state::sled_config::comment with text=TODO(jlusby): Replace this unwrap with a nice user-facing explaining error that the cache dir must be specified at zebra-state/src/lib.rs:36
The problem with this is that the Run with RUST_BACKTRACE...
line is very out of place. We should re-structure how we print backtraces and spantraces to either print the message or set a variable indicating it didn't print, which we can then check at the bottom of the report fn to render the extra suggestions
I was testing out this crate and noticed that the environment variable combination RUST_BACKTRACE=1
and RUST_LIB_BACKTRACE=0
still causes backtraces to be printed from errors. The readme for the eyre
crate mentions that "If you want only panics to have backtraces, set RUST_BACKTRACE=1 and RUST_LIB_BACKTRACE=0." Of course that only applies if you use the nightly backtrace implementation but I assume that this crate should support it as well.
Right now there are some issues with the way ansi_term::Colour::paint
and the bounds it requires for types it paints and how it interacts with std format specifiers. To work around this I've just slapped in a bunch of to_string
and format!
s to just get the code to compile and work. Now all of that needs to be cleaned up. I think for the most part we cannot avoid allocations without fixing upstream issues in ansi_term
, and I haven't had a great experience with responsiveness from the ansi_term
maintainers, so I'd prefer to not block fixes on upstream changes.
To fix this I think we should allocate a single string buffer when we format an error, or if we're feeling really try hard we could even put said string in a thread_local
to reuse the buffer on subsequent format requests. Then, for each case where we have to proactively convert a type to a string to work around bugs in ansi_term
we do so by writing into this single buffer which is then cleared afterwards, preserving the allocation.
Hey Jane 👋 ,
tl;dr library takes my function that returns a Report
, and returns gives me a dyn std::error::Error
, how can I get it back to a Report
to add extra notes onto it?
I've been doing some work with Hyper, and I've run into a situation I'm not quite sure how to handle. I'm working with hyper, and an HTTP Client that supports everything I need it to support. In a custom client I have some code that looks like this:
fn read_request(&self, req: hyper::Request) -> Result<Body> {
// setup code
let resp_result = self.underlying_client.request(req).await;
if let Err(resp_err) = resp_result {
return Err(hyper_to_eyre(/* snipped other pieces of context */, resp_err));
}
// do things with response.
}
The .request()
call ends up calling my custom connector which the relevant bit of context looks like:
let resp = other_conn.call(req).await;
if let Err(resp_err) = resp {
return Err(tcp_stream_to_eyre(resp_err));
}
Ok(EtherStream::Tcp(resp.unwrap()))
If you notice in the error case it is capable of returning a custom Report
error which already has some context in it, but not all of the context I want. Unfortunately the error I get in read_request
is marked as a dyn std::error::Error
, because hyper can throw several of it's own errors as well in this same codepath (my connector call isn't the only thing happening here).
How can I turn this back into a Report
, or something that keeps all the context of the original report, but still allows me to add extra notes?
Hello, I've been using color_eyre
on a work project, and had experienced troubles with the logging (using tracing
/tracing_subscriber
).
Observed Behavior: Creating a eyre::Report
before initializing the tracing_subscriber
even if we're ignoring it makes subsequent logs disappear.
Expected Behavior: The logs should still be printed, wether or not a eyre::Report
is created.
color_eyre
and not on tracing_subscriber
?While testing and trying to know what was happening, I switched to stable_eyre
, and the issue fixed itself, so this must come from color_eyre
.
fn main() {
// Initialize the `color_eyre` Handler
color_eyre::install().unwrap();
// If any [`eyre::Report`] is created (not even returned) at any point before
// the initialization of the `tracing_subscriber`, the tracing logs never output
let _ = color_eyre::eyre::eyre!("A very ignorable error, so we ignore it");
// ^ If we were to comment this line, the log would appear
// Initialize the `tracing_subscriber` Subscriber
tracing_subscriber::fmt::init();
tracing::info!("This log never appears in the console");
}
and I'm using the following versions of crates in my Cargo.toml
:
[dependencies]
tracing = "0.1.35"
tracing-subscriber = "0.3.11"
color-eyre = "0.6.1"
Don't hesitate to ask any question :)
Thanks !
Hi,
I'm using a light background in my terminal and some of the default colors are hard to read – is there a way to change the default color scheme?
BacktracePrinter has a color_scheme method, but I don't see a way to call this method or pass a custom BacktracePrinter
to color-eyre.
The Read Me says the following:
The custom frame filters are particularly useful when combined with color-eyre, so to enable their usage we provide the install fn for setting up a custom BacktracePrinter with custom filters installed.
Would it be possible to either add a method to switch to a color scheme that's optimized for a light background, or add a method that lets the user do this?
ansi_term
released a new major version, 0.12. Looking at the diff I really don't understand why: https://github.com/ogham/rust-ansi-term/compare/v0.11.0..v0.12.0 but this means that the color-eyre
dep is no longer unified with, e.g., the one from tracing-subscriber
.
In some cases it might be useful to bundle several errors into one, displaying them all together. A few prior example are Python's PEP 654, Trio's MultiError (which inspired the former), and Haskell's Validate monad. Would something like that be possible and/or reasonable to add? Asking here rather than eyre
because section
is here, so it feels appropriate.
I can get a mediocre implementation by doing
use std::fmt::Write;
use color_eyre::{Section, SectionExt};
match errors.len() {
0 => Ok(result),
1 => Err(errors.pop().unwrap()),
_ => Err(eyre::eyre!("Multiple errors").section({
let mut s = String::new();
for e in errors {
write!(s, "{:?}", e).unwrap();
}
s.header("Errors:")
})),
}
, but the formatting is pretty bad and contains much duplication; in particular, trimming off the shared tail of the backtraces would make it much better.
Hi, I'm quite new to rust and I'm just starting to use this library for better error output. I don't understand how can the usage.rs
example even run. There is this line with .map(drop)
which is completely obscure to me. As far as I have learned, map expects a Closure, but drop
does not look like a closure, nor has it been defined as a variable. What does it do?
If drop
is a function which is in scope by default, it could be https://doc.rust-lang.org/stable/std/ops/trait.Drop.html, which one tries to execute on a String. But since String is Clone (not Drop), it produces some sort of an error, is that it?
Hi,
in your RustConf you showed this example: `
fn main() -> Result<(), eyre::Report> {
color_eyre::install()?;
let _ = std::process::Command::new("git")
.arg("cat")
.output2()
.wrap_err("The cat couldnot be got")?;
Ok(())
}
`
But I couldn't get it to work.
I tried different use
statements but failed to get the .output2()
working.
Sorry if this issue isn't really one. Help much appreciated on this fun example.
The colored text is quite dark on windows which makes it hard to read. It should probably use the same colors as rustc
since those colors are well tested. rustc
seems to set its colors in rust/src/librustc_errors/emitter.rs
at line 2061 and in rust/src/librustc_errors/lib.rs
at line 957.
The difference seems to be that rustc
is using "intense" colors instead of the normal ones. rustc
is using the termcolor
crate to handle terminal text color and unfortunately ansi_term
doesn't offer a simple way to make colors more intense. We also can't switch to termcolor
since that crate can't be used to color text that is written via std::fmt::Debug
. But I think converting a color to its intense variant can be done using something like:
trait ColorExt {
fn make_intense(self, doit: bool) -> Self;
}
impl ColorExt for ansi_term::Color {
fn make_intense(self, doit: bool) -> Self {
use ansi_term::Color::*;
if doit {
match self {
Black => Fixed(8),
Red => Fixed(9),
Green => Fixed(10),
Yellow => Fixed(11),
Blue => Fixed(12),
Purple => Fixed(13),
Cyan => Fixed(14),
White => Fixed(15),
Fixed(color) if color < 8 => Fixed(color + 8),
other => other,
}
} else {
self
}
}
}
impl ColorExt for ansi_term::Style {
fn make_intense(mut self, doit: bool) -> Self {
if let Some(color) = self.foreground {
self.foreground = Some(color.make_intense(doit));
}
self
}
}
And then just call make_intense(true)
on any color before using it to print something. From my simple testing this results in the same colors as rustc
is using. Also if you want to only do this for windows you can just do make_intense(cfg!(windows))
instead.
Hey again,
Similar to my issue for: #32 , it seems color-eyre has started adding in messages about the fact that backtraces are not being captured, compare a message just using 0.5.0:
With one using 0.5.5:
This adds a lot of noise, even more so when there may be multiple errors printed to the screen (since they're "recoverable" cases):
All this extra lines can make it hard to zero in on what's important, even more so when it's repeated multiple times. Is there any chance similar to the capture spantrace message being able to be turned off with some: capture_span_trace_by_default
we could get an option for disabling the backtrace output as well?
Using this lovely library, and as such I've got a new use case (oh yay!), Currently when telling tracing to log in json by configuring it as such:
let chosen_level = match std::env::var("RUST_LOG_LEVEL").as_ref().map(String::as_str) {
Ok("off") => LevelFilter::OFF,
Ok("error") => LevelFilter::ERROR,
Ok("warn") => LevelFilter::WARN,
Ok("debug") => LevelFilter::DEBUG,
Ok("trace") => LevelFilter::TRACE,
_ => LevelFilter::INFO,
};
let fmt_layer = fmt_layer().with_target(false);
let filter_layer = EnvFilter::from_default_env().add_directive(chosen_level.into());
tracing_subscriber::registry()
.with(filter_layer)
.with(fmt_layer.json())
.with(ErrorLayer::default())
.init();
let res = get_tasks(project_root_path, etype);
if let Err(reportable /*: Report*/) = res {
tracing::error!("{:?}", e);
}
you get the following:
{
"timestamp": "Dec 06 00:39:39.365",
"level": "ERROR",
"fields": {
"message": "\n 0: \u001b[91mpyra::starlark::loop: break used outside of a loop\u001b[0m\n\nLocation:\n \u001b[35msrc/diagnostic/starlark/critical_semantic.rs\u001b[0m:\u001b[35m42\u001b[0m\n\n \u001b[34m\u001b[1m-->\u001b[0m /home/cynthia/projects/personal/pyra/.github/pyra.star:4:3\n\u001b[34m\u001b[1m |\u001b[0m\n...\n\u001b[34m\u001b[1m7 |\u001b[0m break\n\u001b[34m\u001b[1m |\u001b[0m\u001b[31m\u001b[1m ^^^^^\u001b[0m \u001b[31m\u001b[1mthe break keyword is reserved, and can ony be used in a loop\u001b[0m\n\u001b[34m\u001b[1m |\u001b[0m\n\n\u001b[96mSuggestion\u001b[0m: The indentation is less than the line before, perhaps missing an indent?"
}
}
These are the normal fields as tracing for any log message, and if you notice the main error content is all in "message". I'm curious though if there's a way with a Report
object to reverse engineer it back to the "sections"/"notes" that compose that Report'able object so I can say create a json field, one for each section/note/etc. Curious if you have any thoughts?
The underlying color_backtrace crates supports a number of customization options, but there appears to be no way to set them when using color-eyre.
In particular, I wish to add a custom frame filter for my project.
Hi, great lib, thanks for making it!
I've just started using it so I'm not sure about the possibilities/limitations yet.
Couldn't find this question anywhere:
Is it possible to use when writing proc macros in a neat way?
I saw the panic_hook
example which I think I could possibly use to
unwrap()
on fallible function calls in the proc macro implNot sure how the proc macro span stuff will integrate with this (if it works).
I will experiment a bit with this, but perhaps you have some pointers for how to best do this.
I tried out color-eyre in my project that uses Result propagation everywhere (basically just changing all my eyre:Result
imports to color_eyre:Result
). In release builds, I saw no really meaningful difference, but in development builds, I'm seeing server responses that previously took <10 milliseconds now require 3-5 seconds. This is slow enough that it negatively impacts my ability to iterate on the project.
What exactly are the performance consequences of using color-eyre
? Is there maybe a more minimal configuration that would be a little more lightweight?
color eyre is great for command line apps, but gui apps, usually there's no terminal where you can display the output. it would be nice if we could enable a "rfd" feature or something, so that the report is shown in an error dialogue rather than the invisible console.
Hi. Thanks for eyre
and color-eyre
. They're neat ✨ !
We're using our own --debug
option to turn on an off span and back traces:
// Setup `color_eyre` crate for better error reporting with span and back traces
if std::env::var("RUST_SPANTRACE").is_err() {
std::env::set_var("RUST_SPANTRACE", if debug { "1" } else { "0" });
}
if std::env::var("RUST_BACKTRACE").is_err() {
std::env::set_var("RUST_BACKTRACE", if debug { "full" } else { "0" });
}
color_eyre::install()?;
However, we always get a "Backtrace omitted." message which is noisy and potentially confusing for users. It is emanating from here in color-backtrace
and even appers in this crate's examples e.g.
> cargo run --example custom_section
Finished dev [unoptimized + debuginfo] target(s) in 0.02s
Running `target/debug/examples/custom_section`
Error:
0: Unable to read config
1: cmd exited with non-zero status code
Location:
examples/custom_section.rs:22
Stderr:
cat: fake_file: No such file or directory
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SPANTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
0: custom_section::output2 with self="cat" "fake_file"
at examples/custom_section.rs:14
1: custom_section::read_file with path="fake_file"
at examples/custom_section.rs:58
2: custom_section::read_config
at examples/custom_section.rs:63
Suggestion: try using a file that exists next time
Backtrace omitted.
Run with RUST_BACKTRACE=1 environment variable to display it.
Run with RUST_BACKTRACE=full to include source snippets.
Is there a way to configure color-eyre
to prevent the last three lines from being printed?
👋 Hey! I've been porting my crate to use color-eyre
, and this particular application has quite a few "recoverable" errors (perhaps a better word is "warnings" here), but I'd still like to log to the user. I'd like to keep the formatting the same between unrecoverable errors, and recoverable errors I've been doing a pattern where I manually create an error, and just call unwrap_err()
:
use color_eyre::{eyre::eyre, section::help::Help, Report};
use tracing::warn;
warn!(
"{:?}",
Err::<(), Report>(eyre!(
"Mount String for Docker Executor: [{}] is invalid, missing path for container. Will not mount.",
item,
))
.note("Mounts should be in the format: `host_path:path_in_container`")
.unwrap_err()
);
This is because eyre!
does not seem to return something that can have sections on it:
Source Code:
use color_eyre::{eyre::eyre, section::help::Help, Report};
use tracing::warn;
warn!(
"{:?}",
eyre!(
"Mount String for Docker Executor: [{}] is invalid, missing path for container. Will not mount.",
item,
).note("Mounts should be in the format: `host_path:path_in_container`")
);
Compiler Error:
error[E0599]: no method named `note` found for struct `eyre::Report<_>` in the current scope
--> src/executors/docker.rs:311:10
|
311 | ).note("Mounts should be in the format: `host_path:path_in_container`")
| ^^^^ method not found in `eyre::Report<_>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0599`.
I realize this isn't necessarily an error, so I realize it may not exactly fit in the crate, but I figured it'd at least be worth discussion about best path forward since it doesn't feel like a totally unique problem too.
➜ cargo tree | grep eyre
├── color-eyre v0.5.10
│ ├── eyre v0.6.3
I have the following at the top of multiple tests:
color_eyre::install().unwrap_or_else(|_| ());
This causes a panic here: https://github.com/yaahc/color-eyre/blob/master/src/config.rs#L736 because all tests after the first test trigger the panic. Looks like this behavior was introduced in #69.
Is there either a better recommended way to use color-eyre in tests, or could the .expect
be changed to fail gracefully?
based on a discussion with @aldanor in eyre-rs/eyre#41 (comment)
CLI tools are published with each circumstance.
In the case the tool is OSS, backtrace and span trace is very useful because the users can investigate problem by themselves (They can also read source code.) and can report to upstream.
In the case the tool is proprietary, backtrace and span trace is also useful, but I think the developer should make the error message easy to read for users (They may not know Rust.), and make it clear by using note
and suggestion
what the user should do next.
From this viewpoint,
Backtrace omitted.
Run with RUST_BACKTRACE=1 environment variable to display it.
Run with RUST_BACKTRACE=full to include source snippets.
may become noise. I'd like to print this message on debug build and not to do on release build.
More generally, anyhow
has capability to customize error chain output. This is a consequence of the fact that the interface of error chain is public.
I used anyhow
and customized output as below,
let res = do_something();
if let Err(e) = res {
eprintln!();
eprintln!("Error:");
for (i, e) in e.chain().enumerate() {
eprintln!("{:>5}: {}", i, e);
}
std::process::exit(1);
} else {
std::process::exit(0);
}
because, I guess, as you feel this is better than original one. (Especially, in the case the root cause is No such file or directory (os error 2)
, or other difficult-to-undestand error message that the developers of CLI tools cannot control.)
If my understanding is correct, current implementation does not allow developers either
eyre::Handler::debug()
, because struct Handler
has Vec<HelpInfo>
as a member, but visibility of HelpInfo
is pub(crate)
; noreyre::Handler
, because, e.g., note()
requeres downcasting handler to concrete struct crate::Handler
The only available way is forking color-eyre
and making their own little variant, I guess. I think we should not make another crate if the developer is satisfied with collecting capability of color-eyre
(like note
and suggestion
.)
What do you think? I'm a Rust beginner and don't have nice idea to solve the general case...
👋 ,
We have a particular use case that involves deploying to a WASM target, and although the crate seems to build fine with WASM, and work it'd be nice to have continuous integration running on this project that confirms all is working okay as time goes on. FWIW tracing is currently in the same boat: tokio-rs/tracing#642
color-eyre lib.rs
re-exports owo_colors
. Because owo_colors
defines a blanket implementation of its OwoColorize
trait that covers pretty much all types, code completion will show the many many methods of OwoColorize
on every code completion. This makes code completion much less useful for every crate that uses color-eyre
😢.
Example (IntelliJ Rust in CLion):
(IntelliJ Rust intentionally offers methods for completion that aren't in scope yet. When such a method is used, the IDE automatically adds the necessary use
. This is an incredibly useful IDE feature. )
color-eyre
has to re-export owo_colors
? As far as I can tell, no type of owo_colors
shows up in the public API => users who wish to use owo_colors
could define their own dependency.owo_colors
from color-eyre
.I think that color-eyre
is a really cool project 😄 It makes it easy to create CLI tools that communicate information effectively when it's arguably most useful: when things don't quite go according to plan 😉 Thanks for sharing it with the world 😄👍
Hi everyone!
Basically, I'd like to only log when an environment variable is present. Else, just print out the stderr and call it a day. I'm currently writing a parser, that uses ariadne
to pretty-print errors on files. Currently, my code for Eyre looks like this:
fn setup() -> Result<()> {
if std::env::var("SALO_LOG").is_ok() {
if std::env::var("RUST_BACKTRACE").is_err() {
std::env::set_var("RUST_BACKTRACE", "1")
}
color_eyre::install()?;
}
Ok(())
}
When the parser is given code that it deems invalid, it outputs this:
Error: Error
╭─[<unknown>:3:1]
│
3 │ a 2 - 1;
· ┬
· ╰── Unexpected character
────╯
Error: A
Location:
/rustc/35fff69d043b1c0f5c29894e7f4b0da8b039c131/library/core/src/convert/mod.rs:538:9
Which is great already - however, what I'd prefer to see as output is only this:
Error: Error
╭─[<unknown>:3:1]
│
3 │ a 2 - 1;
· ┬
· ╰── Unexpected character
────╯
i.e. omitting the Rust-specific information at the end.
Unless... SALO_LOG
is set (salo is the name of the project:)). In this case, I specifically want a backtrace of the error, all logs, etc.
Not sure if I'm asking in the right place, but some guidance would be awesome. Cheers 🍻
When I copy paste the source code of usage.rs
into a new minimal rust project, it does not show the INFO
trace event and the error does not have the SPANTRACE
section.
The Cargo.toml of that minimal project looks like this:
[package]
name = "minimal"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
color-eyre = {version = "0.6.2", features = ["capture-spantrace"]}
tracing = "0.1.36"
tracing-subscriber = "0.3.15"
tracing-error = "0.2.0"
But when I run cargo run --example usage
in the local clone of the color-eyre
repository, I see the Info Event being print out just just fine:
2022-08-16T06:47:07.017504Z INFO read_config:read_file{path="fake_file"}: Reading file
And the Error is shown with its span trace section:
...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SPANTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
0: usage::read_file with path="fake_file"
at examples\usage.rs:32
1: usage::read_config
at examples\usage.rs:38
...
What am I missing in the minimal example?
Hi!
I tried upgrading eyre
(0.5 -> 0.6) and color_eyre
(0.4.1 -> 0.5) and error messages are no longer colored and don't show suggestions.
with:
eyre = "0.6.0"
color-eyre = { version = "0.5.0", default-features = false }
Looks like it could be because the color_backtrace
dependency is gone? Is there a change in syntax?
The code below fails to compile:
use std::num::ParseIntError;
use color_eyre::Result;
use eyre::eyre;
fn parse(s: &str) -> Result<i32, ParseIntError> {
return s.parse::<i32>();
}
fn main() -> Result<()> {
match parse("abc") {
Ok(n) => Ok(()),
Err(e) => Err(eyre!(e).wrap_err("try parsing an actual number")),
}
}
with the following error:
error[E0308]: mismatched types
--> example.rs:12:23
|
12 | Err(e) => Err(eyre!(e).wrap_err("try parsing an actual number")),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `color_eyre::Handler`, found struct `eyre::DefaultHandler`
|
= note: expected struct `eyre::Report<color_eyre::Handler>`
found struct `eyre::Report<eyre::DefaultHandler>`
error: aborting due to previous error
It seems to me that the dispatch machinery in eyre::kind
module can't deal with different handlers other than the default one, so maybe the issue belongs there, but I ran into this when playing with color_eyre
(which I really like, by the way). The example is a bit contrived, and I'm not sure if I'm doing something I'm not supposed to. What do you think?
There is probably a law that states that any open source Rust project will eventually be asked for serde support.
Anyway, to have this would be great (maybe behind a feature flag, as is tradition).
The use case for me is that I have a networked library, and I want to propagate something like Report
back to the client, to have more meaningful errors on the client.
I would like to add a message like please report the but on github (https://github.com/...)
to the panic hook.
I suggest adding a panic_note
method to HookBuilder
that will just be inserted after the message.
The application panicked (crashed).
Message: No such file or directory (os error 2)
Location: examples/panic_hook.rs:39
Consider reporting the bug on github (https://github.com/yaahc/color-eyre)
Backtrace omitted.
Run with RUST_BACKTRACE=1 environment variable to display it.
Run with RUST_BACKTRACE=full to include source snippets.
I know it's unrelated to this PR, but I found this message confusing when I first encountered it. Perhaps some guidance as to how to "setup an error layer", and what exactly an "error layer" is would be helpful to users who are unfamiliar with the ecosystem.
Originally posted by @kellpossible in #67 (comment)
From examples/theme_test_helper.rs
:
//! Nothing interesting here. This is just a small helper used in a test.
I beg to differ 😄
Using color-eyre
along with the span+guard pattern:
let span = tracing::info_span!("my_span", msg);
let _guard = span.enter();
For me gives the best error reporting I have found as of yet in Rust.
(I wish it was a bit more ergonomic to set up though).
I realize this might fall into the domain of tracing
more than color-eyre
(?), but
I think it's so useful an example highlighting it would be very welcome.
some cfg juggling just needs to be done, should be quite simple
examples/github_issue.rs breaks when we use latest tracing-error.
|
41 | .with(ErrorLayer::default());
| ^^^^^^^^^^^^^^^^^^^^^ the trait `__tracing_subscriber_Layer<Layered<tracing_subscriber::fmt::Layer<Layered<EnvFilter, Registry>>, Layered<EnvFilter, Registry>>>` is not implemented for `ErrorLayer<_>`
Fully reproducible example
Cargo.toml
[dependencies]
color-eyre = { version = "0.5.11", features = ["track-caller","capture-spantrace", "issue-url"] }
tracing = "0.1.29"
tracing-error = { version = "0.2.0", features = ["traced-error"] }
tracing-subscriber = { version = "0.2.5", features = ["env-filter", "json", "fmt"] }
Example
#![allow(dead_code, unused_imports)]
use color_eyre::eyre;
use eyre::{Report, Result};
use tracing::instrument;
#[instrument]
fn main() -> Result<(), Report> {
install_tracing();
color_eyre::config::HookBuilder::default()
.issue_url(concat!(env!("CARGO_PKG_REPOSITORY"), "/issues/new"))
.add_issue_metadata("version", env!("CARGO_PKG_VERSION"))
.issue_filter(|kind| match kind {
color_eyre::ErrorKind::NonRecoverable(_) => false,
color_eyre::ErrorKind::Recoverable(_) => true,
})
.install()?;
let report = read_config().unwrap_err();
eprintln!("Error: {:?}", report);
read_config2();
Ok(())
}
fn install_tracing() {
use tracing_error::ErrorLayer;
use tracing_error::prelude::*;
use tracing_subscriber::prelude::*;
use tracing_subscriber::{fmt, EnvFilter};
let fmt_layer = fmt::layer().with_target(false);
let filter_layer = EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new("info"))
.unwrap();
let k = tracing_subscriber::Registry::default()
.with(filter_layer)
.with(fmt_layer)
.with(ErrorLayer::default());
tracing::subscriber::set_global_default(k).unwrap();
}
#[instrument]
fn read_file(path: &str) -> Result<String> {
Ok(std::fs::read_to_string(path)?)
}
#[instrument]
fn read_config() -> Result<()> {
read_file("fake_file")?;
Ok(())
}
#[instrument]
fn read_file2(path: &str) {
if let Err(e) = std::fs::read_to_string(path) {
panic!("{}", e);
}
}
#[instrument]
fn read_config2() {
read_file2("fake_file")
}
Works fine with
tracing-error = { version = "0.1.2", features = ["traced-error"] }
I've run into a bug when running code on a Raspberry Pi (stable-armv7-unknown-linux-gnueabihf
) where the errors do not print if running with RUST_BACKTRACE=1
or full
. Simple test code:
use eyre::eyre;
use color_eyre::Result;
fn main() -> Result<()> {
return Err(eyre!("Panicy panic"));
}
with:
[dependencies]
eyre = "0.4"
color-eyre = "0.3"
On linux (stable-x86_64-unknown-linux-gnu
) cargo run
produces the following output:
Error:
0: Panicy panic
and RUST_BACKTRACE=1 cargo run
procudes:
Error:
0: Panicy panic
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BACKTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⋮ 3 frames hidden ⋮
4: panic_test::main::h5b6f76bd4e619253
at /home/{USER}/panic_test/src/main.rs:5
⋮ 11 frames hidden ⋮
On the raspberry pi cargo run
behaves as normal but using RUST_BACKTRACE=1
produces:
thread 'main' panicked at 'assertion failed: (self.addr as usize) < (isize::MAX as usize)', <::std::macros::panic macros>:2:4
stack backtrace:
0: backtrace::backtrace::libunwind::trace
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/libunwind.rs:86
1: backtrace::backtrace::trace_unsynchronized
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/mod.rs:66
2: std::sys_common::backtrace::_print_fmt
at src/libstd/sys_common/backtrace.rs:78
3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
at src/libstd/sys_common/backtrace.rs:59
4: core::fmt::write
at src/libcore/fmt/mod.rs:1063
5: std::io::Write::write_fmt
at src/libstd/io/mod.rs:1426
6: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:62
7: std::sys_common::backtrace::print
at src/libstd/sys_common/backtrace.rs:49
8: std::panicking::default_hook::{{closure}}
at src/libstd/panicking.rs:204
9: std::panicking::default_hook
at src/libstd/panicking.rs:224
10: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:470
11: std::panicking::begin_panic
at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/panicking.rs:397
12: <findshlibs::linux::SharedLibrary as findshlibs::SharedLibrary>::virtual_memory_bias
at /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.46/<::std::macros::panic macros>:2
13: backtrace::symbolize::gimli::Cache::new::{{closure}}
at /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.46/src/symbolize/gimli.rs:427
14: findshlibs::linux::SharedLibrary::callback::{{closure}}
at /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/findshlibs-0.5.0/src/linux/mod.rs:185
15: core::ops::function::FnOnce::call_once
at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libcore/ops/function.rs:232
16: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/panic.rs:318
17: std::panicking::try::do_call
at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/panicking.rs:303
18: __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:86
19: std::panicking::try
at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/panicking.rs:281
20: std::panic::catch_unwind
at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/panic.rs:394
21: findshlibs::linux::SharedLibrary::callback
at /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/findshlibs-0.5.0/src/linux/mod.rs:181
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
When running without color-eyre
and just eyre
the raspberry pi behaves as expected, just the error and no backtrace. Not 100% sure the problem is inside color-eyre
but I thought I'd log this.
It would be nice to have something like https://docs.rs/color-backtrace/0.4.2/color_backtrace/struct.BacktracePrinter.html#method.into_panic_handler for HookBuilder
so the panic handler could be combined with other panic handlers in the rust ecosystem without installing it.
Running the usage example on Windows, I get a slightly different output to the documentation:
May 15 15:45:37.897 INFO read_config:read_file{path="fake_file"}: Reading file
Error:
0: Unable to read config
1: The system cannot find the file specified. (os error 2)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SPANTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
0: usage::read_file with path="fake_file"
at examples\usage.rs:31
1: usage::read_config
at examples\usage.rs:37
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BACKTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⋮ 3 frames hidden ⋮
4: color_eyre::{{impl}}::default
at C:\Users\tomSp\Documents\Programming\color-eyre\src\lib.rs:185
⋮ 2 frames hidden ⋮
7: usage::read_config
at C:\Users\tomSp\Documents\Programming\color-eyre\examples\usage.rs:39
8: usage::main
at C:\Users\tomSp\Documents\Programming\color-eyre\examples\usage.rs:10
⋮ 15 frames hidden ⋮
Suggestion: try using a file that exists next time
The read_file
stack frame seems to be outright missing, giving no hint towards the line the actual error occurred. In my own code, I can't find a pattern between the stack frames that get left out, and it makes the message far less useful.
Currently, color_eyre::Context
always generates a new Backtrace
when converting an error..
This is a regression from eyre::DefaultContext
, which will try to preserve an existing Backtrace
, at least on nightly:
https://github.com/yaahc/eyre/blob/dbc3cc181e49657f0bf4e8fbc601c087d96b5757/src/lib.rs#L686
https://github.com/yaahc/eyre/blob/dbc3cc181e49657f0bf4e8fbc601c087d96b5757/src/backtrace.rs#L7-L15
Add a HookBuilder
method that will enable (default) or disable output of tracked location.
e.g
use color_eyre::config::HookBuilder;
fn main() -> eyre::Result<()> {
HookBuilder::new().display_location(false).install()?;
eyre::bail!("an error");
}
gives
Error:
0: an error
Backtrace omitted. Run with RUST_BACKTRACE=1 environment variable to display it.
Run with RUST_BACKTRACE=full to include source snippets.
This program works with color-eyre 0.2.2 but fails to compile with 0.2.3.
// [dependencies]
// color-eyre = "0.2"
// eyre = "0.3"
use color_eyre::Report;
use eyre::WrapErr;
fn main() -> Result<(), Report> {
Ok::<(), Report>(()).wrap_err("...")
}
The next release of color-eyre tries to make some substantial changes to how its structured but overall it should be possible to support mostly drop in place replacement of the old version of color-eyre with the new version
Things to add:
eyre::Report
and eyre::Result
as color_eyre::*
to support old aliases for replacing the default handlercapture-spantrace
by defaultCurrently colored_eyre panics here if you try to install it multiple times. Thus let _ = color_eyre::install();
won't work when used in tests and the result from install() is kinda meaningless.
0: std::panicking::begin_panic_handler
at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\std\src\panicking.rs:517
1: core::panicking::panic_fmt
at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\core\src\panicking.rs:101
2: core::result::unwrap_failed
at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\/library\core\src\result.rs:1617
3: core::result::Result::expect<tuple$<>,color_spantrace::InstallThemeError>
at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35\library\core\src\result.rs:1259
4: color_eyre::config::HookBuilder::into_hooks
at C:\Users\Aron\.cargo\registry\src\github.com-1ecc6299db9ec823\color-eyre-0.5.11\src\config.rs:736
5: color_eyre::config::HookBuilder::install
at C:\Users\Aron\.cargo\registry\src\github.com-1ecc6299db9ec823\color-eyre-0.5.11\src\config.rs:685
6: color_eyre::install
at C:\Users\Aron\.cargo\registry\src\github.com-1ecc6299db9ec823\color-eyre-0.5.11\src\lib.rs:459
Hey 👋 Thanks for the great library!
After installing tracing without adding in a ErrorLayer::default()
(since that prints span traces which I don't want), even when returning an error from a main function I see a note about:
Warning: SpanTrace capture is Unsupported.
Ensure that you've setup an error layer and the versions match
Specifically a full error message looks like:
$ ../../../target/dl
Error:
0: Failed to parse as yaml
--> .dl/dl-tasks.yml:1:11
|
...
3 | - type: ppipeline
| ^ tasks[0].type: unknown variant `ppipeline`, expected one of `command`, `oneof`, `pipeline`, `parallel-pipeline` at line 3 column 11
|
Warning: SpanTrace capture is Unsupported.
Ensure that you've setup an error layer and the versions match
Suggestion: Instead of: "ppipeline", Did you mean: "pipeline"
Note: Full types, and supported values are documented at: https://dev-loop.kungfury.io/docs/schemas/task-conf-file
Is there anyway to remove that: warning: SpanTrace capture is Unsupported
message? I've specifically set it up this way because I don't want span traces captured unless a user is specifically asking for it. As for most users of this binary it won't actually be useful (and serve to confuse potential users who don't understand, and shouldn't have to understand the internals of the tool).
Hey,
would it be possible to add a LICENSE file to the repo?
I am open-sourcing a component that relies on color-eyre and I have to achieve a ClearlyDefined score of >= 75.
Here is the entry for color-eyre 0.5.11: https://clearlydefined.io/definitions/git/github/yaahc/color-eyre/7009a52530cd0442675b9f3b9595d3a28b1fcfe0
I believe adding the LICENSE file should bump the score sufficiently.
Thanks in advance.
Best regards
Darneas
The src/lib.rs
module doc comment still talks about the Help
trait instead of the Section
trait, and a bunch of example code in doc comments still import color_eyre::Help
.
https://github.com/yaahc/color-eyre/blob/472997e9d6911452876032c0db1f9601c70fd91a/src/lib.rs#L224
https://github.com/yaahc/color-eyre/blob/472997e9d6911452876032c0db1f9601c70fd91a/src/lib.rs#L303-L305
https://github.com/yaahc/color-eyre/blob/472997e9d6911452876032c0db1f9601c70fd91a/src/lib.rs#L233
(and 8 more example code references in src/section/mod.rs
)
This is very confusing given that the color_eyre::Help
re-export is marked as #[doc(hidden)]
, and the hyperlink to the Help
trait docs is both broken and not clickable in the cargo doc
/docs.rs rendering anyway. I couldn't figure out what this was talking about until I read through the source to find the hidden re-export
Currently color_eyre
only supports either printing the entire error report including all custom sections, the backtrace, and the span trace. This is a multiple line representation and it doesn't fit well in logs for long running applications. We should try to create an alternate format that fits into one line. Ideally we should print the spantrace first using the existing spantrace formatting logic used to format spans in log messages. The error messages will then be printed using the standard colon separated format error message: cause's error message: cause's cause's error message: ...
This however doesn't handle custom sections, I think it may be sufficient to escape newlines when printing the custom sections but this should be approached with caution.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.