Skip to content

Consider entering Span on Drop for Instrumented #2541

Open
@ilslv

Description

@ilslv

Feature Request

Crates

tracing, tracing-futures

Motivation

Sometimes it's desired to get Span inside Drop implementation. For example:

async {
    let _guard = deferred(|| {
        if std::thread::panicking() {
            tracing::warn!("thread panicked");
        }
    });

    // stuff..
}
.instrument(span)

The problem is there is difference between when Drop can be actually called: inside Future::poll() or on Drop of the entire Future:

use std::{future::Future, pin::Pin, task};

use futures::FutureExt as _;
use tracing::{info_span, Instrument as _, Span};

fn main() {
    tracing_subscriber::fmt().init();

    let span = info_span!("span");

    // polled
    Fut(Some(LogSpanOnDrop))
        .instrument(span.clone())
        .now_or_never()
        .unwrap();

    // never polled
    let _ = Fut(Some(LogSpanOnDrop)).instrument(span);
}

#[derive(Clone, Debug)]
struct LogSpanOnDrop;

impl Drop for LogSpanOnDrop {
    fn drop(&mut self) {
        tracing::info!("drop");
    }
}

struct Fut(Option<LogSpanOnDrop>);

impl Future for Fut {
    type Output = ();

    fn poll(
        mut self: Pin<&mut Self>,
        _: &mut task::Context<'_>,
    ) -> task::Poll<Self::Output> {
        self.set(Fut(None));
        task::Poll::Ready(())
    }
}

Output:

2023-03-30T09:30:46.863224Z  INFO span: soc_common::future::instrumented::t: drop
2023-03-30T09:30:46.863279Z  INFO soc_common::future::instrumented::t: drop

Span is missing for a second log.

Proposal

Would you accept a PR adding Drop implementation for Instrumented, that will enter the Span and Drop inner Future?

Alternatives

Leave it as is.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions