tokio/util/
trace.rs

1cfg_trace! {
2    cfg_rt! {
3        use core::{
4            pin::Pin,
5            task::{Context, Poll},
6        };
7        use pin_project_lite::pin_project;
8        use std::future::Future;
9        pub(crate) use tracing::instrument::Instrumented;
10
11        #[inline]
12        #[track_caller]
13        pub(crate) fn task<F>(task: F, kind: &'static str, name: Option<&str>, id: u64) -> Instrumented<F> {
14            #[track_caller]
15            fn get_span(kind: &'static str, name: Option<&str>, id: u64) -> tracing::Span {
16                let location = std::panic::Location::caller();
17                tracing::trace_span!(
18                    target: "tokio::task",
19                    parent: None,
20                    "runtime.spawn",
21                    %kind,
22                    task.name = %name.unwrap_or_default(),
23                    task.id = id,
24                    loc.file = location.file(),
25                    loc.line = location.line(),
26                    loc.col = location.column(),
27                )
28            }
29            use tracing::instrument::Instrument;
30            let span = get_span(kind, name, id);
31            task.instrument(span)
32        }
33
34        pub(crate) fn async_op<P,F>(inner: P, resource_span: tracing::Span, source: &str, poll_op_name: &'static str, inherits_child_attrs: bool) -> InstrumentedAsyncOp<F>
35        where P: FnOnce() -> F {
36            resource_span.in_scope(|| {
37                let async_op_span = tracing::trace_span!("runtime.resource.async_op", source = source, inherits_child_attrs = inherits_child_attrs);
38                let enter = async_op_span.enter();
39                let async_op_poll_span = tracing::trace_span!("runtime.resource.async_op.poll");
40                let inner = inner();
41                drop(enter);
42                let tracing_ctx = AsyncOpTracingCtx {
43                    async_op_span,
44                    async_op_poll_span,
45                    resource_span: resource_span.clone(),
46                };
47                InstrumentedAsyncOp {
48                    inner,
49                    tracing_ctx,
50                    poll_op_name,
51                }
52            })
53        }
54
55        #[derive(Debug, Clone)]
56        pub(crate) struct AsyncOpTracingCtx {
57            pub(crate) async_op_span: tracing::Span,
58            pub(crate) async_op_poll_span: tracing::Span,
59            pub(crate) resource_span: tracing::Span,
60        }
61
62
63        pin_project! {
64            #[derive(Debug, Clone)]
65            pub(crate) struct InstrumentedAsyncOp<F> {
66                #[pin]
67                pub(crate) inner: F,
68                pub(crate) tracing_ctx: AsyncOpTracingCtx,
69                pub(crate) poll_op_name: &'static str
70            }
71        }
72
73        impl<F: Future> Future for InstrumentedAsyncOp<F> {
74            type Output = F::Output;
75
76            fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
77                let this = self.project();
78                let poll_op_name = &*this.poll_op_name;
79                let _res_enter = this.tracing_ctx.resource_span.enter();
80                let _async_op_enter = this.tracing_ctx.async_op_span.enter();
81                let _async_op_poll_enter = this.tracing_ctx.async_op_poll_span.enter();
82                trace_poll_op!(poll_op_name, this.inner.poll(cx))
83            }
84        }
85    }
86}
87cfg_time! {
88    #[track_caller]
89    pub(crate) fn caller_location() -> Option<&'static std::panic::Location<'static>> {
90        #[cfg(all(tokio_unstable, feature = "tracing"))]
91        return Some(std::panic::Location::caller());
92        #[cfg(not(all(tokio_unstable, feature = "tracing")))]
93        None
94    }
95}
96
97cfg_not_trace! {
98    cfg_rt! {
99        #[inline]
100        pub(crate) fn task<F>(task: F, _: &'static str, _name: Option<&str>, _: u64) -> F {
101            // nop
102            task
103        }
104    }
105}