/rust/registry/src/index.crates.io-6f17d22bba15001f/tracing-0.1.41/src/instrument.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use crate::{ |
2 | | dispatcher::{self, Dispatch}, |
3 | | span::Span, |
4 | | }; |
5 | | use core::{ |
6 | | future::Future, |
7 | | marker::Sized, |
8 | | mem::ManuallyDrop, |
9 | | pin::Pin, |
10 | | task::{Context, Poll}, |
11 | | }; |
12 | | use pin_project_lite::pin_project; |
13 | | |
14 | | /// Attaches spans to a [`std::future::Future`]. |
15 | | /// |
16 | | /// Extension trait allowing futures to be |
17 | | /// instrumented with a `tracing` [span]. |
18 | | /// |
19 | | /// [span]: super::Span |
20 | | pub trait Instrument: Sized { |
21 | | /// Instruments this type with the provided [`Span`], returning an |
22 | | /// `Instrumented` wrapper. |
23 | | /// |
24 | | /// The attached [`Span`] will be [entered] every time the instrumented |
25 | | /// [`Future`] is polled or [`Drop`]ped. |
26 | | /// |
27 | | /// # Examples |
28 | | /// |
29 | | /// Instrumenting a future: |
30 | | /// |
31 | | /// ```rust |
32 | | /// use tracing::Instrument; |
33 | | /// |
34 | | /// # async fn doc() { |
35 | | /// let my_future = async { |
36 | | /// // ... |
37 | | /// }; |
38 | | /// |
39 | | /// my_future |
40 | | /// .instrument(tracing::info_span!("my_future")) |
41 | | /// .await |
42 | | /// # } |
43 | | /// ``` |
44 | | /// |
45 | | /// The [`Span::or_current`] combinator can be used in combination with |
46 | | /// `instrument` to ensure that the [current span] is attached to the |
47 | | /// future if the span passed to `instrument` is [disabled]: |
48 | | /// |
49 | | /// ``` |
50 | | /// use tracing::Instrument; |
51 | | /// # mod tokio { |
52 | | /// # pub(super) fn spawn(_: impl std::future::Future) {} |
53 | | /// # } |
54 | | /// |
55 | | /// let my_future = async { |
56 | | /// // ... |
57 | | /// }; |
58 | | /// |
59 | | /// let outer_span = tracing::info_span!("outer").entered(); |
60 | | /// |
61 | | /// // If the "my_future" span is enabled, then the spawned task will |
62 | | /// // be within both "my_future" *and* "outer", since "outer" is |
63 | | /// // "my_future"'s parent. However, if "my_future" is disabled, |
64 | | /// // the spawned task will *not* be in any span. |
65 | | /// tokio::spawn( |
66 | | /// my_future |
67 | | /// .instrument(tracing::debug_span!("my_future")) |
68 | | /// ); |
69 | | /// |
70 | | /// // Using `Span::or_current` ensures the spawned task is instrumented |
71 | | /// // with the current span, if the new span passed to `instrument` is |
72 | | /// // not enabled. This means that if the "my_future" span is disabled, |
73 | | /// // the spawned task will still be instrumented with the "outer" span: |
74 | | /// # let my_future = async {}; |
75 | | /// tokio::spawn( |
76 | | /// my_future |
77 | | /// .instrument(tracing::debug_span!("my_future").or_current()) |
78 | | /// ); |
79 | | /// ``` |
80 | | /// |
81 | | /// [entered]: super::Span::enter() |
82 | | /// [`Span::or_current`]: super::Span::or_current() |
83 | | /// [current span]: super::Span::current() |
84 | | /// [disabled]: super::Span::is_disabled() |
85 | | /// [`Future`]: std::future::Future |
86 | 12.3k | fn instrument(self, span: Span) -> Instrumented<Self> { |
87 | 12.3k | Instrumented { |
88 | 12.3k | inner: ManuallyDrop::new(self), |
89 | 12.3k | span, |
90 | 12.3k | } |
91 | 12.3k | } Unexecuted instantiation: <_ as tracing::instrument::Instrument>::instrument <<h2::client::Connection<fuzz_e2e::MockIo>>::handshake2::{closure#0} as tracing::instrument::Instrument>::instrument Line | Count | Source | 86 | 12.3k | fn instrument(self, span: Span) -> Instrumented<Self> { | 87 | 12.3k | Instrumented { | 88 | 12.3k | inner: ManuallyDrop::new(self), | 89 | 12.3k | span, | 90 | 12.3k | } | 91 | 12.3k | } |
|
92 | | |
93 | | /// Instruments this type with the [current] [`Span`], returning an |
94 | | /// `Instrumented` wrapper. |
95 | | /// |
96 | | /// The attached [`Span`] will be [entered] every time the instrumented |
97 | | /// [`Future`] is polled or [`Drop`]ped. |
98 | | /// |
99 | | /// This can be used to propagate the current span when spawning a new future. |
100 | | /// |
101 | | /// # Examples |
102 | | /// |
103 | | /// ```rust |
104 | | /// use tracing::Instrument; |
105 | | /// |
106 | | /// # mod tokio { |
107 | | /// # pub(super) fn spawn(_: impl std::future::Future) {} |
108 | | /// # } |
109 | | /// # async fn doc() { |
110 | | /// let span = tracing::info_span!("my_span"); |
111 | | /// let _enter = span.enter(); |
112 | | /// |
113 | | /// // ... |
114 | | /// |
115 | | /// let future = async { |
116 | | /// tracing::debug!("this event will occur inside `my_span`"); |
117 | | /// // ... |
118 | | /// }; |
119 | | /// tokio::spawn(future.in_current_span()); |
120 | | /// # } |
121 | | /// ``` |
122 | | /// |
123 | | /// [current]: super::Span::current() |
124 | | /// [entered]: super::Span::enter() |
125 | | /// [`Span`]: crate::Span |
126 | | /// [`Future`]: std::future::Future |
127 | | #[inline] |
128 | 0 | fn in_current_span(self) -> Instrumented<Self> { |
129 | 0 | self.instrument(Span::current()) |
130 | 0 | } |
131 | | } |
132 | | |
133 | | /// Extension trait allowing futures to be instrumented with |
134 | | /// a `tracing` [`Subscriber`](crate::Subscriber). |
135 | | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] |
136 | | pub trait WithSubscriber: Sized { |
137 | | /// Attaches the provided [`Subscriber`] to this type, returning a |
138 | | /// [`WithDispatch`] wrapper. |
139 | | /// |
140 | | /// The attached [`Subscriber`] will be set as the [default] when the returned |
141 | | /// [`Future`] is polled. |
142 | | /// |
143 | | /// # Examples |
144 | | /// |
145 | | /// ``` |
146 | | /// # use tracing::subscriber::NoSubscriber as MySubscriber; |
147 | | /// # use tracing::subscriber::NoSubscriber as MyOtherSubscriber; |
148 | | /// # async fn docs() { |
149 | | /// use tracing::instrument::WithSubscriber; |
150 | | /// |
151 | | /// // Set the default `Subscriber` |
152 | | /// let _default = tracing::subscriber::set_default(MySubscriber::default()); |
153 | | /// |
154 | | /// tracing::info!("this event will be recorded by the default `Subscriber`"); |
155 | | /// |
156 | | /// // Create a different `Subscriber` and attach it to a future. |
157 | | /// let other_subscriber = MyOtherSubscriber::default(); |
158 | | /// let future = async { |
159 | | /// tracing::info!("this event will be recorded by the other `Subscriber`"); |
160 | | /// // ... |
161 | | /// }; |
162 | | /// |
163 | | /// future |
164 | | /// // Attach the other `Subscriber` to the future before awaiting it |
165 | | /// .with_subscriber(other_subscriber) |
166 | | /// .await; |
167 | | /// |
168 | | /// // Once the future has completed, we return to the default `Subscriber`. |
169 | | /// tracing::info!("this event will be recorded by the default `Subscriber`"); |
170 | | /// # } |
171 | | /// ``` |
172 | | /// |
173 | | /// [`Subscriber`]: super::Subscriber |
174 | | /// [default]: crate::dispatcher#setting-the-default-subscriber |
175 | | /// [`Future`]: std::future::Future |
176 | 0 | fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> |
177 | 0 | where |
178 | 0 | S: Into<Dispatch>, |
179 | 0 | { |
180 | 0 | WithDispatch { |
181 | 0 | inner: self, |
182 | 0 | dispatcher: subscriber.into(), |
183 | 0 | } |
184 | 0 | } |
185 | | |
186 | | /// Attaches the current [default] [`Subscriber`] to this type, returning a |
187 | | /// [`WithDispatch`] wrapper. |
188 | | /// |
189 | | /// The attached `Subscriber` will be set as the [default] when the returned |
190 | | /// [`Future`] is polled. |
191 | | /// |
192 | | /// This can be used to propagate the current dispatcher context when |
193 | | /// spawning a new future that may run on a different thread. |
194 | | /// |
195 | | /// # Examples |
196 | | /// |
197 | | /// ``` |
198 | | /// # mod tokio { |
199 | | /// # pub(super) fn spawn(_: impl std::future::Future) {} |
200 | | /// # } |
201 | | /// # use tracing::subscriber::NoSubscriber as MySubscriber; |
202 | | /// # async fn docs() { |
203 | | /// use tracing::instrument::WithSubscriber; |
204 | | /// |
205 | | /// // Using `set_default` (rather than `set_global_default`) sets the |
206 | | /// // default `Subscriber` for *this* thread only. |
207 | | /// let _default = tracing::subscriber::set_default(MySubscriber::default()); |
208 | | /// |
209 | | /// let future = async { |
210 | | /// // ... |
211 | | /// }; |
212 | | /// |
213 | | /// // If a multi-threaded async runtime is in use, this spawned task may |
214 | | /// // run on a different thread, in a different default `Subscriber`'s context. |
215 | | /// tokio::spawn(future); |
216 | | /// |
217 | | /// // However, calling `with_current_subscriber` on the future before |
218 | | /// // spawning it, ensures that the current thread's default `Subscriber` is |
219 | | /// // propagated to the spawned task, regardless of where it executes: |
220 | | /// # let future = async { }; |
221 | | /// tokio::spawn(future.with_current_subscriber()); |
222 | | /// # } |
223 | | /// ``` |
224 | | /// [`Subscriber`]: super::Subscriber |
225 | | /// [default]: crate::dispatcher#setting-the-default-subscriber |
226 | | /// [`Future`]: std::future::Future |
227 | | #[inline] |
228 | 0 | fn with_current_subscriber(self) -> WithDispatch<Self> { |
229 | 0 | WithDispatch { |
230 | 0 | inner: self, |
231 | 0 | dispatcher: crate::dispatcher::get_default(|default| default.clone()), |
232 | 0 | } |
233 | 0 | } |
234 | | } |
235 | | |
236 | | pin_project! { |
237 | | /// A [`Future`] that has been instrumented with a `tracing` [`Subscriber`]. |
238 | | /// |
239 | | /// This type is returned by the [`WithSubscriber`] extension trait. See that |
240 | | /// trait's documentation for details. |
241 | | /// |
242 | | /// [`Future`]: std::future::Future |
243 | | /// [`Subscriber`]: crate::Subscriber |
244 | | #[derive(Clone, Debug)] |
245 | | #[must_use = "futures do nothing unless you `.await` or poll them"] |
246 | | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] |
247 | | pub struct WithDispatch<T> { |
248 | | #[pin] |
249 | | inner: T, |
250 | | dispatcher: Dispatch, |
251 | | } |
252 | | } |
253 | | |
254 | | pin_project! { |
255 | | /// A [`Future`] that has been instrumented with a `tracing` [`Span`]. |
256 | | /// |
257 | | /// This type is returned by the [`Instrument`] extension trait. See that |
258 | | /// trait's documentation for details. |
259 | | /// |
260 | | /// [`Future`]: std::future::Future |
261 | | /// [`Span`]: crate::Span |
262 | | #[project = InstrumentedProj] |
263 | | #[project_ref = InstrumentedProjRef] |
264 | | #[derive(Debug, Clone)] |
265 | | #[must_use = "futures do nothing unless you `.await` or poll them"] |
266 | | pub struct Instrumented<T> { |
267 | | // `ManuallyDrop` is used here to to enter instrument `Drop` by entering |
268 | | // `Span` and executing `ManuallyDrop::drop`. |
269 | | #[pin] |
270 | | inner: ManuallyDrop<T>, |
271 | | span: Span, |
272 | | } |
273 | | |
274 | | impl<T> PinnedDrop for Instrumented<T> { |
275 | | fn drop(this: Pin<&mut Self>) { |
276 | | let this = this.project(); |
277 | | let _enter = this.span.enter(); |
278 | | // SAFETY: 1. `Pin::get_unchecked_mut()` is safe, because this isn't |
279 | | // different from wrapping `T` in `Option` and calling |
280 | | // `Pin::set(&mut this.inner, None)`, except avoiding |
281 | | // additional memory overhead. |
282 | | // 2. `ManuallyDrop::drop()` is safe, because |
283 | | // `PinnedDrop::drop()` is guaranteed to be called only |
284 | | // once. |
285 | | unsafe { ManuallyDrop::drop(this.inner.get_unchecked_mut()) } |
286 | | } |
287 | | } |
288 | | } |
289 | | |
290 | | impl<'a, T> InstrumentedProj<'a, T> { |
291 | | /// Get a mutable reference to the [`Span`] a pinned mutable reference to |
292 | | /// the wrapped type. |
293 | 105k | fn span_and_inner_pin_mut(self) -> (&'a mut Span, Pin<&'a mut T>) { |
294 | 105k | // SAFETY: As long as `ManuallyDrop<T>` does not move, `T` won't move |
295 | 105k | // and `inner` is valid, because `ManuallyDrop::drop` is called |
296 | 105k | // only inside `Drop` of the `Instrumented`. |
297 | 105k | let inner = unsafe { self.inner.map_unchecked_mut(|v| &mut **v) }; Unexecuted instantiation: <tracing::instrument::InstrumentedProj<_>>::span_and_inner_pin_mut::{closure#0} <tracing::instrument::InstrumentedProj<<h2::client::Connection<fuzz_e2e::MockIo>>::handshake2::{closure#0}>>::span_and_inner_pin_mut::{closure#0} Line | Count | Source | 297 | 105k | let inner = unsafe { self.inner.map_unchecked_mut(|v| &mut **v) }; |
|
298 | 105k | (self.span, inner) |
299 | 105k | } Unexecuted instantiation: <tracing::instrument::InstrumentedProj<_>>::span_and_inner_pin_mut <tracing::instrument::InstrumentedProj<<h2::client::Connection<fuzz_e2e::MockIo>>::handshake2::{closure#0}>>::span_and_inner_pin_mut Line | Count | Source | 293 | 105k | fn span_and_inner_pin_mut(self) -> (&'a mut Span, Pin<&'a mut T>) { | 294 | 105k | // SAFETY: As long as `ManuallyDrop<T>` does not move, `T` won't move | 295 | 105k | // and `inner` is valid, because `ManuallyDrop::drop` is called | 296 | 105k | // only inside `Drop` of the `Instrumented`. | 297 | 105k | let inner = unsafe { self.inner.map_unchecked_mut(|v| &mut **v) }; | 298 | 105k | (self.span, inner) | 299 | 105k | } |
|
300 | | } |
301 | | |
302 | | impl<'a, T> InstrumentedProjRef<'a, T> { |
303 | | /// Get a reference to the [`Span`] a pinned reference to the wrapped type. |
304 | 0 | fn span_and_inner_pin_ref(self) -> (&'a Span, Pin<&'a T>) { |
305 | 0 | // SAFETY: As long as `ManuallyDrop<T>` does not move, `T` won't move |
306 | 0 | // and `inner` is valid, because `ManuallyDrop::drop` is called |
307 | 0 | // only inside `Drop` of the `Instrumented`. |
308 | 0 | let inner = unsafe { self.inner.map_unchecked(|v| &**v) }; |
309 | 0 | (self.span, inner) |
310 | 0 | } |
311 | | } |
312 | | |
313 | | // === impl Instrumented === |
314 | | |
315 | | impl<T: Future> Future for Instrumented<T> { |
316 | | type Output = T::Output; |
317 | | |
318 | 105k | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
319 | 105k | let (span, inner) = self.project().span_and_inner_pin_mut(); |
320 | 105k | let _enter = span.enter(); |
321 | 105k | inner.poll(cx) |
322 | 105k | } Unexecuted instantiation: <tracing::instrument::Instrumented<_> as core::future::future::Future>::poll <tracing::instrument::Instrumented<<h2::client::Connection<fuzz_e2e::MockIo>>::handshake2::{closure#0}> as core::future::future::Future>::poll Line | Count | Source | 318 | 105k | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | 319 | 105k | let (span, inner) = self.project().span_and_inner_pin_mut(); | 320 | 105k | let _enter = span.enter(); | 321 | 105k | inner.poll(cx) | 322 | 105k | } |
|
323 | | } |
324 | | |
325 | | impl<T: Sized> Instrument for T {} |
326 | | |
327 | | impl<T> Instrumented<T> { |
328 | | /// Borrows the `Span` that this type is instrumented by. |
329 | 0 | pub fn span(&self) -> &Span { |
330 | 0 | &self.span |
331 | 0 | } |
332 | | |
333 | | /// Mutably borrows the `Span` that this type is instrumented by. |
334 | 0 | pub fn span_mut(&mut self) -> &mut Span { |
335 | 0 | &mut self.span |
336 | 0 | } |
337 | | |
338 | | /// Borrows the wrapped type. |
339 | 0 | pub fn inner(&self) -> &T { |
340 | 0 | &self.inner |
341 | 0 | } |
342 | | |
343 | | /// Mutably borrows the wrapped type. |
344 | 0 | pub fn inner_mut(&mut self) -> &mut T { |
345 | 0 | &mut self.inner |
346 | 0 | } |
347 | | |
348 | | /// Get a pinned reference to the wrapped type. |
349 | 0 | pub fn inner_pin_ref(self: Pin<&Self>) -> Pin<&T> { |
350 | 0 | self.project_ref().span_and_inner_pin_ref().1 |
351 | 0 | } |
352 | | |
353 | | /// Get a pinned mutable reference to the wrapped type. |
354 | 0 | pub fn inner_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { |
355 | 0 | self.project().span_and_inner_pin_mut().1 |
356 | 0 | } |
357 | | |
358 | | /// Consumes the `Instrumented`, returning the wrapped type. |
359 | | /// |
360 | | /// Note that this drops the span. |
361 | 0 | pub fn into_inner(self) -> T { |
362 | 0 | // To manually destructure `Instrumented` without `Drop`, we |
363 | 0 | // move it into a ManuallyDrop and use pointers to its fields |
364 | 0 | let this = ManuallyDrop::new(self); |
365 | 0 | let span: *const Span = &this.span; |
366 | 0 | let inner: *const ManuallyDrop<T> = &this.inner; |
367 | 0 | // SAFETY: Those pointers are valid for reads, because `Drop` didn't |
368 | 0 | // run, and properly aligned, because `Instrumented` isn't |
369 | 0 | // `#[repr(packed)]`. |
370 | 0 | let _span = unsafe { span.read() }; |
371 | 0 | let inner = unsafe { inner.read() }; |
372 | 0 | ManuallyDrop::into_inner(inner) |
373 | 0 | } |
374 | | } |
375 | | |
376 | | // === impl WithDispatch === |
377 | | |
378 | | #[cfg(feature = "std")] |
379 | | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] |
380 | | impl<T: Future> Future for WithDispatch<T> { |
381 | | type Output = T::Output; |
382 | | |
383 | 0 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
384 | 0 | let this = self.project(); |
385 | 0 | let dispatcher = this.dispatcher; |
386 | 0 | let future = this.inner; |
387 | 0 | let _default = dispatcher::set_default(dispatcher); |
388 | 0 | future.poll(cx) |
389 | 0 | } |
390 | | } |
391 | | |
392 | | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] |
393 | | impl<T: Sized> WithSubscriber for T {} |
394 | | |
395 | | #[cfg(feature = "std")] |
396 | | #[cfg_attr(docsrs, doc(cfg(feature = "std")))] |
397 | | impl<T> WithDispatch<T> { |
398 | | /// Borrows the [`Dispatch`] that is entered when this type is polled. |
399 | 0 | pub fn dispatcher(&self) -> &Dispatch { |
400 | 0 | &self.dispatcher |
401 | 0 | } |
402 | | |
403 | | /// Borrows the wrapped type. |
404 | 0 | pub fn inner(&self) -> &T { |
405 | 0 | &self.inner |
406 | 0 | } |
407 | | |
408 | | /// Mutably borrows the wrapped type. |
409 | 0 | pub fn inner_mut(&mut self) -> &mut T { |
410 | 0 | &mut self.inner |
411 | 0 | } |
412 | | |
413 | | /// Get a pinned reference to the wrapped type. |
414 | 0 | pub fn inner_pin_ref(self: Pin<&Self>) -> Pin<&T> { |
415 | 0 | self.project_ref().inner |
416 | 0 | } |
417 | | |
418 | | /// Get a pinned mutable reference to the wrapped type. |
419 | 0 | pub fn inner_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { |
420 | 0 | self.project().inner |
421 | 0 | } |
422 | | |
423 | | /// Consumes the `Instrumented`, returning the wrapped type. |
424 | | /// |
425 | | /// Note that this drops the span. |
426 | 0 | pub fn into_inner(self) -> T { |
427 | 0 | self.inner |
428 | 0 | } |
429 | | } |