Rust捕获全局panic并记录进程退出日志的方法
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>1. 使用 panic::set_hook 注册异常处理</li><li>2. panic 触发异常</li><li>3. unwrap 触发异常</li><li>4. 使用 human_panic</li></ul></div><p>本文提供了捕获全局<code>panic</code>并记录进程退出日志的方法。</p><p class="maodian"></p><h2>1. 使用 panic::set_hook 注册异常处理</h2>
<div class="jb51code"><pre class="brush:plain;">use human_panic::setup_panic;
use log::error;
use std::{boxed::Box, panic};
fn hook(panic_info: &panic::PanicInfo) {
if cfg!(debug_assertions) {
let err_message = format!("panic occurred {:?}", panic_info);
error!("{}", err_message);
} else {
let err_message = match panic_info.payload().downcast_ref::<&str>() {
Option::Some(&str) => {
let err_message = format!(
"panic info: {:?}, occurred in {:?}",
str,
panic_info.location()
);
err_message
}
Option::None => {
let err_message =
format!("panic occurred in {:?}", panic_info.location());
err_message
}
};
error!("{}", err_message);
}
}
/// 注册异常处理函数
/// 在panic发出后,在panic运行时之前,触发钩子函数去处理这个panic信息。
/// panic信息被保存在PanicInfo结构体中。
pub fn register_panic_hook() {
panic::set_hook(Box::new(|panic_info| {
hook(panic_info);
}));
// setup_panic!();
}</pre></div>
<p class="maodian"></p><h2>2. panic 触发异常</h2>
<div class="jb51code"><pre class="brush:plain;">use core_utils::panic::register_panic_hook;
use core_utils::panic::register_panic_hook;
use env_logger;
use log::LevelFilter;
use std::thread;
use std::time::Duration;
#
fn test_panic_set_hook() {
let _ = env_logger::builder()
.is_test(true)
.filter(None, LevelFilter::Debug)
.try_init();
register_panic_hook();
thread::spawn(|| {
panic!("child thread panic");
});
thread::sleep(Duration::from_millis(100));
}</pre></div>
<p>日志如下</p>
<p><strong>debug模式</strong></p>
<div class="jb51code"><pre class="brush:plain;"> panic occurred PanicInfo { payload: Any { .. }, message: Some(child thread panic), location: Location { file: "core_utils/tests/test_panic.rs", line: 16, col: 9 }, can_unwind: true, force_no_backtrace: false }</pre></div>
<p><strong>release模式</strong></p>
<div class="jb51code"><pre class="brush:plain;"> panic info: "child thread panic", occurred in Some(Location { file: "core_utils/tests/test_panic.rs", line: 17, col: 9 })</pre></div>
<p class="maodian"></p><h2>3. unwrap 触发异常</h2>
<div class="jb51code"><pre class="brush:plain;">#
fn test_panic_unwrap() {
let _ = env_logger::builder()
.is_test(true)
.filter(None, LevelFilter::Debug)
.try_init();
register_panic_hook();
thread::spawn(|| {
let _ = "abc".parse::<i32>().unwrap();
});
thread::sleep(Duration::from_millis(100));
}</pre></div>
<p>日志如下</p>
<p><strong>debug模式</strong></p>
<div class="jb51code"><pre class="brush:plain;"> panic occurred PanicInfo { payload: Any { .. }, message: Some(called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }), location: Location { file: "core_utils/tests/test_panic.rs", line: 33, col: 38 }, can_unwind: true, force_no_backtrace: false }</pre></div>
<p><strong>release模式</strong></p>
<p>注意:unwrap触发的异常会导致 <code>panic_info.payload().downcast_ref::<&str>()</code>返回结果为 None</p>
<div class="jb51code"><pre class="brush:plain;"> panic occurred in Some(Location { file: "core_utils/tests/test_panic.rs", line: 33, col: 38 })</pre></div>
<p class="maodian"></p><h2>4. 使用 human_panic</h2>
<p><code>human_panic</code>只能在非debug模式且环境变量<code>RUST_BACKTRACE</code>未设置的情况下才会生效。</p>
<p>注册 hook</p>
<div class="jb51code"><pre class="brush:plain;">use human_panic::setup_panic;
pub fn register_panic_hook() {
setup_panic!();
}</pre></div>
<p>模拟release环境异常</p>
<div class="jb51code"><pre class="brush:plain;">use core_utils::panic::register_panic_hook;
use env_logger;
use human_panic::setup_panic;
use log::error;
use std::thread;
use std::time::Duration;
fn main() {
env_logger::init();
register_panic_hook();
thread::spawn(|| {
panic!("error");
// let _ = "abc".parse::<i32>().unwrap();
});
thread::sleep(Duration::from_secs(1));
}</pre></div>
<div class="jb51code"><pre class="brush:plain;">cargo run --bin human_panic --release</pre></div>
<p><code>panic</code>发生时会在在临时文件夹下面创建一个报告文件</p>
<div class="jb51code"><pre class="brush:plain;">Well, this is embarrassing.
core_utils had a problem and crashed. To help us diagnose the problem you can send us a crash report.
We have generated a report file at "/var/folders/gx/hn6l2rd56cx0lcwnkblxqvmr0000gn/T/report-93547ab5-9341-4212-a9af-6d2f17d6311d.toml". Submit an issue or email with the subject of "core_utils Crash Report" and include the report as an attachment.
We take privacy seriously, and do not perform any automated error collection. In order to improve the software, we rely on people to submit reports.
Thank you kindly!</pre></div>
<p>报告内容如下</p>
<div class="jb51code"><pre class="brush:plain;">"name" = "core_utils"
"operating_system" = "Mac OS 14.1.1 "
"crate_version" = "0.1.0"
"explanation" = """
Panic occurred in file 'core_utils/src/bin/human_panic.rs' at line 14
"""
"cause" = "error"
"method" = "Panic"
"backtrace" = """
0: 0x105b840a5 - core::panicking::panic_fmt::h2aac8cf45f7ae617
1: 0x1059fd7c6 - std::sys_common::backtrace::__rust_begin_short_backtrace::h4bae865db206eae3
2: 0x1059fe2fd - core::ops::function::FnOnce::call_once{{vtable.shim}}::ha8d441119e8b7a5a
3: 0x105b5a819 - std::sys::pal::unix::thread::Thread::new::thread_start::h679ffa03f8a73496
4: 0x7ff801993202 - __pthread_start"""</pre></div>
<p>到此这篇关于Rust捕获全局panic并记录进程退出日志的文章就介绍到这了,更多相关rust 捕获全局panic内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
<div class="art_xg">
<b>您可能感兴趣的文章:</b><ul><li>rust的nutyp验证和validator验证数据的方法示例详解</li><li>Rust 累计时间长度的操作方法</li><li>rust使用Atomic创建全局变量和使用操作方法</li><li>RUST语言函数的定义与调用方法</li><li>rust 一个日志缓存记录的通用实现方法</li><li>Rust中的方法与关联函数使用解读</li></ul>
</div>
</div>
<!--endmain-->
頁:
[1]