70 %
Chris Biscardi

Custom github issue templated error messages for panic with eyre and Rust

This is an example from this thread on twitter using this PR from yaahc_ on color-eyre. The PanicMessage impl is a direct copy and the github issue formatting is all in custom_url.

rust
use color_eyre::eyre::{eyre, Result, WrapErr};
use color_eyre::section::PanicMessage;
use owo_colors::OwoColorize;
use std::{fmt, panic::Location};
use sys_info::{os_release, os_type};
use url::Url;
struct MyPanicMessage;
const VERSION: &'static str = env!("CARGO_PKG_VERSION");
impl PanicMessage for MyPanicMessage {
fn display(&self, pi: &std::panic::PanicInfo<'_>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "{}", "The application panicked (crashed).".red())?;
// Print panic message.
let payload = pi
.payload()
.downcast_ref::<String>()
.map(String::as_str)
.or_else(|| pi.payload().downcast_ref::<&str>().cloned())
.unwrap_or("<non string panic payload>");
write!(f, "Message: ")?;
writeln!(f, "{}", payload.cyan())?;
// If known, print panic location.
write!(f, "Location: ")?;
if let Some(loc) = pi.location() {
write!(f, "{}", loc.file().purple())?;
write!(f, ":")?;
write!(f, "{}", loc.line().purple())?;
write!(
f,
"\n\nConsider reporting the bug using this URL: {}",
custom_url(loc, payload).cyan()
)?;
} else {
write!(f, "<unknown>")?;
}
Ok(())
}
}
fn custom_url(location: &Location<'_>, message: &str) -> impl fmt::Display {
let url_result = Url::parse_with_params(
"https://github.com/christopherBiscardi/toast/issues/new",
&[
("title", "<autogenerated-issue>"),
(
"body",
format!(
"## Metadata
|key|value|
|--|--|
|**version**|{}|
|**os_type**|{}|
|**os_release**|{}|
|**message**|{}|
|**location**|{}|
## More info
",
VERSION,
os_type().unwrap_or("unavailable".to_string()),
os_release().unwrap_or("unavailable".to_string()),
message,
location,
)
.as_str(),
),
],
);
match &url_result {
Ok(url_struct) => format!("{}", url_struct),
Err(_e) => String::from("https://github.com/christopherBiscardi/toast/issues/new"),
}
}