Struct Trace
pub struct Trace { /* private fields */ }
tokio_unstable and Linux and crate feature rt and crate feature taskdump and (AArch64 or s390x or x86 or x86-64) only.An execution trace of a task’s last poll.
Resolving a backtrace, either via the Display impl or via resolve_backtraces, parses debuginfo, which is possibly a CPU-expensive operation that can take a platform-specific but long time to run - often over 100 milliseconds, especially if the current process’s binary is big. In some cases, the platform might internally cache some of the debuginfo, so successive calls to resolve_backtraces might be faster than the first call, but all guarantees are platform-dependent.
To avoid blocking the runtime, it is recommended that you resolve backtraces inside of a spawn_blocking() and to have some concurrency-limiting mechanism to avoid unexpected performance impact.
See Handle::dump.
Implementations
impl Trace
pub fn resolve_backtraces(&self) -> Vec<Backtrace>
Resolve and return a list of backtraces that are involved in polls in this trace.
The exact backtraces included here are unstable and might change in the future, but you can expect one Backtrace for every call to poll to a bottom-level Tokio future - so if something like join! is used, there will be a backtrace for each future in the join.
pub fn capture<F, R>(f: F) -> (R, Trace)where F: FnOnce() -> R,
Runs the function f in tracing mode, and returns its result along with the resulting Trace.
This is normally called with f being the poll function of a future, and will give you a backtrace that tells you what that one future is doing.
Use Handle::dump instead if you want to know what all the tasks in your program are doing. Also see Handle::dump for more documentation about dumps, but unlike Handle::dump, this function should not be much slower than calling f directly.
Due to the way tracing is implemented, Tokio leaf futures will usually, instead of doing their actual work, return Poll::Pending without registering the task’s waker with any driver. This means forward progress will probably not happen unless you eventually call your future outside of capture, or explicitly re-schedule the task (e.g. by calling cx.waker().wake_by_ref()) after capture returns.
Example usage:
use std::future::Future;
use std::task::Poll;
use tokio::runtime::dump::Trace;
// some future
let mut test_future = std::pin::pin!(async move { tokio::task::yield_now().await; 0 });
// trace it once, see what it's doing
let (trace, res) = Trace::root(std::future::poll_fn(|cx| {
let (res, trace) = Trace::capture(|| test_future.as_mut().poll(cx));
Poll::Ready((trace, res))
})).await;
// await it to let it finish, outside of a `capture`
let output = match res {
Poll::Ready(output) => output,
Poll::Pending => test_future.await,
};
println!("{trace}");Nested calls
Nested calls to capture might return partial traces, but will not do any other undesirable behavior (for example, they will not panic).
pub fn root<F>(f: F) -> Root<F> ⓘwhere F: Future,
Create a root for stack traces captured using Trace::capture. Stack frames above the root will not be captured.
Nesting multiple Root futures is fine. Captures will stop at the first root. Not having a Root is fine as well, but there is no guarantee on where the capture will stop.
Trait Implementations
Auto Trait Implementations
impl Freeze for Trace
impl RefUnwindSafe for Trace
impl Send for Trace
impl Sync for Trace
impl Unpin for Trace
impl UnsafeUnpin for Trace
impl UnwindSafe for Trace
Blanket Implementations
impl<T> BorrowMut<T> for Twhere T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
impl<T> Instrument for T
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
impl<T> ToString for T
impl<T> WithSubscriber for T
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ
MIT License
Copyright © Tokio Contributors
https://docs.rs/tokio/1.53.1/tokio/runtime/dump/struct.Trace.html