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