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