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)] |
12 | fn err() -> Result<u8, TryFromIntError> { |
13 | u8::try_from(1234) |
14 | } |
15 | |
16 | #[instrument (err)] |
17 | fn err_suspicious_else() -> Result<u8, TryFromIntError> { |
18 | {} |
19 | u8::try_from(1234) |
20 | } |
21 | |
22 | #[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)] |
38 | fn err_early_return() -> Result<u8, TryFromIntError> { |
39 | u8::try_from(1234)?; |
40 | Ok(5) |
41 | } |
42 | |
43 | #[test] |
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)] |
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] |
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)] |
93 | fn err_mut(out: &mut u8) -> Result<(), TryFromIntError> { |
94 | *out = u8::try_from(1234)?; |
95 | Ok(()) |
96 | } |
97 | |
98 | #[test] |
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)] |
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] |
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] |
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))] |
180 | fn err_dbg() -> Result<u8, TryFromIntError> { |
181 | u8::try_from(1234) |
182 | } |
183 | |
184 | #[test] |
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] |
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] |
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" ))] |
261 | fn err_info() -> Result<u8, TryFromIntError> { |
262 | u8::try_from(1234) |
263 | } |
264 | |
265 | #[test] |
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" ))] |
281 | fn err_dbg_info() -> Result<u8, TryFromIntError> { |
282 | u8::try_from(1234) |
283 | } |
284 | |
285 | #[test] |
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" ))] |
310 | fn err_warn_info() -> Result<u8, TryFromIntError> { |
311 | u8::try_from(1234) |
312 | } |
313 | |
314 | #[test] |
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 | |