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