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 instrument(self, span: Span) -> Instrumented<Self>86 fn instrument(self, span: Span) -> Instrumented<Self> { 87 Instrumented { 88 inner: ManuallyDrop::new(self), 89 span, 90 } 91 } 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] in_current_span(self) -> Instrumented<Self>128 fn in_current_span(self) -> Instrumented<Self> { 129 self.instrument(Span::current()) 130 } 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 with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> where S: Into<Dispatch>,176 fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> 177 where 178 S: Into<Dispatch>, 179 { 180 WithDispatch { 181 inner: self, 182 dispatcher: subscriber.into(), 183 } 184 } 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] with_current_subscriber(self) -> WithDispatch<Self>228 fn with_current_subscriber(self) -> WithDispatch<Self> { 229 WithDispatch { 230 inner: self, 231 dispatcher: crate::dispatcher::get_default(|default| default.clone()), 232 } 233 } 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. span_and_inner_pin_mut(self) -> (&'a mut Span, Pin<&'a mut T>)293 fn span_and_inner_pin_mut(self) -> (&'a mut Span, Pin<&'a mut T>) { 294 // SAFETY: As long as `ManuallyDrop<T>` does not move, `T` won't move 295 // and `inner` is valid, because `ManuallyDrop::drop` is called 296 // only inside `Drop` of the `Instrumented`. 297 let inner = unsafe { self.inner.map_unchecked_mut(|v| &mut **v) }; 298 (self.span, inner) 299 } 300 } 301 302 impl<'a, T> InstrumentedProjRef<'a, T> { 303 /// Get a reference to the [`Span`] a pinned reference to the wrapped type. span_and_inner_pin_ref(self) -> (&'a Span, Pin<&'a T>)304 fn span_and_inner_pin_ref(self) -> (&'a Span, Pin<&'a T>) { 305 // SAFETY: As long as `ManuallyDrop<T>` does not move, `T` won't move 306 // and `inner` is valid, because `ManuallyDrop::drop` is called 307 // only inside `Drop` of the `Instrumented`. 308 let inner = unsafe { self.inner.map_unchecked(|v| &**v) }; 309 (self.span, inner) 310 } 311 } 312 313 // === impl Instrumented === 314 315 impl<T: Future> Future for Instrumented<T> { 316 type Output = T::Output; 317 poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>318 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 319 let (span, inner) = self.project().span_and_inner_pin_mut(); 320 let _enter = span.enter(); 321 inner.poll(cx) 322 } 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. span(&self) -> &Span329 pub fn span(&self) -> &Span { 330 &self.span 331 } 332 333 /// Mutably borrows the `Span` that this type is instrumented by. span_mut(&mut self) -> &mut Span334 pub fn span_mut(&mut self) -> &mut Span { 335 &mut self.span 336 } 337 338 /// Borrows the wrapped type. inner(&self) -> &T339 pub fn inner(&self) -> &T { 340 &self.inner 341 } 342 343 /// Mutably borrows the wrapped type. inner_mut(&mut self) -> &mut T344 pub fn inner_mut(&mut self) -> &mut T { 345 &mut self.inner 346 } 347 348 /// Get a pinned reference to the wrapped type. inner_pin_ref(self: Pin<&Self>) -> Pin<&T>349 pub fn inner_pin_ref(self: Pin<&Self>) -> Pin<&T> { 350 self.project_ref().span_and_inner_pin_ref().1 351 } 352 353 /// Get a pinned mutable reference to the wrapped type. inner_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>354 pub fn inner_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { 355 self.project().span_and_inner_pin_mut().1 356 } 357 358 /// Consumes the `Instrumented`, returning the wrapped type. 359 /// 360 /// Note that this drops the span. into_inner(self) -> T361 pub fn into_inner(self) -> T { 362 // To manually destructure `Instrumented` without `Drop`, we 363 // move it into a ManuallyDrop and use pointers to its fields 364 let this = ManuallyDrop::new(self); 365 let span: *const Span = &this.span; 366 let inner: *const ManuallyDrop<T> = &this.inner; 367 // SAFETY: Those pointers are valid for reads, because `Drop` didn't 368 // run, and properly aligned, because `Instrumented` isn't 369 // `#[repr(packed)]`. 370 let _span = unsafe { span.read() }; 371 let inner = unsafe { inner.read() }; 372 ManuallyDrop::into_inner(inner) 373 } 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 poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>383 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 384 let this = self.project(); 385 let dispatcher = this.dispatcher; 386 let future = this.inner; 387 let _default = dispatcher::set_default(dispatcher); 388 future.poll(cx) 389 } 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. dispatcher(&self) -> &Dispatch399 pub fn dispatcher(&self) -> &Dispatch { 400 &self.dispatcher 401 } 402 403 /// Borrows the wrapped type. inner(&self) -> &T404 pub fn inner(&self) -> &T { 405 &self.inner 406 } 407 408 /// Mutably borrows the wrapped type. inner_mut(&mut self) -> &mut T409 pub fn inner_mut(&mut self) -> &mut T { 410 &mut self.inner 411 } 412 413 /// Get a pinned reference to the wrapped type. inner_pin_ref(self: Pin<&Self>) -> Pin<&T>414 pub fn inner_pin_ref(self: Pin<&Self>) -> Pin<&T> { 415 self.project_ref().inner 416 } 417 418 /// Get a pinned mutable reference to the wrapped type. inner_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>419 pub fn inner_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { 420 self.project().inner 421 } 422 423 /// Consumes the `Instrumented`, returning the wrapped type. 424 /// 425 /// Note that this drops the span. into_inner(self) -> T426 pub fn into_inner(self) -> T { 427 self.inner 428 } 429 } 430