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