🛈 Note: This is pre-release documentation for the upcoming tracing 0.2.0 ecosystem.

For the release documentation, please see docs.rs, instead.

Struct EnteredSpan

Source
pub struct EnteredSpan { /* private fields */ }
Expand description

An owned version of Entered, a guard representing a span which has been entered and is currently executing.

When the guard is dropped, the span will be exited.

This is returned by the Span::entered function.

Implementations§

Source§

impl EnteredSpan

Source

pub fn id(&self) -> Option<Id>

Returns this span’s Id, if it is enabled.

Source

pub fn exit(self) -> Span

Exits this span, returning the underlying Span.

Methods from Deref<Target = Span>§

Source

pub fn enter(&self) -> Entered<'_>

Enters this span, returning a guard that will exit the span when dropped.

If this span is enabled by the current collector, then this function will call Collect::enter with the span’s Id, and dropping the guard will call Collect::exit. If the span is disabled, this does nothing.

Note: The returned Entered guard does not implement Send. Dropping the guard will exit this span, and if the guard is sent to another thread and dropped there, that thread may never have entered this span. Thus, Entered should not be sent between threads.

Warning: in asynchronous code that uses async/await syntax, Span::enter should be used very carefully or avoided entirely. Holding the drop guard returned by Span::enter across .await points will result in incorrect traces. For example,

async fn my_async_function() {
    let span = info_span!("my_async_function");

    // WARNING: This span will remain entered until this
    // guard is dropped...
    let _enter = span.enter();
    // ...but the `await` keyword may yield, causing the
    // runtime to switch to another task, while remaining in
    // this span!
    some_other_async_function().await

    // ...
}

The drop guard returned by Span::enter exits the span when it is dropped. When an async function or async block yields at an .await point, the current scope is exited, but values in that scope are not dropped (because the async block will eventually resume execution from that await point). This means that another task will begin executing while remaining in the entered span. This results in an incorrect trace.

Instead of using Span::enter in asynchronous code, prefer the following:

  • To enter a span for a synchronous section of code within an async block or function, prefer Span::in_scope. Since in_scope takes a synchronous closure and exits the span when the closure returns, the span will always be exited before the next await point. For example:

    async fn my_async_function() {
        let span = info_span!("my_async_function");
    
        let some_value = span.in_scope(|| {
            // run some synchronous code inside the span...
        });
    
        // This is okay! The span has already been exited before we reach
        // the await point.
        some_other_async_function(some_value).await;
    
        // ...
    }
  • For instrumenting asynchronous code, tracing provides the Future::instrument combinator for attaching a span to a future (async function or block). This will enter the span every time the future is polled, and exit it whenever the future yields.

    Instrument can be used with an async block inside an async function:

    use tracing::Instrument;
    
    async fn my_async_function() {
        let span = info_span!("my_async_function");
        async move {
           // This is correct! If we yield here, the span will be exited,
           // and re-entered when we resume.
           some_other_async_function().await;
    
           //more asynchronous code inside the span...
    
        }
          // instrument the async block with the span...
          .instrument(span)
          // ...and await it.
          .await
    }

    It can also be used to instrument calls to async functions at the callsite:

    use tracing::Instrument;
    
    async fn my_async_function() {
        let some_value = some_other_async_function()
           .instrument(debug_span!("some_other_async_function"))
           .await;
    
        // ...
    }
  • The #[instrument] attribute macro can automatically generate correct code when used on an async function:

    #[tracing::instrument(level = "info")]
    async fn my_async_function() {
    
        // This is correct! If we yield here, the span will be exited,
        // and re-entered when we resume.
        some_other_async_function().await;
    
        // ...
    
    }
§Examples
let span = span!(Level::INFO, "my_span");
let guard = span.enter();

// code here is within the span

drop(guard);

// code here is no longer within the span

Guards need not be explicitly dropped:

fn my_function() -> String {
    // enter a span for the duration of this function.
    let span = trace_span!("my_function");
    let _enter = span.enter();

    // anything happening in functions we call is still inside the span...
    my_other_function();