宣布 async-backtrace
October 27, 2022
今天,我们很高兴宣布 async-backtrace 的首次发布,这是一个 crate,使您能够有效地跟踪和查看应用程序中异步任务的状态。
在同步、多线程应用程序中,您可以通过检查所有运行线程的堆栈跟踪来调查死锁。不幸的是,这种方法对于大多数异步 Rust 应用程序来说都失效了,因为挂起的任务(即未被主动轮询的任务)对于传统的堆栈跟踪是不可见的。async-backtrace
crate 填补了这一空白,使您能够看到这些隐藏任务的状态。它的架构设计为高效且无需配置,并且适合在生产环境中部署。
这个 crate 补充了(但尚未与)tracing
库和 tokio-console
集成。使用 async-backtrace
可以鸟瞰应用程序中的任务状态,并使用 tracing
来隔离导致该状态的输入。如果您的应用程序使用 tokio 运行时,则可以使用 tokio-console
来更深入地了解您的应用程序与 tokio 同步原语的交互。
开始使用
要使用 async-backtrace
,首先将该 crate 添加到您的 Cargo.toml
文件中
[dependencies]
async-backtrace = "0.2"
然后,要将您的 async fn
包含在异步任务跟踪中,只需使用 #[async_backtrace::framed]
注释它们,并调用 taskdump_tree
以接收应用程序任务的漂亮打印树。例如
#[tokio::main(flavor = "current_thread")]
async fn main() {
tokio::select! {
// run the following branches in order of their appearance
biased;
// spawn task #1
_ = tokio::spawn(foo()) => { unreachable!() }
// spawn task #2
_ = tokio::spawn(foo()) => { unreachable!() }
// print the running tasks
_ = tokio::spawn(async {}) => {
println!("{}", async_backtrace::taskdump_tree(true));
}
};
}
#[async_backtrace::framed]
async fn foo() {
bar().await;
}
#[async_backtrace::framed]
async fn bar() {
baz().await;
}
#[async_backtrace::framed]
async fn baz() {
std::future::pending::<()>().await
}
运行上面的示例会打印树
╼ multiple::foo::{{closure}} at backtrace/examples/multiple.rs:22:1
└╼ multiple::bar::{{closure}} at backtrace/examples/multiple.rs:27:1
└╼ multiple::baz::{{closure}} at backtrace/examples/multiple.rs:32:1
╼ multiple::foo::{{closure}} at backtrace/examples/multiple.rs:22:1
└╼ multiple::bar::{{closure}} at backtrace/examples/multiple.rs:27:1
└╼ multiple::baz::{{closure}} at backtrace/examples/multiple.rs:32:1
点击这里查看更多示例!
欢迎反馈
这次发布只是一个初始版本。async-backtrace
的工作才刚刚开始。为了指导我们的开发,我们需要您的反馈。所以,请试用一下,并告诉我们效果如何。请提交 issue 并在 Discord 上 ping 我们。
— Jack Wrenn (@jswrenn)