在我的项目中,我有一个 panic 钩子(Hook),当发生一些计划外的解包时,它会发送一个 HTTP 请求来报告问题。我正在执行某个函数 100 次,我想以某种方式知道何时发生 panic ,是哪一次执行,以防 panic 发生在函数内部。是否可以以某种方式将字符串添加到拦截的panic_info展开中,或者人们如何处理这个问题?
我正在考虑使用catch_unwind,修改捕获的错误并恢复展开,但错误是不透明类型的,所以我看不到向其添加内容的方法。我看到panic_info有有效负载,是否可以以某种方式添加到它?
我想避免使用一些全局互斥体,然后我可以在捕获展开时对其进行修改
最佳答案
一个简单的选择是仅使用 expect()
而不是 unwrap()
并使用信息性错误消息。
另一种方法是使用自定义 panic 类型并尝试向下转换它,例如:
use std::any::Any;
use std::panic::{self, panic_any, UnwindSafe};
// The custom panic payload.
// Must be `'static + Any + Send` for `panic_any()`.
pub struct MyPanicInfo {
pub description: String,
}
trait OptionExt {
type Inner;
fn unwrap_with<F: FnOnce() -> MyPanicInfo>(self, f: F) -> Self::Inner;
}
impl<T> OptionExt for Option<T> {
type Inner = T;
fn unwrap_with<F: FnOnce() -> MyPanicInfo>(self, f: F) -> Self::Inner {
match self {
Some(v) => v,
None => panic_any(f()),
}
}
}
trait ResultExt {
type Ok;
type Err;
fn unwrap_with<F: FnOnce(Self::Err) -> MyPanicInfo>(self, f: F) -> Self::Ok;
}
impl<T, E> ResultExt for Result<T, E> {
type Ok = T;
type Err = E;
fn unwrap_with<F: FnOnce(<Self as ResultExt>::Err) -> MyPanicInfo>(
self,
f: F,
) -> <Self as ResultExt>::Ok {
match self {
Ok(v) => v,
Err(e) => panic_any(f(e)),
}
}
}
pub enum PanicPayload {
MyPanicInfo(Box<MyPanicInfo>),
Unknown(Box<dyn Any + Send>),
}
pub fn my_catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R, PanicPayload> {
panic::catch_unwind(f).map_err(|payload| match payload.downcast() {
Ok(my_panic_info) => PanicPayload::MyPanicInfo(my_panic_info),
Err(unknown_payload) => PanicPayload::Unknown(unknown_payload),
})
}
然后使用类似于 option.unwrap_with(|| MyPanicInfo { description: "abc".to_owned() })
的内容。
关于rust - 如何在捕获时向panick_info添加更多上下文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71065025/