mirror of https://github.com/zkat/miette.git
feat(panic): add backtrace support to panic handler and move set_panic_hook into fancy features
This commit is contained in:
parent
c6daee7b93
commit
858ac16935
|
|
@ -26,6 +26,7 @@ supports-hyperlinks = { version = "1.1.0", optional = true }
|
||||||
supports-color = { version = "1.0.2", optional = true }
|
supports-color = { version = "1.0.2", optional = true }
|
||||||
supports-unicode = { version = "1.0.0", optional = true }
|
supports-unicode = { version = "1.0.0", optional = true }
|
||||||
itertools = { version = "0.10.1", optional = true }
|
itertools = { version = "0.10.1", optional = true }
|
||||||
|
backtrace = { version = "0.3.61", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
semver = "1.0.4"
|
semver = "1.0.4"
|
||||||
|
|
@ -49,7 +50,8 @@ fancy = [
|
||||||
"supports-hyperlinks",
|
"supports-hyperlinks",
|
||||||
"supports-color",
|
"supports-color",
|
||||||
"supports-unicode",
|
"supports-unicode",
|
||||||
"itertools"
|
"itertools",
|
||||||
|
"backtrace"
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
|
|
|
||||||
61
src/panic.rs
61
src/panic.rs
|
|
@ -1,10 +1,14 @@
|
||||||
|
#![cfg(feature = "fancy")]
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
use backtrace::Backtrace;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{self as miette, Context, Diagnostic, Result};
|
use crate::{self as miette, Context, Diagnostic, Result};
|
||||||
|
|
||||||
/// Tells miette to render panics using its rendering engine.
|
/// Tells miette to render panics using its rendering engine.
|
||||||
pub fn set_panic_hook() {
|
pub fn set_panic_hook() {
|
||||||
std::panic::set_hook(Box::new(|info| {
|
std::panic::set_hook(Box::new(move |info| {
|
||||||
let mut message = "Something went wrong".to_string();
|
let mut message = "Something went wrong".to_string();
|
||||||
let payload = info.payload();
|
let payload = info.payload();
|
||||||
if let Some(msg) = payload.downcast_ref::<&str>() {
|
if let Some(msg) = payload.downcast_ref::<&str>() {
|
||||||
|
|
@ -25,6 +29,59 @@ pub fn set_panic_hook() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error, Diagnostic)]
|
#[derive(Debug, Error, Diagnostic)]
|
||||||
#[error("{0}")]
|
#[error("{0}{}", self.maybe_collect_backtrace())]
|
||||||
#[diagnostic(help("set the `RUST_BACKTRACE=1` environment variable to display a backtrace."))]
|
#[diagnostic(help("set the `RUST_BACKTRACE=1` environment variable to display a backtrace."))]
|
||||||
struct Panic(String);
|
struct Panic(String);
|
||||||
|
|
||||||
|
impl Panic {
|
||||||
|
fn maybe_collect_backtrace(&self) -> String {
|
||||||
|
if let Ok(var) = std::env::var("RUST_BACKTRACE") {
|
||||||
|
if !var.is_empty() && var != "0" {
|
||||||
|
// This is all taken from human-panic: https://github.com/rust-cli/human-panic/blob/master/src/report.rs#L55-L107
|
||||||
|
const HEX_WIDTH: usize = std::mem::size_of::<usize>() + 2;
|
||||||
|
//Padding for next lines after frame's address
|
||||||
|
const NEXT_SYMBOL_PADDING: usize = HEX_WIDTH + 6;
|
||||||
|
let mut backtrace = String::new();
|
||||||
|
for (idx, frame) in Backtrace::new().frames().iter().skip(26).enumerate() {
|
||||||
|
let ip = frame.ip();
|
||||||
|
let _ = write!(backtrace, "\n{:4}: {:2$?}", idx, ip, HEX_WIDTH);
|
||||||
|
|
||||||
|
let symbols = frame.symbols();
|
||||||
|
if symbols.is_empty() {
|
||||||
|
let _ = write!(backtrace, " - <unresolved>");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (idx, symbol) in symbols.iter().enumerate() {
|
||||||
|
//Print symbols from this address,
|
||||||
|
//if there are several addresses
|
||||||
|
//we need to put it on next line
|
||||||
|
if idx != 0 {
|
||||||
|
let _ = write!(backtrace, "\n{:1$}", "", NEXT_SYMBOL_PADDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(name) = symbol.name() {
|
||||||
|
let _ = write!(backtrace, " - {}", name);
|
||||||
|
} else {
|
||||||
|
let _ = write!(backtrace, " - <unknown>");
|
||||||
|
}
|
||||||
|
|
||||||
|
//See if there is debug information with file name and line
|
||||||
|
if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) {
|
||||||
|
let _ = write!(
|
||||||
|
backtrace,
|
||||||
|
"\n{:3$}at {}:{}",
|
||||||
|
"",
|
||||||
|
file.display(),
|
||||||
|
line,
|
||||||
|
NEXT_SYMBOL_PADDING
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return backtrace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"".into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue