1use tracing::subscriber::with_default;
2use tracing::Level;
3use tracing_attributes::instrument;
4use tracing_mock::*;
5use tracing_subscriber::filter::EnvFilter;
6use tracing_subscriber::layer::SubscriberExt;
7
8use std::convert::TryFrom;
9use std::num::TryFromIntError;
10
11#[instrument(err)]
12fn err() -> Result<u8, TryFromIntError> {
13 u8::try_from(1234)
14}
15
16#[instrument(err)]
17fn err_suspicious_else() -> Result<u8, TryFromIntError> {
18 {}
19 u8::try_from(1234)
20}
21
22#[test]
23fn 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)]
38fn err_early_return() -> Result<u8, TryFromIntError> {
39 u8::try_from(1234)?;
40 Ok(5)
41}
42
43#[test]
44fn 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)]
59async 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]
67fn 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)]
93fn err_mut(out: &mut u8) -> Result<(), TryFromIntError> {
94 *out = u8::try_from(1234)?;
95 Ok(())
96}
97
98#[test]
99fn 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)]
114async 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]
123fn 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]
149fn 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))]
180fn err_dbg() -> Result<u8, TryFromIntError> {
181 u8::try_from(1234)
182}
183
184#[test]
185fn 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]
209fn 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]
230fn 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"))]
261fn err_info() -> Result<u8, TryFromIntError> {
262 u8::try_from(1234)
263}
264
265#[test]
266fn 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"))]
281fn err_dbg_info() -> Result<u8, TryFromIntError> {
282 u8::try_from(1234)
283}
284
285#[test]
286fn 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"))]
310fn err_warn_info() -> Result<u8, TryFromIntError> {
311 u8::try_from(1234)
312}
313
314#[test]
315fn 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