11use crate :: stdlib:: pin:: Pin ;
22use crate :: stdlib:: task:: { Context , Poll } ;
33use crate :: stdlib:: { future:: Future , marker:: Sized } ;
4- use crate :: { dispatcher, span:: Span , Dispatch } ;
4+ use crate :: {
5+ dispatcher:: { self , Dispatch } ,
6+ span:: Span ,
7+ } ;
58use pin_project_lite:: pin_project;
69
7- /// Attaches spans to a `std::future::Future`.
10+ /// Attaches spans to a [ `std::future::Future`] .
811///
912/// Extension trait allowing futures to be
1013/// instrumented with a `tracing` [span].
1114///
12- /// [span]: ../struct. Span.html
15+ /// [span]: super:: Span
1316pub trait Instrument : Sized {
14- /// Instruments this type with the provided `Span`, returning an
17+ /// Instruments this type with the provided [ `Span`] , returning an
1518 /// `Instrumented` wrapper.
1619 ///
17- /// The attached `Span` will be [entered] every time the instrumented `Future` is polled.
20+ /// The attached [`Span`] will be [entered] every time the instrumented
21+ /// [`Future`] is polled.
1822 ///
1923 /// # Examples
2024 ///
@@ -38,7 +42,7 @@ pub trait Instrument: Sized {
3842 /// `instrument` to ensure that the [current span] is attached to the
3943 /// future if the span passed to `instrument` is [disabled]:
4044 ///
41- /// ```W
45+ /// ```
4246 /// use tracing::Instrument;
4347 /// # mod tokio {
4448 /// # pub(super) fn spawn(_: impl std::future::Future) {}
@@ -74,17 +78,16 @@ pub trait Instrument: Sized {
7478 /// [`Span::or_current`]: super::Span::or_current()
7579 /// [current span]: super::Span::current()
7680 /// [disabled]: super::Span::is_disabled()
81+ /// [`Future`]: std::future::Future
7782 fn instrument ( self , span : Span ) -> Instrumented < Self > {
7883 Instrumented { inner : self , span }
7984 }
8085
81- /// Instruments this type with the [current] `Span`, returning an
86+ /// Instruments this type with the [current] [ `Span`] , returning an
8287 /// `Instrumented` wrapper.
8388 ///
84- /// If the instrumented type is a future, stream, or sink, the attached `Span`
85- /// will be [entered] every time it is polled. If the instrumented type
86- /// is a future executor, every future spawned on that executor will be
87- /// instrumented by the attached `Span`.
89+ /// The attached [`Span`] will be [entered] every time the instrumented
90+ /// [`Future`] is polled.
8891 ///
8992 /// This can be used to propagate the current span when spawning a new future.
9093 ///
@@ -93,6 +96,9 @@ pub trait Instrument: Sized {
9396 /// ```rust
9497 /// use tracing::Instrument;
9598 ///
99+ /// # mod tokio {
100+ /// # pub(super) fn spawn(_: impl std::future::Future) {}
101+ /// # }
96102 /// # async fn doc() {
97103 /// let span = tracing::info_span!("my_span");
98104 /// let _enter = span.enter();
@@ -107,8 +113,10 @@ pub trait Instrument: Sized {
107113 /// # }
108114 /// ```
109115 ///
110- /// [current]: ../struct.Span.html#method.current
111- /// [entered]: ../struct.Span.html#method.enter
116+ /// [current]: super::Span::current()
117+ /// [entered]: super::Span::enter()
118+ /// [`Span`]: crate::Span
119+ /// [`Future`]: std::future::Future
112120 #[ inline]
113121 fn in_current_span ( self ) -> Instrumented < Self > {
114122 self . instrument ( Span :: current ( ) )
@@ -117,63 +125,133 @@ pub trait Instrument: Sized {
117125
118126/// Extension trait allowing futures to be instrumented with
119127/// a `tracing` [`Subscriber`].
120- ///
121- /// [`Subscriber`]: ../trait.Subscriber.html
128+ #[ cfg_attr( docsrs, doc( cfg( feature = "std" ) ) ) ]
122129pub trait WithSubscriber : Sized {
123130 /// Attaches the provided [`Subscriber`] to this type, returning a
124- /// `WithDispatch` wrapper.
131+ /// [`WithDispatch`] wrapper.
132+ ///
133+ /// The attached [`Subscriber`] will be set as the [default] when the returned
134+ /// [`Future`] is polled.
135+ ///
136+ /// # Examples
137+ ///
138+ /// ```
139+ /// # use tracing::subscriber::NoSubscriber as MySubscriber;
140+ /// # use tracing::subscriber::NoSubscriber as MyOtherSubscriber;
141+ /// # async fn docs() {
142+ /// use tracing::instrument::WithSubscriber;
125143 ///
126- /// The attached subscriber will be set as the [default] when the returned `Future` is polled.
144+ /// // Set the default `Subscriber`
145+ /// let _default = tracing::subscriber::set_default(MySubscriber::default());
127146 ///
128- /// [`Subscriber`]: ../trait.Subscriber.html
129- /// [default]: https://docs.rs/tracing/latest/tracing/dispatcher/index.html#setting-the-default-subscriber
147+ /// tracing::info!("this event will be recorded by the default `Subscriber`");
148+ ///
149+ /// // Create a different `Subscriber` and attach it to a future.
150+ /// let other_subscriber = MyOtherSubscriber::default();
151+ /// let future = async {
152+ /// tracing::info!("this event will be recorded by the other `Subscriber`");
153+ /// // ...
154+ /// };
155+ ///
156+ /// future
157+ /// // Attach the other `Subscriber` to the future before awaiting it
158+ /// .with_subscriber(other_subscriber)
159+ /// .await;
160+ ///
161+ /// // Once the future has completed, we return to the default `Subscriber`.
162+ /// tracing::info!("this event will be recorded by the default `Subscriber`");
163+ /// # }
164+ /// ```
165+ ///
166+ /// [`Subscriber`]: super::Subscriber
167+ /// [default]: crate::dispatcher#setting-the-default-subscriber
168+ /// [`Future`]: std::future::Future
130169 fn with_subscriber < S > ( self , subscriber : S ) -> WithDispatch < Self >
131170 where
132171 S : Into < Dispatch > ,
133172 {
134173 WithDispatch {
135174 inner : self ,
136- dispatch : subscriber. into ( ) ,
175+ dispatcher : subscriber. into ( ) ,
137176 }
138177 }
139178
140179 /// Attaches the current [default] [`Subscriber`] to this type, returning a
141- /// `WithDispatch` wrapper.
180+ /// [ `WithDispatch`] wrapper.
142181 ///
143- /// When the wrapped type is a future, stream, or sink, the attached
144- /// subscriber will be set as the [default] while it is being polled.
145- /// When the wrapped type is an executor, the subscriber will be set as the
146- /// default for any futures spawned on that executor.
182+ /// The attached `Subscriber` will be set as the [default] when the returned
183+ /// [`Future`] is polled.
147184 ///
148185 /// This can be used to propagate the current dispatcher context when
149- /// spawning a new future.
186+ /// spawning a new future that may run on a different thread .
150187 ///
151- /// [`Subscriber`]: ../trait.Subscriber.html
152- /// [default]: https://docs.rs/tracing/latest/tracing/dispatcher/index.html#setting-the-default-subscriber
188+ /// # Examples
189+ ///
190+ /// ```
191+ /// # mod tokio {
192+ /// # pub(super) fn spawn(_: impl std::future::Future) {}
193+ /// # }
194+ /// # use tracing::subscriber::NoSubscriber as MySubscriber;
195+ /// # async fn docs() {
196+ /// use tracing::instrument::WithSubscriber;
197+ ///
198+ /// // Using `set_default` (rather than `set_global_default`) sets the
199+ /// // default `Subscriber` for *this* thread only.
200+ /// let _default = tracing::subscriber::set_default(MySubscriber::default());
201+ ///
202+ /// let future = async {
203+ /// // ...
204+ /// };
205+ ///
206+ /// // If a multi-threaded async runtime is in use, this spawned task may
207+ /// // run on a different thread, in a different default `Subscriber`'s context.
208+ /// tokio::spawn(future);
209+ ///
210+ /// // However, calling `with_current_subscriber` on the future before
211+ /// // spawning it, ensures that the current thread's default `Subscriber` is
212+ /// // propagated to the spawned task, regardless of where it executes:
213+ /// # let future = async { };
214+ /// tokio::spawn(future.with_current_subscriber());
215+ /// # }
216+ /// ```
217+ /// [`Subscriber`]: super::Subscriber
218+ /// [default]: crate::dispatcher#setting-the-default-subscriber
219+ /// [`Future`]: std::future::Future
153220 #[ inline]
154221 fn with_current_subscriber ( self ) -> WithDispatch < Self > {
155222 WithDispatch {
156223 inner : self ,
157- dispatch : dispatcher:: get_default ( |default| default. clone ( ) ) ,
224+ dispatcher : crate :: dispatcher:: get_default ( |default| default. clone ( ) ) ,
158225 }
159226 }
160227}
161228
162- impl < T : Sized > WithSubscriber for T { }
163-
164229pin_project ! {
165- /// A future that has been instrumented with a `tracing` subscriber.
230+ /// A [`Future`] that has been instrumented with a `tracing` [`Subscriber`].
231+ ///
232+ /// This type is returned by the [`WithSubscriber`] extension trait. See that
233+ /// trait's documentation for details.
234+ ///
235+ /// [`Future`]: std::future::Future
236+ /// [`Subscriber`]: crate::Subscriber
166237 #[ derive( Clone , Debug ) ]
167238 #[ must_use = "futures do nothing unless you `.await` or poll them" ]
239+ #[ cfg_attr( docsrs, doc( cfg( feature = "std" ) ) ) ]
168240 pub struct WithDispatch <T > {
169241 #[ pin]
170242 inner: T ,
171- dispatch : Dispatch ,
243+ dispatcher : Dispatch ,
172244 }
173245}
174246
175247pin_project ! {
176- /// A future that has been instrumented with a `tracing` span.
248+ /// A [`Future`] that has been instrumented with a `tracing` [`Span`].
249+ ///
250+ /// This type is returned by the [`Instrument`] extension trait. See that
251+ /// trait's documentation for details.
252+ ///
253+ /// [`Future`]: std::future::Future
254+ /// [`Span`]: crate::Span
177255 #[ derive( Debug , Clone ) ]
178256 #[ must_use = "futures do nothing unless you `.await` or poll them" ]
179257 pub struct Instrumented <T > {
@@ -183,6 +261,8 @@ pin_project! {
183261 }
184262}
185263
264+ // === impl Instrumented ===
265+
186266impl < T : Future > Future for Instrumented < T > {
187267 type Output = T :: Output ;
188268
@@ -233,3 +313,58 @@ impl<T> Instrumented<T> {
233313 self . inner
234314 }
235315}
316+
317+ // === impl WithDispatch ===
318+
319+ #[ cfg( feature = "std" ) ]
320+ #[ cfg_attr( docsrs, doc( cfg( feature = "std" ) ) ) ]
321+ impl < T : Future > Future for WithDispatch < T > {
322+ type Output = T :: Output ;
323+
324+ fn poll ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
325+ let this = self . project ( ) ;
326+ let dispatcher = this. dispatcher ;
327+ let future = this. inner ;
328+ let _default = dispatcher:: set_default ( dispatcher) ;
329+ future. poll ( cx)
330+ }
331+ }
332+
333+ #[ cfg_attr( docsrs, doc( cfg( feature = "std" ) ) ) ]
334+ impl < T : Sized > WithSubscriber for T { }
335+
336+ #[ cfg( feature = "std" ) ]
337+ #[ cfg_attr( docsrs, doc( cfg( feature = "std" ) ) ) ]
338+ impl < T > WithDispatch < T > {
339+ /// Borrows the [`Dispatch`] that is entered when this type is polled.
340+ pub fn dispatcher ( & self ) -> & Dispatch {
341+ & self . dispatcher
342+ }
343+
344+ /// Borrows the wrapped type.
345+ pub fn inner ( & self ) -> & T {
346+ & self . inner
347+ }
348+
349+ /// Mutably borrows the wrapped type.
350+ pub fn inner_mut ( & mut self ) -> & mut T {
351+ & mut self . inner
352+ }
353+
354+ /// Get a pinned reference to the wrapped type.
355+ pub fn inner_pin_ref ( self : Pin < & Self > ) -> Pin < & T > {
356+ self . project_ref ( ) . inner
357+ }
358+
359+ /// Get a pinned mutable reference to the wrapped type.
360+ pub fn inner_pin_mut ( self : Pin < & mut Self > ) -> Pin < & mut T > {
361+ self . project ( ) . inner
362+ }
363+
364+ /// Consumes the `Instrumented`, returning the wrapped type.
365+ ///
366+ /// Note that this drops the span.
367+ pub fn into_inner ( self ) -> T {
368+ self . inner
369+ }
370+ }
0 commit comments