1cfg_rt! {
2 use std::marker::PhantomData;
3
4 #[derive(Copy, Clone)]
5 pub(crate) struct SpawnMeta<'a> {
6 #[cfg(all(tokio_unstable, feature = "tracing"))]
8 pub(crate) name: Option<&'a str>,
9 #[cfg(all(tokio_unstable, feature = "tracing"))]
11 pub(crate) original_size: usize,
12 _pd: PhantomData<&'a ()>,
13 }
14
15 impl<'a> SpawnMeta<'a> {
16 #[cfg(all(tokio_unstable, feature = "tracing"))]
18 pub(crate) fn new(name: Option<&'a str>, original_size: usize) -> Self {
19 Self {
20 name,
21 original_size,
22 _pd: PhantomData,
23 }
24 }
25
26 pub(crate) fn new_unnamed(original_size: usize) -> Self {
28 #[cfg(not(all(tokio_unstable, feature = "tracing")))]
29 let _original_size = original_size;
30
31 Self {
32 #[cfg(all(tokio_unstable, feature = "tracing"))]
33 name: None,
34 #[cfg(all(tokio_unstable, feature = "tracing"))]
35 original_size,
36 _pd: PhantomData,
37 }
38 }
39 }
40
41 cfg_trace! {
42 use core::{
43 pin::Pin,
44 task::{Context, Poll},
45 };
46 use pin_project_lite::pin_project;
47 use std::mem;
48 use std::future::Future;
49 use tracing::instrument::Instrument;
50 pub(crate) use tracing::instrument::Instrumented;
51
52 #[inline]
53 #[track_caller]
54 pub(crate) fn task<F>(task: F, kind: &'static str, meta: SpawnMeta<'_>, id: u64) -> Instrumented<F> {
55 #[track_caller]
56 fn get_span(kind: &'static str, spawn_meta: SpawnMeta<'_>, id: u64, task_size: usize) -> tracing::Span {
57 let location = std::panic::Location::caller();
58 let original_size = if spawn_meta.original_size != task_size {
59 Some(spawn_meta.original_size)
60 } else {
61 None
62 };
63 tracing::trace_span!(
64 target: "tokio::task",
65 parent: None,
66 "runtime.spawn",
67 %kind,
68 task.name = %spawn_meta.name.unwrap_or_default(),
69 task.id = id,
70 original_size.bytes = original_size,
71 size.bytes = task_size,
72 loc.file = location.file(),
73 loc.line = location.line(),
74 loc.col = location.column(),
75 )
76 }
77 use tracing::instrument::Instrument;
78 let span = get_span(kind, meta, id, mem::size_of::<F>());
79 task.instrument(span)
80 }
81
82 #[inline]
83 #[track_caller]
84 pub(crate) fn blocking_task<Fn, Fut>(task: Fut, spawn_meta: SpawnMeta<'_>, id: u64) -> Instrumented<Fut> {
85 let location = std::panic::Location::caller();
86
87 let fn_size = mem::size_of::<Fn>();
88 let original_size = if spawn_meta.original_size != fn_size {
89 Some(spawn_meta.original_size)
90 } else {
91 None
92 };
93
94 let span = tracing::trace_span!(
95 target: "tokio::task::blocking",
96 "runtime.spawn",
97 kind = %"blocking",
98 task.name = %spawn_meta.name.unwrap_or_default(),
99 task.id = id,
100 "fn" = %std::any::type_name::<Fn>(),
101 original_size.bytes = original_size,
102 size.bytes = fn_size,
103 loc.file = location.file(),
104 loc.line = location.line(),
105 loc.col = location.column(),
106 );
107 task.instrument(span)
108
109 }
110
111 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>
112 where P: FnOnce() -> F {
113 resource_span.in_scope(|| {
114 let async_op_span = tracing::trace_span!("runtime.resource.async_op", source = source, inherits_child_attrs = inherits_child_attrs);
115 let enter = async_op_span.enter();
116 let async_op_poll_span = tracing::trace_span!("runtime.resource.async_op.poll");
117 let inner = inner();
118 drop(enter);
119 let tracing_ctx = AsyncOpTracingCtx {
120 async_op_span,
121 async_op_poll_span,
122 resource_span: resource_span.clone(),
123 };
124 InstrumentedAsyncOp {
125 inner,
126 tracing_ctx,
127 poll_op_name,
128 }
129 })
130 }
131
132 #[derive(Debug, Clone)]
133 pub(crate) struct AsyncOpTracingCtx {
134 pub(crate) async_op_span: tracing::Span,
135 pub(crate) async_op_poll_span: tracing::Span,
136 pub(crate) resource_span: tracing::Span,
137 }
138
139
140 pin_project! {
141 #[derive(Debug, Clone)]
142 pub(crate) struct InstrumentedAsyncOp<F> {
143 #[pin]
144 pub(crate) inner: F,
145 pub(crate) tracing_ctx: AsyncOpTracingCtx,
146 pub(crate) poll_op_name: &'static str
147 }
148 }
149
150 impl<F: Future> Future for InstrumentedAsyncOp<F> {
151 type Output = F::Output;
152
153 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
154 let this = self.project();
155 let poll_op_name = &*this.poll_op_name;
156 let _res_enter = this.tracing_ctx.resource_span.enter();
157 let _async_op_enter = this.tracing_ctx.async_op_span.enter();
158 let _async_op_poll_enter = this.tracing_ctx.async_op_poll_span.enter();
159 trace_poll_op!(poll_op_name, this.inner.poll(cx))
160 }
161 }
162 }
163
164 cfg_not_trace! {
165 #[inline]
166 pub(crate) fn task<F>(task: F, _kind: &'static str, _meta: SpawnMeta<'_>, _id: u64) -> F {
167 task
169 }
170
171 #[inline]
172 pub(crate) fn blocking_task<Fn, Fut>(task: Fut, _spawn_meta: SpawnMeta<'_>, _id: u64) -> Fut {
173 let _ = PhantomData::<&Fn>;
174 task
176 }
177 }
178}
179
180cfg_time! {
181 #[track_caller]
182 pub(crate) fn caller_location() -> Option<&'static std::panic::Location<'static>> {
183 #[cfg(all(tokio_unstable, feature = "tracing"))]
184 return Some(std::panic::Location::caller());
185 #[cfg(not(all(tokio_unstable, feature = "tracing")))]
186 None
187 }
188}