Struct Trace

Source
pub struct Trace { /* private fields */ }
Available on crate feature rt only.
Expand description

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§

Source§

impl Trace

Source

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.

Source

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, do the equivalent of a yield_now (returning a Poll::Pending and scheduling the current context for execution), which means forward progress will probably not happen unless you eventually call your future outside of capture.

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).

Source

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§

Source§

impl Debug for Trace

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Trace

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Trace

§

impl RefUnwindSafe for Trace

§

impl Send for Trace

§

impl Sync for Trace

§

impl Unpin for Trace

§

impl UnwindSafe for Trace

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more