1 | use crate::{ |
2 | field::RecordFields, |
3 | fmt::{format, FormatEvent, FormatFields, MakeWriter, TestWriter}, |
4 | layer::{self, Context}, |
5 | registry::{self, LookupSpan, SpanRef}, |
6 | }; |
7 | use format::{FmtSpan, TimingDisplay}; |
8 | use std::{ |
9 | any::TypeId, cell::RefCell, env, fmt, io, marker::PhantomData, ops::Deref, time::Instant, |
10 | }; |
11 | use tracing_core::{ |
12 | field, |
13 | span::{Attributes, Current, Id, Record}, |
14 | Event, Metadata, Subscriber, |
15 | }; |
16 | |
17 | /// A [`Layer`] that logs formatted representations of `tracing` events. |
18 | /// |
19 | /// ## Examples |
20 | /// |
21 | /// Constructing a layer with the default configuration: |
22 | /// |
23 | /// ```rust |
24 | /// use tracing_subscriber::{fmt, Registry}; |
25 | /// use tracing_subscriber::prelude::*; |
26 | /// |
27 | /// let subscriber = Registry::default() |
28 | /// .with(fmt::Layer::default()); |
29 | /// |
30 | /// tracing::subscriber::set_global_default(subscriber).unwrap(); |
31 | /// ``` |
32 | /// |
33 | /// Overriding the layer's behavior: |
34 | /// |
35 | /// ```rust |
36 | /// use tracing_subscriber::{fmt, Registry}; |
37 | /// use tracing_subscriber::prelude::*; |
38 | /// |
39 | /// let fmt_layer = fmt::layer() |
40 | /// .with_target(false) // don't include event targets when logging |
41 | /// .with_level(false); // don't include event levels when logging |
42 | /// |
43 | /// let subscriber = Registry::default().with(fmt_layer); |
44 | /// # tracing::subscriber::set_global_default(subscriber).unwrap(); |
45 | /// ``` |
46 | /// |
47 | /// Setting a custom event formatter: |
48 | /// |
49 | /// ```rust |
50 | /// use tracing_subscriber::fmt::{self, format, time}; |
51 | /// use tracing_subscriber::prelude::*; |
52 | /// |
53 | /// let fmt = format().with_timer(time::Uptime::default()); |
54 | /// let fmt_layer = fmt::layer() |
55 | /// .event_format(fmt) |
56 | /// .with_target(false); |
57 | /// # let subscriber = fmt_layer.with_subscriber(tracing_subscriber::registry::Registry::default()); |
58 | /// # tracing::subscriber::set_global_default(subscriber).unwrap(); |
59 | /// ``` |
60 | /// |
61 | /// [`Layer`]: super::layer::Layer |
62 | #[cfg_attr (docsrs, doc(cfg(all(feature = "fmt" , feature = "std" ))))] |
63 | #[derive(Debug)] |
64 | pub struct Layer< |
65 | S, |
66 | N = format::DefaultFields, |
67 | E = format::Format<format::Full>, |
68 | W = fn() -> io::Stdout, |
69 | > { |
70 | make_writer: W, |
71 | fmt_fields: N, |
72 | fmt_event: E, |
73 | fmt_span: format::FmtSpanConfig, |
74 | is_ansi: bool, |
75 | log_internal_errors: bool, |
76 | _inner: PhantomData<fn(S)>, |
77 | } |
78 | |
79 | impl<S> Layer<S> { |
80 | /// Returns a new [`Layer`][self::Layer] with the default configuration. |
81 | pub fn new() -> Self { |
82 | Self::default() |
83 | } |
84 | } |
85 | |
86 | // This needs to be a seperate impl block because they place different bounds on the type parameters. |
87 | impl<S, N, E, W> Layer<S, N, E, W> |
88 | where |
89 | S: Subscriber + for<'a> LookupSpan<'a>, |
90 | N: for<'writer> FormatFields<'writer> + 'static, |
91 | W: for<'writer> MakeWriter<'writer> + 'static, |
92 | { |
93 | /// Sets the [event formatter][`FormatEvent`] that the layer being built will |
94 | /// use to format events. |
95 | /// |
96 | /// The event formatter may be any type implementing the [`FormatEvent`] |
97 | /// trait, which is implemented for all functions taking a [`FmtContext`], a |
98 | /// [`Writer`], and an [`Event`]. |
99 | /// |
100 | /// # Examples |
101 | /// |
102 | /// Setting a type implementing [`FormatEvent`] as the formatter: |
103 | /// ```rust |
104 | /// use tracing_subscriber::fmt::{self, format}; |
105 | /// |
106 | /// let layer = fmt::layer() |
107 | /// .event_format(format().compact()); |
108 | /// # // this is necessary for type inference. |
109 | /// # use tracing_subscriber::Layer as _; |
110 | /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); |
111 | /// ``` |
112 | /// [`FormatEvent`]: format::FormatEvent |
113 | /// [`Event`]: tracing::Event |
114 | /// [`Writer`]: format::Writer |
115 | pub fn event_format<E2>(self, e: E2) -> Layer<S, N, E2, W> |
116 | where |
117 | E2: FormatEvent<S, N> + 'static, |
118 | { |
119 | Layer { |
120 | fmt_fields: self.fmt_fields, |
121 | fmt_event: e, |
122 | fmt_span: self.fmt_span, |
123 | make_writer: self.make_writer, |
124 | is_ansi: self.is_ansi, |
125 | log_internal_errors: self.log_internal_errors, |
126 | _inner: self._inner, |
127 | } |
128 | } |
129 | |
130 | /// Updates the event formatter by applying a function to the existing event formatter. |
131 | /// |
132 | /// This sets the event formatter that the layer being built will use to record fields. |
133 | /// |
134 | /// # Examples |
135 | /// |
136 | /// Updating an event formatter: |
137 | /// |
138 | /// ```rust |
139 | /// let layer = tracing_subscriber::fmt::layer() |
140 | /// .map_event_format(|e| e.compact()); |
141 | /// # // this is necessary for type inference. |
142 | /// # use tracing_subscriber::Layer as _; |
143 | /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); |
144 | /// ``` |
145 | pub fn map_event_format<E2>(self, f: impl FnOnce(E) -> E2) -> Layer<S, N, E2, W> |
146 | where |
147 | E2: FormatEvent<S, N> + 'static, |
148 | { |
149 | Layer { |
150 | fmt_fields: self.fmt_fields, |
151 | fmt_event: f(self.fmt_event), |
152 | fmt_span: self.fmt_span, |
153 | make_writer: self.make_writer, |
154 | is_ansi: self.is_ansi, |
155 | log_internal_errors: self.log_internal_errors, |
156 | _inner: self._inner, |
157 | } |
158 | } |
159 | } |
160 | |
161 | // This needs to be a seperate impl block because they place different bounds on the type parameters. |
162 | impl<S, N, E, W> Layer<S, N, E, W> { |
163 | /// Sets the [`MakeWriter`] that the layer being built will use to write events. |
164 | /// |
165 | /// # Examples |
166 | /// |
167 | /// Using `stderr` rather than `stdout`: |
168 | /// |
169 | /// ```rust |
170 | /// use std::io; |
171 | /// use tracing_subscriber::fmt; |
172 | /// |
173 | /// let layer = fmt::layer() |
174 | /// .with_writer(io::stderr); |
175 | /// # // this is necessary for type inference. |
176 | /// # use tracing_subscriber::Layer as _; |
177 | /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); |
178 | /// ``` |
179 | pub fn with_writer<W2>(self, make_writer: W2) -> Layer<S, N, E, W2> |
180 | where |
181 | W2: for<'writer> MakeWriter<'writer> + 'static, |
182 | { |
183 | Layer { |
184 | fmt_fields: self.fmt_fields, |
185 | fmt_event: self.fmt_event, |
186 | fmt_span: self.fmt_span, |
187 | is_ansi: self.is_ansi, |
188 | log_internal_errors: self.log_internal_errors, |
189 | make_writer, |
190 | _inner: self._inner, |
191 | } |
192 | } |
193 | |
194 | /// Borrows the [writer] for this [`Layer`]. |
195 | /// |
196 | /// [writer]: MakeWriter |
197 | pub fn writer(&self) -> &W { |
198 | &self.make_writer |
199 | } |
200 | |
201 | /// Mutably borrows the [writer] for this [`Layer`]. |
202 | /// |
203 | /// This method is primarily expected to be used with the |
204 | /// [`reload::Handle::modify`](crate::reload::Handle::modify) method. |
205 | /// |
206 | /// # Examples |
207 | /// |
208 | /// ``` |
209 | /// # use tracing::info; |
210 | /// # use tracing_subscriber::{fmt,reload,Registry,prelude::*}; |
211 | /// # fn non_blocking<T: std::io::Write>(writer: T) -> (fn() -> std::io::Stdout) { |
212 | /// # std::io::stdout |
213 | /// # } |
214 | /// # fn main() { |
215 | /// let layer = fmt::layer().with_writer(non_blocking(std::io::stderr())); |
216 | /// let (layer, reload_handle) = reload::Layer::new(layer); |
217 | /// # |
218 | /// # // specifying the Registry type is required |
219 | /// # let _: &reload::Handle<fmt::Layer<Registry, _, _, _>, Registry> = &reload_handle; |
220 | /// # |
221 | /// info!("This will be logged to stderr" ); |
222 | /// reload_handle.modify(|layer| *layer.writer_mut() = non_blocking(std::io::stdout())); |
223 | /// info!("This will be logged to stdout" ); |
224 | /// # } |
225 | /// ``` |
226 | /// |
227 | /// [writer]: MakeWriter |
228 | pub fn writer_mut(&mut self) -> &mut W { |
229 | &mut self.make_writer |
230 | } |
231 | |
232 | /// Sets whether this layer should use ANSI terminal formatting |
233 | /// escape codes (such as colors). |
234 | /// |
235 | /// This method is primarily expected to be used with the |
236 | /// [`reload::Handle::modify`](crate::reload::Handle::modify) method when changing |
237 | /// the writer. |
238 | #[cfg (feature = "ansi" )] |
239 | #[cfg_attr (docsrs, doc(cfg(feature = "ansi" )))] |
240 | pub fn set_ansi(&mut self, ansi: bool) { |
241 | self.is_ansi = ansi; |
242 | } |
243 | |
244 | /// Configures the layer to support [`libtest`'s output capturing][capturing] when used in |
245 | /// unit tests. |
246 | /// |
247 | /// See [`TestWriter`] for additional details. |
248 | /// |
249 | /// # Examples |
250 | /// |
251 | /// Using [`TestWriter`] to let `cargo test` capture test output: |
252 | /// |
253 | /// ```rust |
254 | /// use std::io; |
255 | /// use tracing_subscriber::fmt; |
256 | /// |
257 | /// let layer = fmt::layer() |
258 | /// .with_test_writer(); |
259 | /// # // this is necessary for type inference. |
260 | /// # use tracing_subscriber::Layer as _; |
261 | /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); |
262 | /// ``` |
263 | /// [capturing]: |
264 | /// https://doc.rust-lang.org/book/ch11-02-running-tests.html#showing-function-output |
265 | /// [`TestWriter`]: super::writer::TestWriter |
266 | pub fn with_test_writer(self) -> Layer<S, N, E, TestWriter> { |
267 | Layer { |
268 | fmt_fields: self.fmt_fields, |
269 | fmt_event: self.fmt_event, |
270 | fmt_span: self.fmt_span, |
271 | is_ansi: self.is_ansi, |
272 | log_internal_errors: self.log_internal_errors, |
273 | make_writer: TestWriter::default(), |
274 | _inner: self._inner, |
275 | } |
276 | } |
277 | |
278 | /// Sets whether or not the formatter emits ANSI terminal escape codes |
279 | /// for colors and other text formatting. |
280 | /// |
281 | /// When the "ansi" crate feature flag is enabled, ANSI colors are enabled |
282 | /// by default unless the [`NO_COLOR`] environment variable is set to |
283 | /// a non-empty value. If the [`NO_COLOR`] environment variable is set to |
284 | /// any non-empty value, then ANSI colors will be suppressed by default. |
285 | /// The [`with_ansi`] and [`set_ansi`] methods can be used to forcibly |
286 | /// enable ANSI colors, overriding any [`NO_COLOR`] environment variable. |
287 | /// |
288 | /// [`NO_COLOR`]: https://no-color.org/ |
289 | /// |
290 | /// Enabling ANSI escapes (calling `with_ansi(true)`) requires the "ansi" |
291 | /// crate feature flag. Calling `with_ansi(true)` without the "ansi" |
292 | /// feature flag enabled will panic if debug assertions are enabled, or |
293 | /// print a warning otherwise. |
294 | /// |
295 | /// This method itself is still available without the feature flag. This |
296 | /// is to allow ANSI escape codes to be explicitly *disabled* without |
297 | /// having to opt-in to the dependencies required to emit ANSI formatting. |
298 | /// This way, code which constructs a formatter that should never emit |
299 | /// ANSI escape codes can ensure that they are not used, regardless of |
300 | /// whether or not other crates in the dependency graph enable the "ansi" |
301 | /// feature flag. |
302 | /// |
303 | /// [`with_ansi`]: Subscriber::with_ansi |
304 | /// [`set_ansi`]: Subscriber::set_ansi |
305 | pub fn with_ansi(self, ansi: bool) -> Self { |
306 | #[cfg (not(feature = "ansi" ))] |
307 | if ansi { |
308 | const ERROR: &str = |
309 | "tracing-subscriber: the `ansi` crate feature is required to enable ANSI terminal colors" ; |
310 | #[cfg (debug_assertions)] |
311 | panic!("{}" , ERROR); |
312 | #[cfg (not(debug_assertions))] |
313 | eprintln!("{}" , ERROR); |
314 | } |
315 | |
316 | Self { |
317 | is_ansi: ansi, |
318 | ..self |
319 | } |
320 | } |
321 | |
322 | /// Sets whether to write errors from [`FormatEvent`] to the writer. |
323 | /// Defaults to true. |
324 | /// |
325 | /// By default, `fmt::Layer` will write any `FormatEvent`-internal errors to |
326 | /// the writer. These errors are unlikely and will only occur if there is a |
327 | /// bug in the `FormatEvent` implementation or its dependencies. |
328 | /// |
329 | /// If writing to the writer fails, the error message is printed to stderr |
330 | /// as a fallback. |
331 | /// |
332 | /// [`FormatEvent`]: crate::fmt::FormatEvent |
333 | pub fn log_internal_errors(self, log_internal_errors: bool) -> Self { |
334 | Self { |
335 | log_internal_errors, |
336 | ..self |
337 | } |
338 | } |
339 | |
340 | /// Updates the [`MakeWriter`] by applying a function to the existing [`MakeWriter`]. |
341 | /// |
342 | /// This sets the [`MakeWriter`] that the layer being built will use to write events. |
343 | /// |
344 | /// # Examples |
345 | /// |
346 | /// Redirect output to stderr if level is <= WARN: |
347 | /// |
348 | /// ```rust |
349 | /// use tracing::Level; |
350 | /// use tracing_subscriber::fmt::{self, writer::MakeWriterExt}; |
351 | /// |
352 | /// let stderr = std::io::stderr.with_max_level(Level::WARN); |
353 | /// let layer = fmt::layer() |
354 | /// .map_writer(move |w| stderr.or_else(w)); |
355 | /// # // this is necessary for type inference. |
356 | /// # use tracing_subscriber::Layer as _; |
357 | /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); |
358 | /// ``` |
359 | pub fn map_writer<W2>(self, f: impl FnOnce(W) -> W2) -> Layer<S, N, E, W2> |
360 | where |
361 | W2: for<'writer> MakeWriter<'writer> + 'static, |
362 | { |
363 | Layer { |
364 | fmt_fields: self.fmt_fields, |
365 | fmt_event: self.fmt_event, |
366 | fmt_span: self.fmt_span, |
367 | is_ansi: self.is_ansi, |
368 | log_internal_errors: self.log_internal_errors, |
369 | make_writer: f(self.make_writer), |
370 | _inner: self._inner, |
371 | } |
372 | } |
373 | } |
374 | |
375 | impl<S, N, L, T, W> Layer<S, N, format::Format<L, T>, W> |
376 | where |
377 | N: for<'writer> FormatFields<'writer> + 'static, |
378 | { |
379 | /// Use the given [`timer`] for span and event timestamps. |
380 | /// |
381 | /// See the [`time` module] for the provided timer implementations. |
382 | /// |
383 | /// Note that using the `"time`"" feature flag enables the |
384 | /// additional time formatters [`UtcTime`] and [`LocalTime`], which use the |
385 | /// [`time` crate] to provide more sophisticated timestamp formatting |
386 | /// options. |
387 | /// |
388 | /// [`timer`]: super::time::FormatTime |
389 | /// [`time` module]: mod@super::time |
390 | /// [`UtcTime`]: super::time::UtcTime |
391 | /// [`LocalTime`]: super::time::LocalTime |
392 | /// [`time` crate]: https://docs.rs/time/0.3 |
393 | pub fn with_timer<T2>(self, timer: T2) -> Layer<S, N, format::Format<L, T2>, W> { |
394 | Layer { |
395 | fmt_event: self.fmt_event.with_timer(timer), |
396 | fmt_fields: self.fmt_fields, |
397 | fmt_span: self.fmt_span, |
398 | make_writer: self.make_writer, |
399 | is_ansi: self.is_ansi, |
400 | log_internal_errors: self.log_internal_errors, |
401 | _inner: self._inner, |
402 | } |
403 | } |
404 | |
405 | /// Do not emit timestamps with spans and event. |
406 | pub fn without_time(self) -> Layer<S, N, format::Format<L, ()>, W> { |
407 | Layer { |
408 | fmt_event: self.fmt_event.without_time(), |
409 | fmt_fields: self.fmt_fields, |
410 | fmt_span: self.fmt_span.without_time(), |
411 | make_writer: self.make_writer, |
412 | is_ansi: self.is_ansi, |
413 | log_internal_errors: self.log_internal_errors, |
414 | _inner: self._inner, |
415 | } |
416 | } |
417 | |
418 | /// Configures how synthesized events are emitted at points in the [span |
419 | /// lifecycle][lifecycle]. |
420 | /// |
421 | /// The following options are available: |
422 | /// |
423 | /// - `FmtSpan::NONE`: No events will be synthesized when spans are |
424 | /// created, entered, exited, or closed. Data from spans will still be |
425 | /// included as the context for formatted events. This is the default. |
426 | /// - `FmtSpan::NEW`: An event will be synthesized when spans are created. |
427 | /// - `FmtSpan::ENTER`: An event will be synthesized when spans are entered. |
428 | /// - `FmtSpan::EXIT`: An event will be synthesized when spans are exited. |
429 | /// - `FmtSpan::CLOSE`: An event will be synthesized when a span closes. If |
430 | /// [timestamps are enabled][time] for this formatter, the generated |
431 | /// event will contain fields with the span's _busy time_ (the total |
432 | /// time for which it was entered) and _idle time_ (the total time that |
433 | /// the span existed but was not entered). |
434 | /// - `FmtSpan::ACTIVE`: Events will be synthesized when spans are entered |
435 | /// or exited. |
436 | /// - `FmtSpan::FULL`: Events will be synthesized whenever a span is |
437 | /// created, entered, exited, or closed. If timestamps are enabled, the |
438 | /// close event will contain the span's busy and idle time, as |
439 | /// described above. |
440 | /// |
441 | /// The options can be enabled in any combination. For instance, the following |
442 | /// will synthesize events whenever spans are created and closed: |
443 | /// |
444 | /// ```rust |
445 | /// use tracing_subscriber::fmt; |
446 | /// use tracing_subscriber::fmt::format::FmtSpan; |
447 | /// |
448 | /// let subscriber = fmt() |
449 | /// .with_span_events(FmtSpan::NEW | FmtSpan::CLOSE) |
450 | /// .finish(); |
451 | /// ``` |
452 | /// |
453 | /// Note that the generated events will only be part of the log output by |
454 | /// this formatter; they will not be recorded by other `Subscriber`s or by |
455 | /// `Layer`s added to this subscriber. |
456 | /// |
457 | /// [lifecycle]: https://docs.rs/tracing/latest/tracing/span/index.html#the-span-lifecycle |
458 | /// [time]: Layer::without_time() |
459 | pub fn with_span_events(self, kind: FmtSpan) -> Self { |
460 | Layer { |
461 | fmt_span: self.fmt_span.with_kind(kind), |
462 | ..self |
463 | } |
464 | } |
465 | |
466 | /// Sets whether or not an event's target is displayed. |
467 | pub fn with_target(self, display_target: bool) -> Layer<S, N, format::Format<L, T>, W> { |
468 | Layer { |
469 | fmt_event: self.fmt_event.with_target(display_target), |
470 | ..self |
471 | } |
472 | } |
473 | /// Sets whether or not an event's [source code file path][file] is |
474 | /// displayed. |
475 | /// |
476 | /// [file]: tracing_core::Metadata::file |
477 | pub fn with_file(self, display_filename: bool) -> Layer<S, N, format::Format<L, T>, W> { |
478 | Layer { |
479 | fmt_event: self.fmt_event.with_file(display_filename), |
480 | ..self |
481 | } |
482 | } |
483 | |
484 | /// Sets whether or not an event's [source code line number][line] is |
485 | /// displayed. |
486 | /// |
487 | /// [line]: tracing_core::Metadata::line |
488 | pub fn with_line_number( |
489 | self, |
490 | display_line_number: bool, |
491 | ) -> Layer<S, N, format::Format<L, T>, W> { |
492 | Layer { |
493 | fmt_event: self.fmt_event.with_line_number(display_line_number), |
494 | ..self |
495 | } |
496 | } |
497 | |
498 | /// Sets whether or not an event's level is displayed. |
499 | pub fn with_level(self, display_level: bool) -> Layer<S, N, format::Format<L, T>, W> { |
500 | Layer { |
501 | fmt_event: self.fmt_event.with_level(display_level), |
502 | ..self |
503 | } |
504 | } |
505 | |
506 | /// Sets whether or not the [thread ID] of the current thread is displayed |
507 | /// when formatting events. |
508 | /// |
509 | /// [thread ID]: std::thread::ThreadId |
510 | pub fn with_thread_ids(self, display_thread_ids: bool) -> Layer<S, N, format::Format<L, T>, W> { |
511 | Layer { |
512 | fmt_event: self.fmt_event.with_thread_ids(display_thread_ids), |
513 | ..self |
514 | } |
515 | } |
516 | |
517 | /// Sets whether or not the [name] of the current thread is displayed |
518 | /// when formatting events. |
519 | /// |
520 | /// [name]: std::thread#naming-threads |
521 | pub fn with_thread_names( |
522 | self, |
523 | display_thread_names: bool, |
524 | ) -> Layer<S, N, format::Format<L, T>, W> { |
525 | Layer { |
526 | fmt_event: self.fmt_event.with_thread_names(display_thread_names), |
527 | ..self |
528 | } |
529 | } |
530 | |
531 | /// Sets the layer being built to use a [less verbose formatter][super::format::Compact]. |
532 | pub fn compact(self) -> Layer<S, N, format::Format<format::Compact, T>, W> |
533 | where |
534 | N: for<'writer> FormatFields<'writer> + 'static, |
535 | { |
536 | Layer { |
537 | fmt_event: self.fmt_event.compact(), |
538 | fmt_fields: self.fmt_fields, |
539 | fmt_span: self.fmt_span, |
540 | make_writer: self.make_writer, |
541 | is_ansi: self.is_ansi, |
542 | log_internal_errors: self.log_internal_errors, |
543 | _inner: self._inner, |
544 | } |
545 | } |
546 | |
547 | /// Sets the layer being built to use an [excessively pretty, human-readable formatter](crate::fmt::format::Pretty). |
548 | #[cfg (feature = "ansi" )] |
549 | #[cfg_attr (docsrs, doc(cfg(feature = "ansi" )))] |
550 | pub fn pretty(self) -> Layer<S, format::Pretty, format::Format<format::Pretty, T>, W> { |
551 | Layer { |
552 | fmt_event: self.fmt_event.pretty(), |
553 | fmt_fields: format::Pretty::default(), |
554 | fmt_span: self.fmt_span, |
555 | make_writer: self.make_writer, |
556 | is_ansi: self.is_ansi, |
557 | log_internal_errors: self.log_internal_errors, |
558 | _inner: self._inner, |
559 | } |
560 | } |
561 | |
562 | /// Sets the layer being built to use a [JSON formatter][super::format::Json]. |
563 | /// |
564 | /// The full format includes fields from all entered spans. |
565 | /// |
566 | /// # Example Output |
567 | /// |
568 | /// ```ignore,json |
569 | /// {"timestamp":"Feb 20 11:28:15.096","level":"INFO","target":"mycrate","fields":{"message":"some message", "key": "value"}} |
570 | /// ``` |
571 | /// |
572 | /// # Options |
573 | /// |
574 | /// - [`Layer::flatten_event`] can be used to enable flattening event fields into the root |
575 | /// object. |
576 | /// |
577 | /// [`Layer::flatten_event`]: Layer::flatten_event() |
578 | #[cfg (feature = "json" )] |
579 | #[cfg_attr (docsrs, doc(cfg(feature = "json" )))] |
580 | pub fn json(self) -> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { |
581 | Layer { |
582 | fmt_event: self.fmt_event.json(), |
583 | fmt_fields: format::JsonFields::new(), |
584 | fmt_span: self.fmt_span, |
585 | make_writer: self.make_writer, |
586 | // always disable ANSI escapes in JSON mode! |
587 | is_ansi: false, |
588 | log_internal_errors: self.log_internal_errors, |
589 | _inner: self._inner, |
590 | } |
591 | } |
592 | } |
593 | |
594 | #[cfg (feature = "json" )] |
595 | #[cfg_attr (docsrs, doc(cfg(feature = "json" )))] |
596 | impl<S, T, W> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { |
597 | /// Sets the JSON layer being built to flatten event metadata. |
598 | /// |
599 | /// See [`format::Json`][super::format::Json] |
600 | pub fn flatten_event( |
601 | self, |
602 | flatten_event: bool, |
603 | ) -> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { |
604 | Layer { |
605 | fmt_event: self.fmt_event.flatten_event(flatten_event), |
606 | fmt_fields: format::JsonFields::new(), |
607 | ..self |
608 | } |
609 | } |
610 | |
611 | /// Sets whether or not the formatter will include the current span in |
612 | /// formatted events. |
613 | /// |
614 | /// See [`format::Json`][super::format::Json] |
615 | pub fn with_current_span( |
616 | self, |
617 | display_current_span: bool, |
618 | ) -> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { |
619 | Layer { |
620 | fmt_event: self.fmt_event.with_current_span(display_current_span), |
621 | fmt_fields: format::JsonFields::new(), |
622 | ..self |
623 | } |
624 | } |
625 | |
626 | /// Sets whether or not the formatter will include a list (from root to leaf) |
627 | /// of all currently entered spans in formatted events. |
628 | /// |
629 | /// See [`format::Json`][super::format::Json] |
630 | pub fn with_span_list( |
631 | self, |
632 | display_span_list: bool, |
633 | ) -> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> { |
634 | Layer { |
635 | fmt_event: self.fmt_event.with_span_list(display_span_list), |
636 | fmt_fields: format::JsonFields::new(), |
637 | ..self |
638 | } |
639 | } |
640 | } |
641 | |
642 | impl<S, N, E, W> Layer<S, N, E, W> { |
643 | /// Sets the field formatter that the layer being built will use to record |
644 | /// fields. |
645 | pub fn fmt_fields<N2>(self, fmt_fields: N2) -> Layer<S, N2, E, W> |
646 | where |
647 | N2: for<'writer> FormatFields<'writer> + 'static, |
648 | { |
649 | Layer { |
650 | fmt_event: self.fmt_event, |
651 | fmt_fields, |
652 | fmt_span: self.fmt_span, |
653 | make_writer: self.make_writer, |
654 | is_ansi: self.is_ansi, |
655 | log_internal_errors: self.log_internal_errors, |
656 | _inner: self._inner, |
657 | } |
658 | } |
659 | |
660 | /// Updates the field formatter by applying a function to the existing field formatter. |
661 | /// |
662 | /// This sets the field formatter that the layer being built will use to record fields. |
663 | /// |
664 | /// # Examples |
665 | /// |
666 | /// Updating a field formatter: |
667 | /// |
668 | /// ```rust |
669 | /// use tracing_subscriber::field::MakeExt; |
670 | /// let layer = tracing_subscriber::fmt::layer() |
671 | /// .map_fmt_fields(|f| f.debug_alt()); |
672 | /// # // this is necessary for type inference. |
673 | /// # use tracing_subscriber::Layer as _; |
674 | /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default()); |
675 | /// ``` |
676 | pub fn map_fmt_fields<N2>(self, f: impl FnOnce(N) -> N2) -> Layer<S, N2, E, W> |
677 | where |
678 | N2: for<'writer> FormatFields<'writer> + 'static, |
679 | { |
680 | Layer { |
681 | fmt_event: self.fmt_event, |
682 | fmt_fields: f(self.fmt_fields), |
683 | fmt_span: self.fmt_span, |
684 | make_writer: self.make_writer, |
685 | is_ansi: self.is_ansi, |
686 | log_internal_errors: self.log_internal_errors, |
687 | _inner: self._inner, |
688 | } |
689 | } |
690 | } |
691 | |
692 | impl<S> Default for Layer<S> { |
693 | fn default() -> Self { |
694 | // only enable ANSI when the feature is enabled, and the NO_COLOR |
695 | // environment variable is unset or empty. |
696 | let ansi = cfg!(feature = "ansi" ) && env::var("NO_COLOR" ).map_or(true, |v| v.is_empty()); |
697 | |
698 | Layer { |
699 | fmt_fields: format::DefaultFields::default(), |
700 | fmt_event: format::Format::default(), |
701 | fmt_span: format::FmtSpanConfig::default(), |
702 | make_writer: io::stdout, |
703 | is_ansi: ansi, |
704 | log_internal_errors: false, |
705 | _inner: PhantomData, |
706 | } |
707 | } |
708 | } |
709 | |
710 | impl<S, N, E, W> Layer<S, N, E, W> |
711 | where |
712 | S: Subscriber + for<'a> LookupSpan<'a>, |
713 | N: for<'writer> FormatFields<'writer> + 'static, |
714 | E: FormatEvent<S, N> + 'static, |
715 | W: for<'writer> MakeWriter<'writer> + 'static, |
716 | { |
717 | #[inline ] |
718 | fn make_ctx<'a>(&'a self, ctx: Context<'a, S>, event: &'a Event<'a>) -> FmtContext<'a, S, N> { |
719 | FmtContext { |
720 | ctx, |
721 | fmt_fields: &self.fmt_fields, |
722 | event, |
723 | } |
724 | } |
725 | } |
726 | |
727 | /// A formatted representation of a span's fields stored in its [extensions]. |
728 | /// |
729 | /// Because `FormattedFields` is generic over the type of the formatter that |
730 | /// produced it, multiple versions of a span's formatted fields can be stored in |
731 | /// the [`Extensions`][extensions] type-map. This means that when multiple |
732 | /// formatters are in use, each can store its own formatted representation |
733 | /// without conflicting. |
734 | /// |
735 | /// [extensions]: crate::registry::Extensions |
736 | #[derive(Default)] |
737 | pub struct FormattedFields<E: ?Sized> { |
738 | _format_fields: PhantomData<fn(E)>, |
739 | was_ansi: bool, |
740 | /// The formatted fields of a span. |
741 | pub fields: String, |
742 | } |
743 | |
744 | impl<E: ?Sized> FormattedFields<E> { |
745 | /// Returns a new `FormattedFields`. |
746 | pub fn new(fields: String) -> Self { |
747 | Self { |
748 | fields, |
749 | was_ansi: false, |
750 | _format_fields: PhantomData, |
751 | } |
752 | } |
753 | |
754 | /// Returns a new [`format::Writer`] for writing to this `FormattedFields`. |
755 | /// |
756 | /// The returned [`format::Writer`] can be used with the |
757 | /// [`FormatFields::format_fields`] method. |
758 | pub fn as_writer(&mut self) -> format::Writer<'_> { |
759 | format::Writer::new(&mut self.fields).with_ansi(self.was_ansi) |
760 | } |
761 | } |
762 | |
763 | impl<E: ?Sized> fmt::Debug for FormattedFields<E> { |
764 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
765 | f.debug_struct("FormattedFields" ) |
766 | .field("fields" , &self.fields) |
767 | .field("formatter" , &format_args!("{}" , std::any::type_name::<E>())) |
768 | .field("was_ansi" , &self.was_ansi) |
769 | .finish() |
770 | } |
771 | } |
772 | |
773 | impl<E: ?Sized> fmt::Display for FormattedFields<E> { |
774 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
775 | fmt::Display::fmt(&self.fields, f) |
776 | } |
777 | } |
778 | |
779 | impl<E: ?Sized> Deref for FormattedFields<E> { |
780 | type Target = String; |
781 | fn deref(&self) -> &Self::Target { |
782 | &self.fields |
783 | } |
784 | } |
785 | |
786 | // === impl FmtLayer === |
787 | |
788 | macro_rules! with_event_from_span { |
789 | ($id:ident, $span:ident, $($field:literal = $value:expr),*, |$event:ident| $code:block) => { |
790 | let meta = $span.metadata(); |
791 | let cs = meta.callsite(); |
792 | let fs = field::FieldSet::new(&[$($field),*], cs); |
793 | #[allow(unused)] |
794 | let mut iter = fs.iter(); |
795 | let v = [$( |
796 | (&iter.next().unwrap(), ::core::option::Option::Some(&$value as &dyn field::Value)), |
797 | )*]; |
798 | let vs = fs.value_set(&v); |
799 | let $event = Event::new_child_of($id, meta, &vs); |
800 | $code |
801 | }; |
802 | } |
803 | |
804 | impl<S, N, E, W> layer::Layer<S> for Layer<S, N, E, W> |
805 | where |
806 | S: Subscriber + for<'a> LookupSpan<'a>, |
807 | N: for<'writer> FormatFields<'writer> + 'static, |
808 | E: FormatEvent<S, N> + 'static, |
809 | W: for<'writer> MakeWriter<'writer> + 'static, |
810 | { |
811 | fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) { |
812 | let span = ctx.span(id).expect("Span not found, this is a bug" ); |
813 | let mut extensions = span.extensions_mut(); |
814 | |
815 | if extensions.get_mut::<FormattedFields<N>>().is_none() { |
816 | let mut fields = FormattedFields::<N>::new(String::new()); |
817 | if self |
818 | .fmt_fields |
819 | .format_fields(fields.as_writer().with_ansi(self.is_ansi), attrs) |
820 | .is_ok() |
821 | { |
822 | fields.was_ansi = self.is_ansi; |
823 | extensions.insert(fields); |
824 | } else { |
825 | eprintln!( |
826 | "[tracing-subscriber] Unable to format the following event, ignoring: {:?}" , |
827 | attrs |
828 | ); |
829 | } |
830 | } |
831 | |
832 | if self.fmt_span.fmt_timing |
833 | && self.fmt_span.trace_close() |
834 | && extensions.get_mut::<Timings>().is_none() |
835 | { |
836 | extensions.insert(Timings::new()); |
837 | } |
838 | |
839 | if self.fmt_span.trace_new() { |
840 | with_event_from_span!(id, span, "message" = "new" , |event| { |
841 | drop(extensions); |
842 | drop(span); |
843 | self.on_event(&event, ctx); |
844 | }); |
845 | } |
846 | } |
847 | |
848 | fn on_record(&self, id: &Id, values: &Record<'_>, ctx: Context<'_, S>) { |
849 | let span = ctx.span(id).expect("Span not found, this is a bug" ); |
850 | let mut extensions = span.extensions_mut(); |
851 | if let Some(fields) = extensions.get_mut::<FormattedFields<N>>() { |
852 | let _ = self.fmt_fields.add_fields(fields, values); |
853 | return; |
854 | } |
855 | |
856 | let mut fields = FormattedFields::<N>::new(String::new()); |
857 | if self |
858 | .fmt_fields |
859 | .format_fields(fields.as_writer().with_ansi(self.is_ansi), values) |
860 | .is_ok() |
861 | { |
862 | fields.was_ansi = self.is_ansi; |
863 | extensions.insert(fields); |
864 | } |
865 | } |
866 | |
867 | fn on_enter(&self, id: &Id, ctx: Context<'_, S>) { |
868 | if self.fmt_span.trace_enter() || self.fmt_span.trace_close() && self.fmt_span.fmt_timing { |
869 | let span = ctx.span(id).expect("Span not found, this is a bug" ); |
870 | let mut extensions = span.extensions_mut(); |
871 | if let Some(timings) = extensions.get_mut::<Timings>() { |
872 | let now = Instant::now(); |
873 | timings.idle += (now - timings.last).as_nanos() as u64; |
874 | timings.last = now; |
875 | } |
876 | |
877 | if self.fmt_span.trace_enter() { |
878 | with_event_from_span!(id, span, "message" = "enter" , |event| { |
879 | drop(extensions); |
880 | drop(span); |
881 | self.on_event(&event, ctx); |
882 | }); |
883 | } |
884 | } |
885 | } |
886 | |
887 | fn on_exit(&self, id: &Id, ctx: Context<'_, S>) { |
888 | if self.fmt_span.trace_exit() || self.fmt_span.trace_close() && self.fmt_span.fmt_timing { |
889 | let span = ctx.span(id).expect("Span not found, this is a bug" ); |
890 | let mut extensions = span.extensions_mut(); |
891 | if let Some(timings) = extensions.get_mut::<Timings>() { |
892 | let now = Instant::now(); |
893 | timings.busy += (now - timings.last).as_nanos() as u64; |
894 | timings.last = now; |
895 | } |
896 | |
897 | if self.fmt_span.trace_exit() { |
898 | with_event_from_span!(id, span, "message" = "exit" , |event| { |
899 | drop(extensions); |
900 | drop(span); |
901 | self.on_event(&event, ctx); |
902 | }); |
903 | } |
904 | } |
905 | } |
906 | |
907 | fn on_close(&self, id: Id, ctx: Context<'_, S>) { |
908 | if self.fmt_span.trace_close() { |
909 | let span = ctx.span(&id).expect("Span not found, this is a bug" ); |
910 | let extensions = span.extensions(); |
911 | if let Some(timing) = extensions.get::<Timings>() { |
912 | let Timings { |
913 | busy, |
914 | mut idle, |
915 | last, |
916 | } = *timing; |
917 | idle += (Instant::now() - last).as_nanos() as u64; |
918 | |
919 | let t_idle = field::display(TimingDisplay(idle)); |
920 | let t_busy = field::display(TimingDisplay(busy)); |
921 | |
922 | with_event_from_span!( |
923 | id, |
924 | span, |
925 | "message" = "close" , |
926 | "time.busy" = t_busy, |
927 | "time.idle" = t_idle, |
928 | |event| { |
929 | drop(extensions); |
930 | drop(span); |
931 | self.on_event(&event, ctx); |
932 | } |
933 | ); |
934 | } else { |
935 | with_event_from_span!(id, span, "message" = "close" , |event| { |
936 | drop(extensions); |
937 | drop(span); |
938 | self.on_event(&event, ctx); |
939 | }); |
940 | } |
941 | } |
942 | } |
943 | |
944 | fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) { |
945 | thread_local! { |
946 | static BUF: RefCell<String> = RefCell::new(String::new()); |
947 | } |
948 | |
949 | BUF.with(|buf| { |
950 | let borrow = buf.try_borrow_mut(); |
951 | let mut a; |
952 | let mut b; |
953 | let mut buf = match borrow { |
954 | Ok(buf) => { |
955 | a = buf; |
956 | &mut *a |
957 | } |
958 | _ => { |
959 | b = String::new(); |
960 | &mut b |
961 | } |
962 | }; |
963 | |
964 | let ctx = self.make_ctx(ctx, event); |
965 | if self |
966 | .fmt_event |
967 | .format_event( |
968 | &ctx, |
969 | format::Writer::new(&mut buf).with_ansi(self.is_ansi), |
970 | event, |
971 | ) |
972 | .is_ok() |
973 | { |
974 | let mut writer = self.make_writer.make_writer_for(event.metadata()); |
975 | let res = io::Write::write_all(&mut writer, buf.as_bytes()); |
976 | if self.log_internal_errors { |
977 | if let Err(e) = res { |
978 | eprintln!("[tracing-subscriber] Unable to write an event to the Writer for this Subscriber! Error: {} \n" , e); |
979 | } |
980 | } |
981 | } else if self.log_internal_errors { |
982 | let err_msg = format!("Unable to format the following event. Name: {}; Fields: {:?} \n" , |
983 | event.metadata().name(), event.fields()); |
984 | let mut writer = self.make_writer.make_writer_for(event.metadata()); |
985 | let res = io::Write::write_all(&mut writer, err_msg.as_bytes()); |
986 | if let Err(e) = res { |
987 | eprintln!("[tracing-subscriber] Unable to write an \"event formatting error \" to the Writer for this Subscriber! Error: {} \n" , e); |
988 | } |
989 | } |
990 | |
991 | buf.clear(); |
992 | }); |
993 | } |
994 | |
995 | unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> { |
996 | // This `downcast_raw` impl allows downcasting a `fmt` layer to any of |
997 | // its components (event formatter, field formatter, and `MakeWriter`) |
998 | // as well as to the layer's type itself. The potential use-cases for |
999 | // this *may* be somewhat niche, though... |
1000 | match () { |
1001 | _ if id == TypeId::of::<Self>() => Some(self as *const Self as *const ()), |
1002 | _ if id == TypeId::of::<E>() => Some(&self.fmt_event as *const E as *const ()), |
1003 | _ if id == TypeId::of::<N>() => Some(&self.fmt_fields as *const N as *const ()), |
1004 | _ if id == TypeId::of::<W>() => Some(&self.make_writer as *const W as *const ()), |
1005 | _ => None, |
1006 | } |
1007 | } |
1008 | } |
1009 | |
1010 | /// Provides the current span context to a formatter. |
1011 | pub struct FmtContext<'a, S, N> { |
1012 | pub(crate) ctx: Context<'a, S>, |
1013 | pub(crate) fmt_fields: &'a N, |
1014 | pub(crate) event: &'a Event<'a>, |
1015 | } |
1016 | |
1017 | impl<'a, S, N> fmt::Debug for FmtContext<'a, S, N> { |
1018 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1019 | f.debug_struct("FmtContext" ).finish() |
1020 | } |
1021 | } |
1022 | |
1023 | impl<'cx, 'writer, S, N> FormatFields<'writer> for FmtContext<'cx, S, N> |
1024 | where |
1025 | S: Subscriber + for<'lookup> LookupSpan<'lookup>, |
1026 | N: FormatFields<'writer> + 'static, |
1027 | { |
1028 | fn format_fields<R: RecordFields>( |
1029 | &self, |
1030 | writer: format::Writer<'writer>, |
1031 | fields: R, |
1032 | ) -> fmt::Result { |
1033 | self.fmt_fields.format_fields(writer, fields) |
1034 | } |
1035 | } |
1036 | |
1037 | impl<'a, S, N> FmtContext<'a, S, N> |
1038 | where |
1039 | S: Subscriber + for<'lookup> LookupSpan<'lookup>, |
1040 | N: for<'writer> FormatFields<'writer> + 'static, |
1041 | { |
1042 | /// Visits every span in the current context with a closure. |
1043 | /// |
1044 | /// The provided closure will be called first with the current span, |
1045 | /// and then with that span's parent, and then that span's parent, |
1046 | /// and so on until a root span is reached. |
1047 | pub fn visit_spans<E, F>(&self, mut f: F) -> Result<(), E> |
1048 | where |
1049 | F: FnMut(&SpanRef<'_, S>) -> Result<(), E>, |
1050 | { |
1051 | // visit all the current spans |
1052 | if let Some(scope) = self.event_scope() { |
1053 | for span in scope.from_root() { |
1054 | f(&span)?; |
1055 | } |
1056 | } |
1057 | Ok(()) |
1058 | } |
1059 | |
1060 | /// Returns metadata for the span with the given `id`, if it exists. |
1061 | /// |
1062 | /// If this returns `None`, then no span exists for that ID (either it has |
1063 | /// closed or the ID is invalid). |
1064 | #[inline ] |
1065 | pub fn metadata(&self, id: &Id) -> Option<&'static Metadata<'static>> |
1066 | where |
1067 | S: for<'lookup> LookupSpan<'lookup>, |
1068 | { |
1069 | self.ctx.metadata(id) |
1070 | } |
1071 | |
1072 | /// Returns [stored data] for the span with the given `id`, if it exists. |
1073 | /// |
1074 | /// If this returns `None`, then no span exists for that ID (either it has |
1075 | /// closed or the ID is invalid). |
1076 | /// |
1077 | /// [stored data]: crate::registry::SpanRef |
1078 | #[inline ] |
1079 | pub fn span(&self, id: &Id) -> Option<SpanRef<'_, S>> |
1080 | where |
1081 | S: for<'lookup> LookupSpan<'lookup>, |
1082 | { |
1083 | self.ctx.span(id) |
1084 | } |
1085 | |
1086 | /// Returns `true` if an active span exists for the given `Id`. |
1087 | #[inline ] |
1088 | pub fn exists(&self, id: &Id) -> bool |
1089 | where |
1090 | S: for<'lookup> LookupSpan<'lookup>, |
1091 | { |
1092 | self.ctx.exists(id) |
1093 | } |
1094 | |
1095 | /// Returns [stored data] for the span that the wrapped subscriber considers |
1096 | /// to be the current. |
1097 | /// |
1098 | /// If this returns `None`, then we are not currently within a span. |
1099 | /// |
1100 | /// [stored data]: crate::registry::SpanRef |
1101 | #[inline ] |
1102 | pub fn lookup_current(&self) -> Option<SpanRef<'_, S>> |
1103 | where |
1104 | S: for<'lookup> LookupSpan<'lookup>, |
1105 | { |
1106 | self.ctx.lookup_current() |
1107 | } |
1108 | |
1109 | /// Returns the current span for this formatter. |
1110 | pub fn current_span(&self) -> Current { |
1111 | self.ctx.current_span() |
1112 | } |
1113 | |
1114 | /// Returns [stored data] for the parent span of the event currently being |
1115 | /// formatted. |
1116 | /// |
1117 | /// If the event has a contextual parent, this will return the current span. If |
1118 | /// the event has an explicit parent span, this will return that span. If |
1119 | /// the event does not have a parent span, this will return `None`. |
1120 | /// |
1121 | /// [stored data]: SpanRef |
1122 | pub fn parent_span(&self) -> Option<SpanRef<'_, S>> { |
1123 | self.ctx.event_span(self.event) |
1124 | } |
1125 | |
1126 | /// Returns an iterator over the [stored data] for all the spans in the |
1127 | /// current context, starting with the specified span and ending with the |
1128 | /// root of the trace tree and ending with the current span. |
1129 | /// |
1130 | /// This is equivalent to the [`Context::span_scope`] method. |
1131 | /// |
1132 | /// <div class="information"> |
1133 | /// <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div> |
1134 | /// </div> |
1135 | /// <div class="example-wrap" style="display:inline-block"> |
1136 | /// <pre class="ignore" style="white-space:normal;font:inherit;"> |
1137 | /// <strong>Note</strong>: Compared to <a href="#method.scope"><code>scope</code></a> this |
1138 | /// returns the spans in reverse order (from leaf to root). Use |
1139 | /// <a href="../registry/struct.Scope.html#method.from_root"><code>Scope::from_root</code></a> |
1140 | /// in case root-to-leaf ordering is desired. |
1141 | /// </pre></div> |
1142 | /// |
1143 | /// <div class="example-wrap" style="display:inline-block"> |
1144 | /// <pre class="ignore" style="white-space:normal;font:inherit;"> |
1145 | /// <strong>Note</strong>: This requires the wrapped subscriber to implement the |
1146 | /// <a href="../registry/trait.LookupSpan.html"><code>LookupSpan</code></a> trait. |
1147 | /// See the documentation on <a href="./struct.Context.html"><code>Context</code>'s |
1148 | /// declaration</a> for details. |
1149 | /// </pre></div> |
1150 | /// |
1151 | /// [stored data]: crate::registry::SpanRef |
1152 | pub fn span_scope(&self, id: &Id) -> Option<registry::Scope<'_, S>> |
1153 | where |
1154 | S: for<'lookup> LookupSpan<'lookup>, |
1155 | { |
1156 | self.ctx.span_scope(id) |
1157 | } |
1158 | |
1159 | /// Returns an iterator over the [stored data] for all the spans in the |
1160 | /// event's span context, starting with its parent span and ending with the |
1161 | /// root of the trace tree. |
1162 | /// |
1163 | /// This is equivalent to calling the [`Context::event_scope`] method and |
1164 | /// passing the event currently being formatted. |
1165 | /// |
1166 | /// <div class="example-wrap" style="display:inline-block"> |
1167 | /// <pre class="ignore" style="white-space:normal;font:inherit;"> |
1168 | /// <strong>Note</strong>: Compared to <a href="#method.scope"><code>scope</code></a> this |
1169 | /// returns the spans in reverse order (from leaf to root). Use |
1170 | /// <a href="../registry/struct.Scope.html#method.from_root"><code>Scope::from_root</code></a> |
1171 | /// in case root-to-leaf ordering is desired. |
1172 | /// </pre></div> |
1173 | /// |
1174 | /// <div class="example-wrap" style="display:inline-block"> |
1175 | /// <pre class="ignore" style="white-space:normal;font:inherit;"> |
1176 | /// <strong>Note</strong>: This requires the wrapped subscriber to implement the |
1177 | /// <a href="../registry/trait.LookupSpan.html"><code>LookupSpan</code></a> trait. |
1178 | /// See the documentation on <a href="./struct.Context.html"><code>Context</code>'s |
1179 | /// declaration</a> for details. |
1180 | /// </pre></div> |
1181 | /// |
1182 | /// [stored data]: crate::registry::SpanRef |
1183 | pub fn event_scope(&self) -> Option<registry::Scope<'_, S>> |
1184 | where |
1185 | S: for<'lookup> registry::LookupSpan<'lookup>, |
1186 | { |
1187 | self.ctx.event_scope(self.event) |
1188 | } |
1189 | |
1190 | /// Returns the [field formatter] configured by the subscriber invoking |
1191 | /// `format_event`. |
1192 | /// |
1193 | /// The event formatter may use the returned field formatter to format the |
1194 | /// fields of any events it records. |
1195 | /// |
1196 | /// [field formatter]: FormatFields |
1197 | pub fn field_format(&self) -> &N { |
1198 | self.fmt_fields |
1199 | } |
1200 | } |
1201 | |
1202 | struct Timings { |
1203 | idle: u64, |
1204 | busy: u64, |
1205 | last: Instant, |
1206 | } |
1207 | |
1208 | impl Timings { |
1209 | fn new() -> Self { |
1210 | Self { |
1211 | idle: 0, |
1212 | busy: 0, |
1213 | last: Instant::now(), |
1214 | } |
1215 | } |
1216 | } |
1217 | |
1218 | #[cfg (test)] |
1219 | mod test { |
1220 | use super::*; |
1221 | use crate::fmt::{ |
1222 | self, |
1223 | format::{self, test::MockTime, Format}, |
1224 | layer::Layer as _, |
1225 | test::{MockMakeWriter, MockWriter}, |
1226 | time, |
1227 | }; |
1228 | use crate::Registry; |
1229 | use format::FmtSpan; |
1230 | use regex::Regex; |
1231 | use tracing::subscriber::with_default; |
1232 | use tracing_core::dispatcher::Dispatch; |
1233 | |
1234 | #[test] |
1235 | fn impls() { |
1236 | let f = Format::default().with_timer(time::Uptime::default()); |
1237 | let fmt = fmt::Layer::default().event_format(f); |
1238 | let subscriber = fmt.with_subscriber(Registry::default()); |
1239 | let _dispatch = Dispatch::new(subscriber); |
1240 | |
1241 | let f = format::Format::default(); |
1242 | let fmt = fmt::Layer::default().event_format(f); |
1243 | let subscriber = fmt.with_subscriber(Registry::default()); |
1244 | let _dispatch = Dispatch::new(subscriber); |
1245 | |
1246 | let f = format::Format::default().compact(); |
1247 | let fmt = fmt::Layer::default().event_format(f); |
1248 | let subscriber = fmt.with_subscriber(Registry::default()); |
1249 | let _dispatch = Dispatch::new(subscriber); |
1250 | } |
1251 | |
1252 | #[test] |
1253 | fn fmt_layer_downcasts() { |
1254 | let f = format::Format::default(); |
1255 | let fmt = fmt::Layer::default().event_format(f); |
1256 | let subscriber = fmt.with_subscriber(Registry::default()); |
1257 | |
1258 | let dispatch = Dispatch::new(subscriber); |
1259 | assert!(dispatch.downcast_ref::<fmt::Layer<Registry>>().is_some()); |
1260 | } |
1261 | |
1262 | #[test] |
1263 | fn fmt_layer_downcasts_to_parts() { |
1264 | let f = format::Format::default(); |
1265 | let fmt = fmt::Layer::default().event_format(f); |
1266 | let subscriber = fmt.with_subscriber(Registry::default()); |
1267 | let dispatch = Dispatch::new(subscriber); |
1268 | assert!(dispatch.downcast_ref::<format::DefaultFields>().is_some()); |
1269 | assert!(dispatch.downcast_ref::<format::Format>().is_some()) |
1270 | } |
1271 | |
1272 | #[test] |
1273 | fn is_lookup_span() { |
1274 | fn assert_lookup_span<T: for<'a> crate::registry::LookupSpan<'a>>(_: T) {} |
1275 | let fmt = fmt::Layer::default(); |
1276 | let subscriber = fmt.with_subscriber(Registry::default()); |
1277 | assert_lookup_span(subscriber) |
1278 | } |
1279 | |
1280 | fn sanitize_timings(s: String) -> String { |
1281 | let re = Regex::new("time \\.(idle|busy)=([0-9.]+)[mµn]s" ).unwrap(); |
1282 | re.replace_all(s.as_str(), "timing" ).to_string() |
1283 | } |
1284 | |
1285 | #[test] |
1286 | fn format_error_print_to_stderr() { |
1287 | struct AlwaysError; |
1288 | |
1289 | impl std::fmt::Debug for AlwaysError { |
1290 | fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
1291 | Err(std::fmt::Error) |
1292 | } |
1293 | } |
1294 | |
1295 | let make_writer = MockMakeWriter::default(); |
1296 | let subscriber = crate::fmt::Subscriber::builder() |
1297 | .with_writer(make_writer.clone()) |
1298 | .with_level(false) |
1299 | .with_ansi(false) |
1300 | .with_timer(MockTime) |
1301 | .finish(); |
1302 | |
1303 | with_default(subscriber, || { |
1304 | tracing::info!(?AlwaysError); |
1305 | }); |
1306 | let actual = sanitize_timings(make_writer.get_string()); |
1307 | |
1308 | // Only assert the start because the line number and callsite may change. |
1309 | let expected = concat!( |
1310 | "Unable to format the following event. Name: event " , |
1311 | file!(), |
1312 | ":" |
1313 | ); |
1314 | assert!( |
1315 | actual.as_str().starts_with(expected), |
1316 | " \nactual = {} \nshould start with expected = {} \n" , |
1317 | actual, |
1318 | expected |
1319 | ); |
1320 | } |
1321 | |
1322 | #[test] |
1323 | fn format_error_ignore_if_log_internal_errors_is_false() { |
1324 | struct AlwaysError; |
1325 | |
1326 | impl std::fmt::Debug for AlwaysError { |
1327 | fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
1328 | Err(std::fmt::Error) |
1329 | } |
1330 | } |
1331 | |
1332 | let make_writer = MockMakeWriter::default(); |
1333 | let subscriber = crate::fmt::Subscriber::builder() |
1334 | .with_writer(make_writer.clone()) |
1335 | .with_level(false) |
1336 | .with_ansi(false) |
1337 | .with_timer(MockTime) |
1338 | .log_internal_errors(false) |
1339 | .finish(); |
1340 | |
1341 | with_default(subscriber, || { |
1342 | tracing::info!(?AlwaysError); |
1343 | }); |
1344 | let actual = sanitize_timings(make_writer.get_string()); |
1345 | assert_eq!("" , actual.as_str()); |
1346 | } |
1347 | |
1348 | #[test] |
1349 | fn synthesize_span_none() { |
1350 | let make_writer = MockMakeWriter::default(); |
1351 | let subscriber = crate::fmt::Subscriber::builder() |
1352 | .with_writer(make_writer.clone()) |
1353 | .with_level(false) |
1354 | .with_ansi(false) |
1355 | .with_timer(MockTime) |
1356 | // check that FmtSpan::NONE is the default |
1357 | .finish(); |
1358 | |
1359 | with_default(subscriber, || { |
1360 | let span1 = tracing::info_span!("span1" , x = 42); |
1361 | let _e = span1.enter(); |
1362 | }); |
1363 | let actual = sanitize_timings(make_writer.get_string()); |
1364 | assert_eq!("" , actual.as_str()); |
1365 | } |
1366 | |
1367 | #[test] |
1368 | fn synthesize_span_active() { |
1369 | let make_writer = MockMakeWriter::default(); |
1370 | let subscriber = crate::fmt::Subscriber::builder() |
1371 | .with_writer(make_writer.clone()) |
1372 | .with_level(false) |
1373 | .with_ansi(false) |
1374 | .with_timer(MockTime) |
1375 | .with_span_events(FmtSpan::ACTIVE) |
1376 | .finish(); |
1377 | |
1378 | with_default(subscriber, || { |
1379 | let span1 = tracing::info_span!("span1" , x = 42); |
1380 | let _e = span1.enter(); |
1381 | }); |
1382 | let actual = sanitize_timings(make_writer.get_string()); |
1383 | assert_eq!( |
1384 | "fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: enter \n\ |
1385 | fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: exit \n" , |
1386 | actual.as_str() |
1387 | ); |
1388 | } |
1389 | |
1390 | #[test] |
1391 | fn synthesize_span_close() { |
1392 | let make_writer = MockMakeWriter::default(); |
1393 | let subscriber = crate::fmt::Subscriber::builder() |
1394 | .with_writer(make_writer.clone()) |
1395 | .with_level(false) |
1396 | .with_ansi(false) |
1397 | .with_timer(MockTime) |
1398 | .with_span_events(FmtSpan::CLOSE) |
1399 | .finish(); |
1400 | |
1401 | with_default(subscriber, || { |
1402 | let span1 = tracing::info_span!("span1" , x = 42); |
1403 | let _e = span1.enter(); |
1404 | }); |
1405 | let actual = sanitize_timings(make_writer.get_string()); |
1406 | assert_eq!( |
1407 | "fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: close timing timing \n" , |
1408 | actual.as_str() |
1409 | ); |
1410 | } |
1411 | |
1412 | #[test] |
1413 | fn synthesize_span_close_no_timing() { |
1414 | let make_writer = MockMakeWriter::default(); |
1415 | let subscriber = crate::fmt::Subscriber::builder() |
1416 | .with_writer(make_writer.clone()) |
1417 | .with_level(false) |
1418 | .with_ansi(false) |
1419 | .with_timer(MockTime) |
1420 | .without_time() |
1421 | .with_span_events(FmtSpan::CLOSE) |
1422 | .finish(); |
1423 | |
1424 | with_default(subscriber, || { |
1425 | let span1 = tracing::info_span!("span1" , x = 42); |
1426 | let _e = span1.enter(); |
1427 | }); |
1428 | let actual = sanitize_timings(make_writer.get_string()); |
1429 | assert_eq!( |
1430 | "span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: close \n" , |
1431 | actual.as_str() |
1432 | ); |
1433 | } |
1434 | |
1435 | #[test] |
1436 | fn synthesize_span_full() { |
1437 | let make_writer = MockMakeWriter::default(); |
1438 | let subscriber = crate::fmt::Subscriber::builder() |
1439 | .with_writer(make_writer.clone()) |
1440 | .with_level(false) |
1441 | .with_ansi(false) |
1442 | .with_timer(MockTime) |
1443 | .with_span_events(FmtSpan::FULL) |
1444 | .finish(); |
1445 | |
1446 | with_default(subscriber, || { |
1447 | let span1 = tracing::info_span!("span1" , x = 42); |
1448 | let _e = span1.enter(); |
1449 | }); |
1450 | let actual = sanitize_timings(make_writer.get_string()); |
1451 | assert_eq!( |
1452 | "fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: new \n\ |
1453 | fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: enter \n\ |
1454 | fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: exit \n\ |
1455 | fake time span1{x=42}: tracing_subscriber::fmt::fmt_layer::test: close timing timing \n" , |
1456 | actual.as_str() |
1457 | ); |
1458 | } |
1459 | |
1460 | #[test] |
1461 | fn make_writer_based_on_meta() { |
1462 | struct MakeByTarget { |
1463 | make_writer1: MockMakeWriter, |
1464 | make_writer2: MockMakeWriter, |
1465 | } |
1466 | |
1467 | impl<'a> MakeWriter<'a> for MakeByTarget { |
1468 | type Writer = MockWriter; |
1469 | |
1470 | fn make_writer(&'a self) -> Self::Writer { |
1471 | self.make_writer1.make_writer() |
1472 | } |
1473 | |
1474 | fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer { |
1475 | if meta.target() == "writer2" { |
1476 | return self.make_writer2.make_writer(); |
1477 | } |
1478 | self.make_writer() |
1479 | } |
1480 | } |
1481 | |
1482 | let make_writer1 = MockMakeWriter::default(); |
1483 | let make_writer2 = MockMakeWriter::default(); |
1484 | |
1485 | let make_writer = MakeByTarget { |
1486 | make_writer1: make_writer1.clone(), |
1487 | make_writer2: make_writer2.clone(), |
1488 | }; |
1489 | |
1490 | let subscriber = crate::fmt::Subscriber::builder() |
1491 | .with_writer(make_writer) |
1492 | .with_level(false) |
1493 | .with_target(false) |
1494 | .with_ansi(false) |
1495 | .with_timer(MockTime) |
1496 | .with_span_events(FmtSpan::CLOSE) |
1497 | .finish(); |
1498 | |
1499 | with_default(subscriber, || { |
1500 | let span1 = tracing::info_span!("writer1_span" , x = 42); |
1501 | let _e = span1.enter(); |
1502 | tracing::info!(target: "writer2" , "hello writer2!" ); |
1503 | let span2 = tracing::info_span!(target: "writer2" , "writer2_span" ); |
1504 | let _e = span2.enter(); |
1505 | tracing::warn!(target: "writer1" , "hello writer1!" ); |
1506 | }); |
1507 | |
1508 | let actual = sanitize_timings(make_writer1.get_string()); |
1509 | assert_eq!( |
1510 | "fake time writer1_span{x=42}:writer2_span: hello writer1! \n\ |
1511 | fake time writer1_span{x=42}: close timing timing \n" , |
1512 | actual.as_str() |
1513 | ); |
1514 | let actual = sanitize_timings(make_writer2.get_string()); |
1515 | assert_eq!( |
1516 | "fake time writer1_span{x=42}: hello writer2! \n\ |
1517 | fake time writer1_span{x=42}:writer2_span: close timing timing \n" , |
1518 | actual.as_str() |
1519 | ); |
1520 | } |
1521 | |
1522 | // Because we need to modify an environment variable for these test cases, |
1523 | // we do them all in a single test. |
1524 | #[cfg (feature = "ansi" )] |
1525 | #[test] |
1526 | fn layer_no_color() { |
1527 | const NO_COLOR: &str = "NO_COLOR" ; |
1528 | |
1529 | // Restores the previous value of the `NO_COLOR` env variable when |
1530 | // dropped. |
1531 | // |
1532 | // This is done in a `Drop` implementation, rather than just resetting |
1533 | // the value at the end of the test, so that the previous value is |
1534 | // restored even if the test panics. |
1535 | struct RestoreEnvVar(Result<String, env::VarError>); |
1536 | impl Drop for RestoreEnvVar { |
1537 | fn drop(&mut self) { |
1538 | match self.0 { |
1539 | Ok(ref var) => env::set_var(NO_COLOR, var), |
1540 | Err(_) => env::remove_var(NO_COLOR), |
1541 | } |
1542 | } |
1543 | } |
1544 | |
1545 | let _saved_no_color = RestoreEnvVar(env::var(NO_COLOR)); |
1546 | |
1547 | let cases: Vec<(Option<&str>, bool)> = vec![ |
1548 | (Some("0" ), false), // any non-empty value disables ansi |
1549 | (Some("off" ), false), // any non-empty value disables ansi |
1550 | (Some("1" ), false), |
1551 | (Some("" ), true), // empty value does not disable ansi |
1552 | (None, true), |
1553 | ]; |
1554 | |
1555 | for (var, ansi) in cases { |
1556 | if let Some(value) = var { |
1557 | env::set_var(NO_COLOR, value); |
1558 | } else { |
1559 | env::remove_var(NO_COLOR); |
1560 | } |
1561 | |
1562 | let layer: Layer<()> = fmt::Layer::default(); |
1563 | assert_eq!( |
1564 | layer.is_ansi, ansi, |
1565 | "NO_COLOR={:?}; Layer::default().is_ansi should be {}" , |
1566 | var, ansi |
1567 | ); |
1568 | |
1569 | // with_ansi should override any `NO_COLOR` value |
1570 | let layer: Layer<()> = fmt::Layer::default().with_ansi(true); |
1571 | assert!( |
1572 | layer.is_ansi, |
1573 | "NO_COLOR={:?}; Layer::default().with_ansi(true).is_ansi should be true" , |
1574 | var |
1575 | ); |
1576 | |
1577 | // set_ansi should override any `NO_COLOR` value |
1578 | let mut layer: Layer<()> = fmt::Layer::default(); |
1579 | layer.set_ansi(true); |
1580 | assert!( |
1581 | layer.is_ansi, |
1582 | "NO_COLOR={:?}; layer.set_ansi(true); layer.is_ansi should be true" , |
1583 | var |
1584 | ); |
1585 | } |
1586 | |
1587 | // dropping `_saved_no_color` will restore the previous value of |
1588 | // `NO_COLOR`. |
1589 | } |
1590 | } |
1591 | |