1 use tracing::subscriber::with_default;
2 use tracing::Level;
3 use tracing_attributes::instrument;
4 use tracing_mock::*;
5 use tracing_subscriber::filter::EnvFilter;
6 use tracing_subscriber::layer::SubscriberExt;
7 
8 use std::convert::TryFrom;
9 use std::num::TryFromIntError;
10 
11 #[instrument(err)]
err() -> Result<u8, TryFromIntError>12 fn err() -> Result<u8, TryFromIntError> {
13     u8::try_from(1234)
14 }
15 
16 #[instrument(err)]
err_suspicious_else() -> Result<u8, TryFromIntError>17 fn err_suspicious_else() -> Result<u8, TryFromIntError> {
18     {}
19     u8::try_from(1234)
20 }
21 
22 #[test]
test()23 fn test() {
24     let span = expect::span().named("err");
25     let (subscriber, handle) = subscriber::mock()
26         .new_span(span.clone())
27         .enter(span.clone())
28         .event(expect::event().at_level(Level::ERROR))
29         .exit(span.clone())
30         .drop_span(span)
31         .only()
32         .run_with_handle();
33     with_default(subscriber, || err().ok());
34     handle.assert_finished();
35 }
36 
37 #[instrument(err)]
err_early_return() -> Result<u8, TryFromIntError>38 fn err_early_return() -> Result<u8, TryFromIntError> {
39     u8::try_from(1234)?;
40     Ok(5)
41 }
42 
43 #[test]
test_early_return()44 fn test_early_return() {
45     let span = expect::span().named("err_early_return");
46     let (subscriber, handle) = subscriber::mock()
47         .new_span(span.clone())
48         .enter(span.clone())
49         .event(expect::event().at_level(Level::ERROR))
50         .exit(span.clone())
51         .drop_span(span)
52         .only()
53         .run_with_handle();
54     with_default(subscriber, || err_early_return().ok());
55     handle.assert_finished();
56 }
57 
58 #[instrument(err)]
err_async(polls: usize) -> Result<u8, TryFromIntError>59 async fn err_async(polls: usize) -> Result<u8, TryFromIntError> {
60     let future = PollN::new_ok(polls);
61     tracing::trace!(awaiting = true);
62     future.await.ok();
63     u8::try_from(1234)
64 }
65 
66 #[test]
test_async()67 fn test_async() {
68     let span = expect::span().named("err_async");
69     let (subscriber, handle) = subscriber::mock()
70         .new_span(span.clone())
71         .enter(span.clone())
72         .event(
73             expect::event()
74                 .with_fields(expect::field("awaiting").with_value(&true))
75                 .at_level(Level::TRACE),
76         )
77         .exit(span.clone())
78         .enter(span.clone())
79         .event(expect::event().at_level(Level::ERROR))
80         .exit(span.clone())
81         .enter(span.clone())
82         .exit(span.clone())
83         .drop_span(span)
84         .only()
85         .run_with_handle();
86     with_default(subscriber, || {
87         block_on_future(async { err_async(2).await }).ok();
88     });
89     handle.assert_finished();
90 }
91 
92 #[instrument(err)]
err_mut(out: &mut u8) -> Result<(), TryFromIntError>93 fn err_mut(out: &mut u8) -> Result<(), TryFromIntError> {
94     *out = u8::try_from(1234)?;
95     Ok(())
96 }
97 
98 #[test]
test_mut()99 fn test_mut() {
100     let span = expect::span().named("err_mut");
101     let (subscriber, handle) = subscriber::mock()
102         .new_span(span.clone())
103         .enter(span.clone())
104         .event(expect::event().at_level(Level::ERROR))
105         .exit(span.clone())
106         .drop_span(span)
107         .only()
108         .run_with_handle();
109     with_default(subscriber, || err_mut(&mut 0).ok());
110     handle.assert_finished();
111 }
112 
113 #[instrument(err)]
err_mut_async(polls: usize, out: &mut u8) -> Result<(), TryFromIntError>114 async fn err_mut_async(polls: usize, out: &mut u8) -> Result<(), TryFromIntError> {
115     let future = PollN::new_ok(polls);
116     tracing::trace!(awaiting = true);
117     future.await.ok();
118     *out = u8::try_from(1234)?;
119     Ok(())
120 }
121 
122 #[test]
test_mut_async()123 fn test_mut_async() {
124     let span = expect::span().named("err_mut_async");
125     let (subscriber, handle) = subscriber::mock()
126         .new_span(span.clone())
127         .enter(span.clone())
128         .event(
129             expect::event()
130                 .with_fields(expect::field("awaiting").with_value(&true))
131                 .at_level(Level::TRACE),
132         )
133         .exit(span.clone())
134         .enter(span.clone())
135         .event(expect::event().at_level(Level::ERROR))
136         .exit(span.clone())
137         .enter(span.clone())
138         .exit(span.clone())
139         .drop_span(span)
140         .only()
141         .run_with_handle();
142     with_default(subscriber, || {
143         block_on_future(async { err_mut_async(2, &mut 0).await }).ok();
144     });
145     handle.assert_finished();
146 }
147 
148 #[test]
impl_trait_return_type()149 fn impl_trait_return_type() {
150     // Reproduces https://github.com/tokio-rs/tracing/issues/1227
151 
152     #[instrument(err)]
153     fn returns_impl_trait(x: usize) -> Result<impl Iterator<Item = usize>, String> {
154         Ok(0..x)
155     }
156 
157     let span = expect::span().named("returns_impl_trait");
158 
159     let (subscriber, handle) = subscriber::mock()
160         .new_span(
161             span.clone()
162                 .with_field(expect::field("x").with_value(&10usize).only()),
163         )
164         .enter(span.clone())
165         .exit(span.clone())
166         .drop_span(span)
167         .only()
168         .run_with_handle();
169 
170     with_default(subscriber, || {
171         for _ in returns_impl_trait(10).unwrap() {
172             // nop
173         }
174     });
175 
176     handle.assert_finished();
177 }
178 
179 #[instrument(err(Debug))]
err_dbg() -> Result<u8, TryFromIntError>180 fn err_dbg() -> Result<u8, TryFromIntError> {
181     u8::try_from(1234)
182 }
183 
184 #[test]
test_err_dbg()185 fn test_err_dbg() {
186     let span = expect::span().named("err_dbg");
187     let (subscriber, handle) = subscriber::mock()
188         .new_span(span.clone())
189         .enter(span.clone())
190         .event(
191             expect::event().at_level(Level::ERROR).with_fields(
192                 expect::field("error")
193                     // use the actual error value that will be emitted, so
194                     // that this test doesn't break if the standard library
195                     // changes the `fmt::Debug` output from the error type
196                     // in the future.
197                     .with_value(&tracing::field::debug(u8::try_from(1234).unwrap_err())),
198             ),
199         )
200         .exit(span.clone())
201         .drop_span(span)
202         .only()
203         .run_with_handle();
204     with_default(subscriber, || err_dbg().ok());
205     handle.assert_finished();
206 }
207 
208 #[test]
test_err_display_default()209 fn test_err_display_default() {
210     let span = expect::span().named("err");
211     let (subscriber, handle) = subscriber::mock()
212         .new_span(span.clone())
213         .enter(span.clone())
214         .event(
215             expect::event().at_level(Level::ERROR).with_fields(
216                 expect::field("error")
217                     // by default, errors will be emitted with their display values
218                     .with_value(&tracing::field::display(u8::try_from(1234).unwrap_err())),
219             ),
220         )
221         .exit(span.clone())
222         .drop_span(span)
223         .only()
224         .run_with_handle();
225     with_default(subscriber, || err().ok());
226     handle.assert_finished();
227 }
228 
229 #[test]
test_err_custom_target()230 fn test_err_custom_target() {
231     let filter: EnvFilter = "my_target=error".parse().expect("filter should parse");
232     let span = expect::span().named("error_span").with_target("my_target");
233 
234     let (subscriber, handle) = subscriber::mock()
235         .new_span(span.clone())
236         .enter(span.clone())
237         .event(
238             expect::event()
239                 .at_level(Level::ERROR)
240                 .with_target("my_target"),
241         )
242         .exit(span.clone())
243         .drop_span(span)
244         .only()
245         .run_with_handle();
246 
247     let subscriber = subscriber.with(filter);
248 
249     with_default(subscriber, || {
250         let error_span = tracing::error_span!(target: "my_target", "error_span");
251 
252         {
253             let _enter = error_span.enter();
254             tracing::error!(target: "my_target", "This should display")
255         }
256     });
257     handle.assert_finished();
258 }
259 
260 #[instrument(err(level = "info"))]
err_info() -> Result<u8, TryFromIntError>261 fn err_info() -> Result<u8, TryFromIntError> {
262     u8::try_from(1234)
263 }
264 
265 #[test]
test_err_info()266 fn test_err_info() {
267     let span = expect::span().named("err_info");
268     let (subscriber, handle) = subscriber::mock()
269         .new_span(span.clone())
270         .enter(span.clone())
271         .event(expect::event().at_level(Level::INFO))
272         .exit(span.clone())
273         .drop_span(span)
274         .only()
275         .run_with_handle();
276     with_default(subscriber, || err_info().ok());
277     handle.assert_finished();
278 }
279 
280 #[instrument(err(Debug, level = "info"))]
err_dbg_info() -> Result<u8, TryFromIntError>281 fn err_dbg_info() -> Result<u8, TryFromIntError> {
282     u8::try_from(1234)
283 }
284 
285 #[test]
test_err_dbg_info()286 fn test_err_dbg_info() {
287     let span = expect::span().named("err_dbg_info");
288     let (subscriber, handle) = subscriber::mock()
289         .new_span(span.clone())
290         .enter(span.clone())
291         .event(
292             expect::event().at_level(Level::INFO).with_fields(
293                 expect::field("error")
294                     // use the actual error value that will be emitted, so
295                     // that this test doesn't break if the standard library
296                     // changes the `fmt::Debug` output from the error type
297                     // in the future.
298                     .with_value(&tracing::field::debug(u8::try_from(1234).unwrap_err())),
299             ),
300         )
301         .exit(span.clone())
302         .drop_span(span)
303         .only()
304         .run_with_handle();
305     with_default(subscriber, || err_dbg_info().ok());
306     handle.assert_finished();
307 }
308 
309 #[instrument(level = "warn", err(level = "info"))]
err_warn_info() -> Result<u8, TryFromIntError>310 fn err_warn_info() -> Result<u8, TryFromIntError> {
311     u8::try_from(1234)
312 }
313 
314 #[test]
test_err_warn_info()315 fn test_err_warn_info() {
316     let span = expect::span().named("err_warn_info").at_level(Level::WARN);
317     let (subscriber, handle) = subscriber::mock()
318         .new_span(span.clone())
319         .enter(span.clone())
320         .event(expect::event().at_level(Level::INFO))
321         .exit(span.clone())
322         .drop_span(span)
323         .only()
324         .run_with_handle();
325     with_default(subscriber, || err_warn_info().ok());
326     handle.assert_finished();
327 }
328