• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::convert::Infallible;
2 use std::{future::Future, pin::Pin, sync::Arc};
3 
4 use tracing::subscriber::with_default;
5 use tracing_attributes::instrument;
6 use tracing_mock::{expect, subscriber};
7 use tracing_test::{block_on_future, PollN};
8 
9 #[instrument]
test_async_fn(polls: usize) -> Result<(), ()>10 async fn test_async_fn(polls: usize) -> Result<(), ()> {
11     let future = PollN::new_ok(polls);
12     tracing::trace!(awaiting = true);
13     future.await
14 }
15 
16 // Reproduces a compile error when returning an `impl Trait` from an
17 // instrumented async fn (see https://github.com/tokio-rs/tracing/issues/1615)
18 #[allow(dead_code)] // this is just here to test whether it compiles.
19 #[instrument]
test_ret_impl_trait(n: i32) -> Result<impl Iterator<Item = i32>, ()>20 async fn test_ret_impl_trait(n: i32) -> Result<impl Iterator<Item = i32>, ()> {
21     Ok((0..10).filter(move |x| *x < n))
22 }
23 
24 // Reproduces a compile error when returning an `impl Trait` from an
25 // instrumented async fn (see https://github.com/tokio-rs/tracing/issues/1615)
26 #[allow(dead_code)] // this is just here to test whether it compiles.
27 #[instrument(err)]
test_ret_impl_trait_err(n: i32) -> Result<impl Iterator<Item = i32>, &'static str>28 async fn test_ret_impl_trait_err(n: i32) -> Result<impl Iterator<Item = i32>, &'static str> {
29     Ok((0..10).filter(move |x| *x < n))
30 }
31 
32 #[instrument]
test_async_fn_empty()33 async fn test_async_fn_empty() {}
34 
35 #[instrument]
test_async_unsafe_fn_empty()36 async unsafe fn test_async_unsafe_fn_empty() {}
37 
38 // Reproduces a compile error when an instrumented function body contains inner
39 // attributes (https://github.com/tokio-rs/tracing/issues/2294).
40 #[deny(unused_variables)]
41 #[instrument]
repro_async_2294()42 async fn repro_async_2294() {
43     #![allow(unused_variables)]
44     let i = 42;
45 }
46 
47 // Reproduces https://github.com/tokio-rs/tracing/issues/1613
48 #[instrument]
49 // LOAD-BEARING `#[rustfmt::skip]`! This is necessary to reproduce the bug;
50 // with the rustfmt-generated formatting, the lint will not be triggered!
51 #[rustfmt::skip]
52 #[deny(clippy::suspicious_else_formatting)]
repro_1613(var: bool)53 async fn repro_1613(var: bool) {
54     println!(
55         "{}",
56         if var { "true" } else { "false" }
57     );
58 }
59 
60 // Reproduces https://github.com/tokio-rs/tracing/issues/1613
61 // and https://github.com/rust-lang/rust-clippy/issues/7760
62 #[instrument]
63 #[deny(clippy::suspicious_else_formatting)]
repro_1613_2()64 async fn repro_1613_2() {
65     // hello world
66     // else
67 }
68 
69 // Reproduces https://github.com/tokio-rs/tracing/issues/1831
70 #[allow(dead_code)] // this is just here to test whether it compiles.
71 #[instrument]
72 #[deny(unused_braces)]
repro_1831() -> Pin<Box<dyn Future<Output = ()>>>73 fn repro_1831() -> Pin<Box<dyn Future<Output = ()>>> {
74     Box::pin(async move {})
75 }
76 
77 // This replicates the pattern used to implement async trait methods on nightly using the
78 // `type_alias_impl_trait` feature
79 #[allow(dead_code)] // this is just here to test whether it compiles.
80 #[instrument(ret, err)]
81 #[deny(unused_braces)]
82 #[allow(clippy::manual_async_fn)]
repro_1831_2() -> impl Future<Output = Result<(), Infallible>>83 fn repro_1831_2() -> impl Future<Output = Result<(), Infallible>> {
84     async { Ok(()) }
85 }
86 
87 #[test]
async_fn_only_enters_for_polls()88 fn async_fn_only_enters_for_polls() {
89     let (subscriber, handle) = subscriber::mock()
90         .new_span(expect::span().named("test_async_fn"))
91         .enter(expect::span().named("test_async_fn"))
92         .event(expect::event().with_fields(expect::field("awaiting").with_value(&true)))
93         .exit(expect::span().named("test_async_fn"))
94         .enter(expect::span().named("test_async_fn"))
95         .exit(expect::span().named("test_async_fn"))
96         .enter(expect::span().named("test_async_fn"))
97         .exit(expect::span().named("test_async_fn"))
98         .drop_span(expect::span().named("test_async_fn"))
99         .only()
100         .run_with_handle();
101     with_default(subscriber, || {
102         block_on_future(async { test_async_fn(2).await }).unwrap();
103     });
104     handle.assert_finished();
105 }
106 
107 #[test]
async_fn_nested()108 fn async_fn_nested() {
109     #[instrument]
110     async fn test_async_fns_nested() {
111         test_async_fns_nested_other().await
112     }
113 
114     #[instrument]
115     async fn test_async_fns_nested_other() {
116         tracing::trace!(nested = true);
117     }
118 
119     let span = expect::span().named("test_async_fns_nested");
120     let span2 = expect::span().named("test_async_fns_nested_other");
121     let (subscriber, handle) = subscriber::mock()
122         .new_span(span.clone())
123         .enter(span.clone())
124         .new_span(span2.clone())
125         .enter(span2.clone())
126         .event(expect::event().with_fields(expect::field("nested").with_value(&true)))
127         .exit(span2.clone())
128         .enter(span2.clone())
129         .exit(span2.clone())
130         .drop_span(span2)
131         .exit(span.clone())
132         .enter(span.clone())
133         .exit(span.clone())
134         .drop_span(span)
135         .only()
136         .run_with_handle();
137 
138     with_default(subscriber, || {
139         block_on_future(async { test_async_fns_nested().await });
140     });
141 
142     handle.assert_finished();
143 }
144 
145 #[test]
async_fn_with_async_trait()146 fn async_fn_with_async_trait() {
147     use async_trait::async_trait;
148 
149     // test the correctness of the metadata obtained by #[instrument]
150     // (function name, functions parameters) when async-trait is used
151     #[async_trait]
152     pub trait TestA {
153         async fn foo(&mut self, v: usize);
154     }
155 
156     // test nesting of async fns with aync-trait
157     #[async_trait]
158     pub trait TestB {
159         async fn bar(&self);
160     }
161 
162     // test skip(self) with async-await
163     #[async_trait]
164     pub trait TestC {
165         async fn baz(&self);
166     }
167 
168     #[derive(Debug)]
169     struct TestImpl(usize);
170 
171     #[async_trait]
172     impl TestA for TestImpl {
173         #[instrument]
174         async fn foo(&mut self, v: usize) {
175             self.baz().await;
176             self.0 = v;
177             self.bar().await
178         }
179     }
180 
181     #[async_trait]
182     impl TestB for TestImpl {
183         #[instrument]
184         async fn bar(&self) {
185             tracing::trace!(val = self.0);
186         }
187     }
188 
189     #[async_trait]
190     impl TestC for TestImpl {
191         #[instrument(skip(self))]
192         async fn baz(&self) {
193             tracing::trace!(val = self.0);
194         }
195     }
196 
197     let span = expect::span().named("foo");
198     let span2 = expect::span().named("bar");
199     let span3 = expect::span().named("baz");
200     let (subscriber, handle) = subscriber::mock()
201         .new_span(
202             span.clone()
203                 .with_fields(expect::field("self"))
204                 .with_fields(expect::field("v")),
205         )
206         .enter(span.clone())
207         .new_span(span3.clone())
208         .enter(span3.clone())
209         .event(expect::event().with_fields(expect::field("val").with_value(&2u64)))
210         .exit(span3.clone())
211         .enter(span3.clone())
212         .exit(span3.clone())
213         .drop_span(span3)
214         .new_span(span2.clone().with_fields(expect::field("self")))
215         .enter(span2.clone())
216         .event(expect::event().with_fields(expect::field("val").with_value(&5u64)))
217         .exit(span2.clone())
218         .enter(span2.clone())
219         .exit(span2.clone())
220         .drop_span(span2)
221         .exit(span.clone())
222         .enter(span.clone())
223         .exit(span.clone())
224         .drop_span(span)
225         .only()
226         .run_with_handle();
227 
228     with_default(subscriber, || {
229         let mut test = TestImpl(2);
230         block_on_future(async { test.foo(5).await });
231     });
232 
233     handle.assert_finished();
234 }
235 
236 #[test]
async_fn_with_async_trait_and_fields_expressions()237 fn async_fn_with_async_trait_and_fields_expressions() {
238     use async_trait::async_trait;
239 
240     #[async_trait]
241     pub trait Test {
242         async fn call(&mut self, v: usize);
243     }
244 
245     #[derive(Clone, Debug)]
246     struct TestImpl;
247 
248     impl TestImpl {
249         fn foo(&self) -> usize {
250             42
251         }
252     }
253 
254     #[async_trait]
255     impl Test for TestImpl {
256         // check that self is correctly handled, even when using async_trait
257         #[instrument(fields(val=self.foo(), val2=Self::clone(self).foo(), test=%_v+5))]
258         async fn call(&mut self, _v: usize) {}
259     }
260 
261     let span = expect::span().named("call");
262     let (subscriber, handle) = subscriber::mock()
263         .new_span(
264             span.clone().with_fields(
265                 expect::field("_v")
266                     .with_value(&5usize)
267                     .and(expect::field("test").with_value(&tracing::field::debug(10)))
268                     .and(expect::field("val").with_value(&42u64))
269                     .and(expect::field("val2").with_value(&42u64)),
270             ),
271         )
272         .enter(span.clone())
273         .exit(span.clone())
274         .enter(span.clone())
275         .exit(span.clone())
276         .drop_span(span)
277         .only()
278         .run_with_handle();
279 
280     with_default(subscriber, || {
281         block_on_future(async { TestImpl.call(5).await });
282     });
283 
284     handle.assert_finished();
285 }
286 
287 #[test]
async_fn_with_async_trait_and_fields_expressions_with_generic_parameter()288 fn async_fn_with_async_trait_and_fields_expressions_with_generic_parameter() {
289     use async_trait::async_trait;
290 
291     #[async_trait]
292     pub trait Test {
293         async fn call();
294         async fn call_with_self(&self);
295         async fn call_with_mut_self(&mut self);
296     }
297 
298     #[derive(Clone, Debug)]
299     struct TestImpl;
300 
301     // we also test sync functions that return futures, as they should be handled just like
302     // async-trait (>= 0.1.44) functions
303     impl TestImpl {
304         #[instrument(fields(Self=std::any::type_name::<Self>()))]
305         fn sync_fun(&self) -> Pin<Box<dyn Future<Output = ()> + Send + '_>> {
306             let val = self.clone();
307             Box::pin(async move {
308                 let _ = val;
309             })
310         }
311     }
312 
313     #[async_trait]
314     impl Test for TestImpl {
315         // instrumenting this is currently not possible, see https://github.com/tokio-rs/tracing/issues/864#issuecomment-667508801
316         //#[instrument(fields(Self=std::any::type_name::<Self>()))]
317         async fn call() {}
318 
319         #[instrument(fields(Self=std::any::type_name::<Self>()))]
320         async fn call_with_self(&self) {
321             self.sync_fun().await;
322         }
323 
324         #[instrument(fields(Self=std::any::type_name::<Self>()))]
325         async fn call_with_mut_self(&mut self) {}
326     }
327 
328     //let span = span::mock().named("call");
329     let span2 = expect::span().named("call_with_self");
330     let span3 = expect::span().named("call_with_mut_self");
331     let span4 = expect::span().named("sync_fun");
332     let (subscriber, handle) = subscriber::mock()
333         /*.new_span(span.clone()
334             .with_fields(
335                 expect::field("Self").with_value(&"TestImpler")))
336         .enter(span.clone())
337         .exit(span.clone())
338         .drop_span(span)*/
339         .new_span(
340             span2
341                 .clone()
342                 .with_fields(expect::field("Self").with_value(&std::any::type_name::<TestImpl>())),
343         )
344         .enter(span2.clone())
345         .new_span(
346             span4
347                 .clone()
348                 .with_fields(expect::field("Self").with_value(&std::any::type_name::<TestImpl>())),
349         )
350         .enter(span4.clone())
351         .exit(span4.clone())
352         .enter(span4.clone())
353         .exit(span4)
354         .exit(span2.clone())
355         .enter(span2.clone())
356         .exit(span2.clone())
357         .drop_span(span2)
358         .new_span(
359             span3
360                 .clone()
361                 .with_fields(expect::field("Self").with_value(&std::any::type_name::<TestImpl>())),
362         )
363         .enter(span3.clone())
364         .exit(span3.clone())
365         .enter(span3.clone())
366         .exit(span3.clone())
367         .drop_span(span3)
368         .only()
369         .run_with_handle();
370 
371     with_default(subscriber, || {
372         block_on_future(async {
373             TestImpl::call().await;
374             TestImpl.call_with_self().await;
375             TestImpl.call_with_mut_self().await
376         });
377     });
378 
379     handle.assert_finished();
380 }
381 
382 #[test]
out_of_scope_fields()383 fn out_of_scope_fields() {
384     // Reproduces tokio-rs/tracing#1296
385 
386     struct Thing {
387         metrics: Arc<()>,
388     }
389 
390     impl Thing {
391         #[instrument(skip(self, _req), fields(app_id))]
392         fn call(&mut self, _req: ()) -> Pin<Box<dyn Future<Output = Arc<()>> + Send + Sync>> {
393             // ...
394             let metrics = self.metrics.clone();
395             // ...
396             Box::pin(async move {
397                 // ...
398                 metrics // cannot find value `metrics` in this scope
399             })
400         }
401     }
402 
403     let span = expect::span().named("call");
404     let (subscriber, handle) = subscriber::mock()
405         .new_span(span.clone())
406         .enter(span.clone())
407         .exit(span.clone())
408         .enter(span.clone())
409         .exit(span.clone())
410         .drop_span(span)
411         .only()
412         .run_with_handle();
413 
414     with_default(subscriber, || {
415         block_on_future(async {
416             let mut my_thing = Thing {
417                 metrics: Arc::new(()),
418             };
419             my_thing.call(()).await;
420         });
421     });
422 
423     handle.assert_finished();
424 }
425 
426 #[test]
manual_impl_future()427 fn manual_impl_future() {
428     #[allow(clippy::manual_async_fn)]
429     #[instrument]
430     fn manual_impl_future() -> impl Future<Output = ()> {
431         async {
432             tracing::trace!(poll = true);
433         }
434     }
435 
436     let span = expect::span().named("manual_impl_future");
437     let poll_event = || expect::event().with_fields(expect::field("poll").with_value(&true));
438 
439     let (subscriber, handle) = subscriber::mock()
440         // await manual_impl_future
441         .new_span(span.clone())
442         .enter(span.clone())
443         .event(poll_event())
444         .exit(span.clone())
445         .enter(span.clone())
446         .exit(span.clone())
447         .drop_span(span)
448         .only()
449         .run_with_handle();
450 
451     with_default(subscriber, || {
452         block_on_future(async {
453             manual_impl_future().await;
454         });
455     });
456 
457     handle.assert_finished();
458 }
459 
460 #[test]
manual_box_pin()461 fn manual_box_pin() {
462     #[instrument]
463     fn manual_box_pin() -> Pin<Box<dyn Future<Output = ()>>> {
464         Box::pin(async {
465             tracing::trace!(poll = true);
466         })
467     }
468 
469     let span = expect::span().named("manual_box_pin");
470     let poll_event = || expect::event().with_fields(expect::field("poll").with_value(&true));
471 
472     let (subscriber, handle) = subscriber::mock()
473         // await manual_box_pin
474         .new_span(span.clone())
475         .enter(span.clone())
476         .event(poll_event())
477         .exit(span.clone())
478         .enter(span.clone())
479         .exit(span.clone())
480         .drop_span(span)
481         .only()
482         .run_with_handle();
483 
484     with_default(subscriber, || {
485         block_on_future(async {
486             manual_box_pin().await;
487         });
488     });
489 
490     handle.assert_finished();
491 }
492