Coverage Report

Created: 2026-08-31 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-subscriber-0.3.23/src/fmt/mod.rs
Line
Count
Source
1
//! A `Subscriber` for formatting and logging `tracing` data.
2
//!
3
//! # Overview
4
//!
5
//! [`tracing`] is a framework for instrumenting Rust programs with context-aware,
6
//! structured, event-based diagnostic information. This crate provides an
7
//! implementation of the [`Subscriber`] trait that records `tracing`'s `Event`s
8
//! and `Span`s by formatting them as text and logging them to stdout.
9
//!
10
//! # Usage
11
//!
12
//! First, add this to your `Cargo.toml` file:
13
//!
14
//! ```toml
15
//! [dependencies]
16
//! tracing-subscriber = "0.3"
17
//! ```
18
//!
19
//! *Compiler support: [requires `rustc` 1.65+][msrv]*
20
//!
21
//! [msrv]: super#supported-rust-versions
22
//!
23
//! Add the following to your executable to initialize the default subscriber:
24
//! ```rust
25
//! use tracing_subscriber;
26
//!
27
//! tracing_subscriber::fmt::init();
28
//! ```
29
//!
30
//! ## Filtering Events with Environment Variables
31
//!
32
//! The default subscriber installed by `init` enables you to filter events
33
//! at runtime using environment variables (using the [`EnvFilter`]).
34
//!
35
//! The filter syntax is a superset of the [`env_logger`] syntax.
36
//!
37
//! For example:
38
//! - Setting `RUST_LOG=debug` enables all `Span`s and `Event`s
39
//!   set to the log level `DEBUG` or higher
40
//! - Setting `RUST_LOG=my_crate=trace` enables `Span`s and `Event`s
41
//!   in `my_crate` at all log levels
42
//!
43
//! **Note**: This should **not** be called by libraries. Libraries should use
44
//! [`tracing`] to publish `tracing` `Event`s.
45
//!
46
//! # Configuration
47
//!
48
//! You can configure a subscriber instead of using the defaults with
49
//! the following functions:
50
//!
51
//! ### Subscriber
52
//!
53
//! The [`FmtSubscriber`] formats and records `tracing` events as line-oriented logs.
54
//! You can create one by calling:
55
//!
56
//! ```rust
57
//! let subscriber = tracing_subscriber::fmt()
58
//!     // ... add configuration
59
//!     .finish();
60
//! ```
61
//!
62
//! You can find the configuration methods for [`FmtSubscriber`] in
63
//! [`SubscriberBuilder`].
64
//!
65
//! ## Formatters
66
//!
67
//! The output format used by the layer and subscriber in this module is
68
//! represented by implementing the [`FormatEvent`] trait, and can be
69
//! customized. This module provides a number of formatter implementations:
70
//!
71
//! * [`format::Full`]: The default formatter. This emits human-readable,
72
//!   single-line logs for each event that occurs, with the current span context
73
//!   displayed before the formatted representation of the event. See
74
//!   [here](format::Full#example-output) for sample output.
75
//!
76
//! * [`format::Compact`]: A variant of the default formatter, optimized for
77
//!   short line lengths. Fields from the current span context are appended to
78
//!   the fields of the formatted event. See
79
//!   [here](format::Compact#example-output) for sample output.
80
//!
81
//! * [`format::Pretty`]: Emits excessively pretty, multi-line logs, optimized
82
//!   for human readability. This is primarily intended to be used in local
83
//!   development and debugging, or for command-line applications, where
84
//!   automated analysis and compact storage of logs is less of a priority than
85
//!   readability and visual appeal. See [here](format::Pretty#example-output)
86
//!   for sample output.
87
//!
88
//! * [`format::Json`]: Outputs newline-delimited JSON logs. This is intended
89
//!   for production use with systems where structured logs are consumed as JSON
90
//!   by analysis and viewing tools. The JSON output is not optimized for human
91
//!   readability. See [here](format::Json#example-output) for sample output.
92
//!
93
//! ### Customizing Formatters
94
//!
95
//! The formatting of log lines for spans and events is controlled by two
96
//! traits, [`FormatEvent`] and [`FormatFields`]. The [`FormatEvent`] trait
97
//! determines the overall formatting of the log line, such as what information
98
//! from the event's metadata and span context is included and in what order.
99
//! The [`FormatFields`] trait determines how fields — both the event's
100
//! fields and fields on spans — are formatted.
101
//!
102
//! The [`fmt::format`] module provides several types which implement these traits,
103
//! many of which expose additional configuration options to customize their
104
//! output. The [`format::Format`] type implements common configuration used by
105
//! all the formatters provided in this crate, and can be used as a builder to
106
//! set specific formatting settings. For example:
107
//!
108
//! ```
109
//! use tracing_subscriber::fmt;
110
//!
111
//! // Configure a custom event formatter
112
//! let format = fmt::format()
113
//!    .with_level(false) // don't include levels in formatted output
114
//!    .with_target(false) // don't include targets
115
//!    .with_thread_ids(true) // include the thread ID of the current thread
116
//!    .with_thread_names(true) // include the name of the current thread
117
//!    .compact(); // use the `Compact` formatting style.
118
//!
119
//! // Create a `fmt` subscriber that uses our custom event format, and set it
120
//! // as the default.
121
//! tracing_subscriber::fmt()
122
//!     .event_format(format)
123
//!     .init();
124
//! ```
125
//!
126
//! However, if a specific output format is needed, other crates can
127
//! also implement [`FormatEvent`] and [`FormatFields`]. See those traits'
128
//! documentation for details on how to implement them.
129
//!
130
//! ## Filters
131
//!
132
//! If you want to filter the `tracing` `Events` based on environment
133
//! variables, you can use the [`EnvFilter`] as follows:
134
//!
135
//! ```rust
136
//! use tracing_subscriber::EnvFilter;
137
//!
138
//! let filter = EnvFilter::from_default_env();
139
//! ```
140
//!
141
//! As mentioned above, the [`EnvFilter`] allows `Span`s and `Event`s to
142
//! be filtered at runtime by setting the `RUST_LOG` environment variable.
143
//!
144
//! You can find the other available [`filter`]s in the documentation.
145
//!
146
//! ### Using Your Subscriber
147
//!
148
//! Finally, once you have configured your `Subscriber`, you need to
149
//! configure your executable to use it.
150
//!
151
//! A subscriber can be installed globally using:
152
//! ```rust
153
//! use tracing;
154
//! use tracing_subscriber::FmtSubscriber;
155
//!
156
//! let subscriber = FmtSubscriber::new();
157
//!
158
//! tracing::subscriber::set_global_default(subscriber)
159
//!     .map_err(|_err| eprintln!("Unable to set global default subscriber"));
160
//! // Note this will only fail if you try to set the global default
161
//! // subscriber multiple times
162
//! ```
163
//!
164
//! ### Composing Layers
165
//!
166
//! Composing an [`EnvFilter`] `Layer` and a [format `Layer`][super::fmt::Layer]:
167
//!
168
//! ```rust
169
//! use tracing_subscriber::{fmt, EnvFilter};
170
//! use tracing_subscriber::prelude::*;
171
//!
172
//! let fmt_layer = fmt::layer()
173
//!     .with_target(false);
174
//! let filter_layer = EnvFilter::try_from_default_env()
175
//!     .or_else(|_| EnvFilter::try_new("info"))
176
//!     .unwrap();
177
//!
178
//! tracing_subscriber::registry()
179
//!     .with(filter_layer)
180
//!     .with(fmt_layer)
181
//!     .init();
182
//! ```
183
//!
184
//! [`EnvFilter`]: super::filter::EnvFilter
185
//! [`env_logger`]: https://docs.rs/env_logger/
186
//! [`filter`]: super::filter
187
//! [`FmtSubscriber`]: Subscriber
188
//! [`Subscriber`]:
189
//!     https://docs.rs/tracing/latest/tracing/trait.Subscriber.html
190
//! [`tracing`]: https://crates.io/crates/tracing
191
//! [`fmt::format`]: mod@crate::fmt::format
192
193
use alloc::boxed::Box;
194
use core::any::TypeId;
195
use std::{error::Error, io};
196
use tracing_core::{span, subscriber::Interest, Event, Metadata};
197
198
mod fmt_layer;
199
#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))]
200
pub mod format;
201
#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))]
202
pub mod time;
203
#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))]
204
pub mod writer;
205
206
pub use fmt_layer::{FmtContext, FormattedFields, Layer};
207
208
use crate::layer::Layer as _;
209
use crate::util::SubscriberInitExt;
210
use crate::{
211
    filter::LevelFilter,
212
    layer,
213
    registry::{LookupSpan, Registry},
214
};
215
216
#[doc(inline)]
217
pub use self::{
218
    format::{format, FormatEvent, FormatFields},
219
    time::time,
220
    writer::{MakeWriter, TestWriter},
221
};
222
223
/// A `Subscriber` that logs formatted representations of `tracing` events.
224
///
225
/// This consists of an inner `Formatter` wrapped in a layer that performs filtering.
226
#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))]
227
#[derive(Debug)]
228
pub struct Subscriber<
229
    N = format::DefaultFields,
230
    E = format::Format<format::Full>,
231
    F = LevelFilter,
232
    W = fn() -> io::Stdout,
233
> {
234
    inner: layer::Layered<F, Formatter<N, E, W>>,
235
}
236
237
/// A `Subscriber` that logs formatted representations of `tracing` events.
238
/// This type only logs formatted events; it does not perform any filtering.
239
#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))]
240
pub type Formatter<
241
    N = format::DefaultFields,
242
    E = format::Format<format::Full>,
243
    W = fn() -> io::Stdout,
244
> = layer::Layered<fmt_layer::Layer<Registry, N, E, W>, Registry>;
245
246
/// Configures and constructs `Subscriber`s.
247
#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))]
248
#[derive(Debug)]
249
#[must_use]
250
pub struct SubscriberBuilder<
251
    N = format::DefaultFields,
252
    E = format::Format<format::Full>,
253
    F = LevelFilter,
254
    W = fn() -> io::Stdout,
255
> {
256
    filter: F,
257
    inner: Layer<Registry, N, E, W>,
258
}
259
260
/// Returns a new [`SubscriberBuilder`] for configuring a [formatting subscriber].
261
///
262
/// This is essentially shorthand for [`SubscriberBuilder::default()]`.
263
///
264
/// # Examples
265
///
266
/// Using [`init`] to set the default subscriber:
267
///
268
/// ```rust
269
/// tracing_subscriber::fmt().init();
270
/// ```
271
///
272
/// Configuring the output format:
273
///
274
/// ```rust
275
///
276
/// tracing_subscriber::fmt()
277
///     // Configure formatting settings.
278
///     .with_target(false)
279
///     .with_timer(tracing_subscriber::fmt::time::uptime())
280
///     .with_level(true)
281
///     // Set the subscriber as the default.
282
///     .init();
283
/// ```
284
///
285
/// [`try_init`] returns an error if the default subscriber could not be set:
286
///
287
/// ```rust
288
/// use std::error::Error;
289
///
290
/// fn init_subscriber() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
291
///     tracing_subscriber::fmt()
292
///         // Configure the subscriber to emit logs in JSON format.
293
///         .json()
294
///         // Configure the subscriber to flatten event fields in the output JSON objects.
295
///         .flatten_event(true)
296
///         // Set the subscriber as the default, returning an error if this fails.
297
///         .try_init()?;
298
///
299
///     Ok(())
300
/// }
301
/// ```
302
///
303
/// Rather than setting the subscriber as the default, [`finish`] _returns_ the
304
/// constructed subscriber, which may then be passed to other functions:
305
///
306
/// ```rust
307
/// let subscriber = tracing_subscriber::fmt()
308
///     .with_max_level(tracing::Level::DEBUG)
309
///     .compact()
310
///     .finish();
311
///
312
/// tracing::subscriber::with_default(subscriber, || {
313
///     // the subscriber will only be set as the default
314
///     // inside this closure...
315
/// })
316
/// ```
317
///
318
/// [formatting subscriber]: Subscriber
319
/// [`SubscriberBuilder::default()`]: SubscriberBuilder::default
320
/// [`init`]: SubscriberBuilder::init()
321
/// [`try_init`]: SubscriberBuilder::try_init()
322
/// [`finish`]: SubscriberBuilder::finish()
323
#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))]
324
0
pub fn fmt() -> SubscriberBuilder {
325
0
    SubscriberBuilder::default()
326
0
}
327
328
/// Returns a new [formatting layer] that can be [composed] with other layers to
329
/// construct a [`Subscriber`].
330
///
331
/// This is a shorthand for the equivalent [`Layer::default()`] function.
332
///
333
/// [formatting layer]: Layer
334
/// [composed]: crate::layer
335
/// [`Layer::default()`]: Layer::default
336
#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))]
337
0
pub fn layer<S>() -> Layer<S> {
338
0
    Layer::default()
339
0
}
340
341
impl Subscriber {
342
    /// The maximum [verbosity level] that is enabled by a `Subscriber` by
343
    /// default.
344
    ///
345
    /// This can be overridden with the [`SubscriberBuilder::with_max_level`] method.
346
    ///
347
    /// [verbosity level]: tracing_core::Level
348
    /// [`SubscriberBuilder::with_max_level`]: SubscriberBuilder::with_max_level
349
    pub const DEFAULT_MAX_LEVEL: LevelFilter = LevelFilter::INFO;
350
351
    /// Returns a new `SubscriberBuilder` for configuring a format subscriber.
352
0
    pub fn builder() -> SubscriberBuilder {
353
0
        SubscriberBuilder::default()
354
0
    }
355
356
    /// Returns a new format subscriber with the default configuration.
357
0
    pub fn new() -> Self {
358
0
        Default::default()
359
0
    }
360
}
361
362
impl Default for Subscriber {
363
0
    fn default() -> Self {
364
0
        SubscriberBuilder::default().finish()
365
0
    }
366
}
367
368
// === impl Subscriber ===
369
370
impl<N, E, F, W> tracing_core::Subscriber for Subscriber<N, E, F, W>
371
where
372
    N: for<'writer> FormatFields<'writer> + 'static,
373
    E: FormatEvent<Registry, N> + 'static,
374
    F: layer::Layer<Formatter<N, E, W>> + 'static,
375
    W: for<'writer> MakeWriter<'writer> + 'static,
376
    layer::Layered<F, Formatter<N, E, W>>: tracing_core::Subscriber,
377
    fmt_layer::Layer<Registry, N, E, W>: layer::Layer<Registry>,
378
{
379
    #[inline]
380
0
    fn register_callsite(&self, meta: &'static Metadata<'static>) -> Interest {
381
0
        self.inner.register_callsite(meta)
382
0
    }
383
384
    #[inline]
385
0
    fn enabled(&self, meta: &Metadata<'_>) -> bool {
386
0
        self.inner.enabled(meta)
387
0
    }
388
389
    #[inline]
390
0
    fn new_span(&self, attrs: &span::Attributes<'_>) -> span::Id {
391
0
        self.inner.new_span(attrs)
392
0
    }
393
394
    #[inline]
395
0
    fn record(&self, span: &span::Id, values: &span::Record<'_>) {
396
0
        self.inner.record(span, values)
397
0
    }
398
399
    #[inline]
400
0
    fn record_follows_from(&self, span: &span::Id, follows: &span::Id) {
401
0
        self.inner.record_follows_from(span, follows)
402
0
    }
403
404
    #[inline]
405
0
    fn event_enabled(&self, event: &Event<'_>) -> bool {
406
0
        self.inner.event_enabled(event)
407
0
    }
408
409
    #[inline]
410
0
    fn event(&self, event: &Event<'_>) {
411
0
        self.inner.event(event);
412
0
    }
413
414
    #[inline]
415
0
    fn enter(&self, id: &span::Id) {
416
        // TODO: add on_enter hook
417
0
        self.inner.enter(id);
418
0
    }
419
420
    #[inline]
421
0
    fn exit(&self, id: &span::Id) {
422
0
        self.inner.exit(id);
423
0
    }
424
425
    #[inline]
426
0
    fn current_span(&self) -> span::Current {
427
0
        self.inner.current_span()
428
0
    }
429
430
    #[inline]
431
0
    fn clone_span(&self, id: &span::Id) -> span::Id {
432
0
        self.inner.clone_span(id)
433
0
    }
434
435
    #[inline]
436
0
    fn try_close(&self, id: span::Id) -> bool {
437
0
        self.inner.try_close(id)
438
0
    }
439
440
    #[inline]
441
0
    fn max_level_hint(&self) -> Option<tracing_core::LevelFilter> {
442
0
        self.inner.max_level_hint()
443
0
    }
444
445
0
    unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> {
446
0
        if id == TypeId::of::<Self>() {
447
0
            Some(self as *const Self as *const ())
448
        } else {
449
0
            unsafe { self.inner.downcast_raw(id) }
450
        }
451
0
    }
452
}
453
454
impl<'a, N, E, F, W> LookupSpan<'a> for Subscriber<N, E, F, W>
455
where
456
    layer::Layered<F, Formatter<N, E, W>>: LookupSpan<'a>,
457
{
458
    type Data = <layer::Layered<F, Formatter<N, E, W>> as LookupSpan<'a>>::Data;
459
460
0
    fn span_data(&'a self, id: &span::Id) -> Option<Self::Data> {
461
0
        self.inner.span_data(id)
462
0
    }
463
}
464
465
// ===== impl SubscriberBuilder =====
466
467
impl Default for SubscriberBuilder {
468
0
    fn default() -> Self {
469
0
        SubscriberBuilder {
470
0
            filter: Subscriber::DEFAULT_MAX_LEVEL,
471
0
            inner: Default::default(),
472
0
        }
473
0
        .log_internal_errors(true)
474
0
    }
475
}
476
477
impl<N, E, F, W> SubscriberBuilder<N, E, F, W>
478
where
479
    N: for<'writer> FormatFields<'writer> + 'static,
480
    E: FormatEvent<Registry, N> + 'static,
481
    W: for<'writer> MakeWriter<'writer> + 'static,
482
    F: layer::Layer<Formatter<N, E, W>> + Send + Sync + 'static,
483
    fmt_layer::Layer<Registry, N, E, W>: layer::Layer<Registry> + Send + Sync + 'static,
484
{
485
    /// Finish the builder, returning a new `FmtSubscriber`.
486
0
    pub fn finish(self) -> Subscriber<N, E, F, W> {
487
0
        let subscriber = self.inner.with_subscriber(Registry::default());
488
0
        Subscriber {
489
0
            inner: self.filter.with_subscriber(subscriber),
490
0
        }
491
0
    }
492
493
    /// Install this Subscriber as the global default if one is
494
    /// not already set.
495
    ///
496
    /// If the `tracing-log` feature is enabled, this will also install
497
    /// the LogTracer to convert `Log` records into `tracing` `Event`s.
498
    ///
499
    /// # Errors
500
    /// Returns an Error if the initialization was unsuccessful, likely
501
    /// because a global subscriber was already installed by another
502
    /// call to `try_init`.
503
0
    pub fn try_init(self) -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
504
        use crate::util::SubscriberInitExt;
505
0
        self.finish().try_init()?;
506
507
0
        Ok(())
508
0
    }
509
510
    /// Install this Subscriber as the global default.
511
    ///
512
    /// If the `tracing-log` feature is enabled, this will also install
513
    /// the LogTracer to convert `Log` records into `tracing` `Event`s.
514
    ///
515
    /// # Panics
516
    /// Panics if the initialization was unsuccessful, likely because a
517
    /// global subscriber was already installed by another call to `try_init`.
518
0
    pub fn init(self) {
519
0
        self.try_init()
520
0
            .expect("Unable to install global subscriber")
521
0
    }
522
}
523
524
impl<N, E, F, W> From<SubscriberBuilder<N, E, F, W>> for tracing_core::Dispatch
525
where
526
    N: for<'writer> FormatFields<'writer> + 'static,
527
    E: FormatEvent<Registry, N> + 'static,
528
    W: for<'writer> MakeWriter<'writer> + 'static,
529
    F: layer::Layer<Formatter<N, E, W>> + Send + Sync + 'static,
530
    fmt_layer::Layer<Registry, N, E, W>: layer::Layer<Registry> + Send + Sync + 'static,
531
{
532
0
    fn from(builder: SubscriberBuilder<N, E, F, W>) -> tracing_core::Dispatch {
533
0
        tracing_core::Dispatch::new(builder.finish())
534
0
    }
535
}
536
537
impl<N, L, T, F, W> SubscriberBuilder<N, format::Format<L, T>, F, W>
538
where
539
    N: for<'writer> FormatFields<'writer> + 'static,
540
{
541
    /// Use the given [`timer`] for log message timestamps.
542
    ///
543
    /// See the [`time` module] for the provided timer implementations.
544
    ///
545
    /// Note that using the `"time`"" feature flag enables the
546
    /// additional time formatters [`UtcTime`] and [`LocalTime`], which use the
547
    /// [`time` crate] to provide more sophisticated timestamp formatting
548
    /// options.
549
    ///
550
    /// [`timer`]: time::FormatTime
551
    /// [`time` module]: mod@time
552
    /// [`UtcTime`]: time::UtcTime
553
    /// [`LocalTime`]: time::LocalTime
554
    /// [`time` crate]: https://docs.rs/time/0.3
555
0
    pub fn with_timer<T2>(self, timer: T2) -> SubscriberBuilder<N, format::Format<L, T2>, F, W> {
556
0
        SubscriberBuilder {
557
0
            filter: self.filter,
558
0
            inner: self.inner.with_timer(timer),
559
0
        }
560
0
    }
561
562
    /// Do not emit timestamps with log messages.
563
0
    pub fn without_time(self) -> SubscriberBuilder<N, format::Format<L, ()>, F, W> {
564
0
        SubscriberBuilder {
565
0
            filter: self.filter,
566
0
            inner: self.inner.without_time(),
567
0
        }
568
0
    }
569
570
    /// Configures how synthesized events are emitted at points in the [span
571
    /// lifecycle][lifecycle].
572
    ///
573
    /// The following options are available:
574
    ///
575
    /// - `FmtSpan::NONE`: No events will be synthesized when spans are
576
    ///   created, entered, exited, or closed. Data from spans will still be
577
    ///   included as the context for formatted events. This is the default.
578
    /// - `FmtSpan::NEW`: An event will be synthesized when spans are created.
579
    /// - `FmtSpan::ENTER`: An event will be synthesized when spans are entered.
580
    /// - `FmtSpan::EXIT`: An event will be synthesized when spans are exited.
581
    /// - `FmtSpan::CLOSE`: An event will be synthesized when a span closes. If
582
    ///   [timestamps are enabled][time] for this formatter, the generated
583
    ///   event will contain fields with the span's _busy time_ (the total
584
    ///   time for which it was entered) and _idle time_ (the total time that
585
    ///   the span existed but was not entered).
586
    /// - `FmtSpan::ACTIVE`: An event will be synthesized when spans are entered
587
    ///   or exited.
588
    /// - `FmtSpan::FULL`: Events will be synthesized whenever a span is
589
    ///   created, entered, exited, or closed. If timestamps are enabled, the
590
    ///   close event will contain the span's busy and idle time, as
591
    ///   described above.
592
    ///
593
    /// The options can be enabled in any combination. For instance, the following
594
    /// will synthesize events whenever spans are created and closed:
595
    ///
596
    /// ```rust
597
    /// use tracing_subscriber::fmt::format::FmtSpan;
598
    /// use tracing_subscriber::fmt;
599
    ///
600
    /// let subscriber = fmt()
601
    ///     .with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
602
    ///     .finish();
603
    /// ```
604
    ///
605
    /// Note that the generated events will only be part of the log output by
606
    /// this formatter; they will not be recorded by other `Subscriber`s or by
607
    /// `Layer`s added to this subscriber.
608
    ///
609
    /// [lifecycle]: https://docs.rs/tracing/latest/tracing/span/index.html#the-span-lifecycle
610
    /// [time]: SubscriberBuilder::without_time()
611
0
    pub fn with_span_events(self, kind: format::FmtSpan) -> Self {
612
0
        SubscriberBuilder {
613
0
            inner: self.inner.with_span_events(kind),
614
0
            ..self
615
0
        }
616
0
    }
617
618
    /// Sets whether or not the formatter emits ANSI terminal escape codes
619
    /// for colors and other text formatting.
620
    ///
621
    /// Enabling ANSI escapes (calling `with_ansi(true)`) requires the "ansi"
622
    /// crate feature flag. Calling `with_ansi(true)` without the "ansi"
623
    /// feature flag enabled will panic if debug assertions are enabled, or
624
    /// print a warning otherwise.
625
    ///
626
    /// This method itself is still available without the feature flag. This
627
    /// is to allow ANSI escape codes to be explicitly *disabled* without
628
    /// having to opt-in to the dependencies required to emit ANSI formatting.
629
    /// This way, code which constructs a formatter that should never emit
630
    /// ANSI escape codes can ensure that they are not used, regardless of
631
    /// whether or not other crates in the dependency graph enable the "ansi"
632
    /// feature flag.
633
0
    pub fn with_ansi(self, ansi: bool) -> SubscriberBuilder<N, format::Format<L, T>, F, W> {
634
0
        SubscriberBuilder {
635
0
            inner: self.inner.with_ansi(ansi),
636
0
            ..self
637
0
        }
638
0
    }
639
640
    /// Sets whether ANSI control character sanitization is enabled.
641
    ///
642
    /// This defaults to `true` as a protective measure against terminal
643
    /// injection attacks. If this is set to `false`, ANSI sanitization is
644
    /// disabled and trusted ANSI control sequences in logged values are passed
645
    /// through unchanged.
646
0
    pub fn with_ansi_sanitization(
647
0
        self,
648
0
        ansi_sanitization: bool,
649
0
    ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> {
650
0
        SubscriberBuilder {
651
0
            inner: self.inner.with_ansi_sanitization(ansi_sanitization),
652
0
            ..self
653
0
        }
654
0
    }
655
656
    /// Sets whether to write errors from [`FormatEvent`] to the writer.
657
    /// Defaults to true.
658
    ///
659
    /// By default, `fmt::Layer` will write any `FormatEvent`-internal errors to
660
    /// the writer. These errors are unlikely and will only occur if there is a
661
    /// bug in the `FormatEvent` implementation or its dependencies.
662
    ///
663
    /// If writing to the writer fails, the error message is printed to stderr
664
    /// as a fallback.
665
    ///
666
    /// [`FormatEvent`]: crate::fmt::FormatEvent
667
0
    pub fn log_internal_errors(
668
0
        self,
669
0
        log_internal_errors: bool,
670
0
    ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> {
671
0
        SubscriberBuilder {
672
0
            inner: self.inner.log_internal_errors(log_internal_errors),
673
0
            ..self
674
0
        }
675
0
    }
676
677
    /// Sets whether or not an event's target is displayed.
678
0
    pub fn with_target(
679
0
        self,
680
0
        display_target: bool,
681
0
    ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> {
682
0
        SubscriberBuilder {
683
0
            inner: self.inner.with_target(display_target),
684
0
            ..self
685
0
        }
686
0
    }
687
688
    /// Sets whether or not an event's [source code file path][file] is
689
    /// displayed.
690
    ///
691
    /// [file]: tracing_core::Metadata::file
692
0
    pub fn with_file(
693
0
        self,
694
0
        display_filename: bool,
695
0
    ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> {
696
0
        SubscriberBuilder {
697
0
            inner: self.inner.with_file(display_filename),
698
0
            ..self
699
0
        }
700
0
    }
701
702
    /// Sets whether or not an event's [source code line number][line] is
703
    /// displayed.
704
    ///
705
    /// [line]: tracing_core::Metadata::line
706
0
    pub fn with_line_number(
707
0
        self,
708
0
        display_line_number: bool,
709
0
    ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> {
710
0
        SubscriberBuilder {
711
0
            inner: self.inner.with_line_number(display_line_number),
712
0
            ..self
713
0
        }
714
0
    }
715
716
    /// Sets whether or not an event's level is displayed.
717
0
    pub fn with_level(
718
0
        self,
719
0
        display_level: bool,
720
0
    ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> {
721
0
        SubscriberBuilder {
722
0
            inner: self.inner.with_level(display_level),
723
0
            ..self
724
0
        }
725
0
    }
726
727
    /// Sets whether or not the [name] of the current thread is displayed
728
    /// when formatting events.
729
    ///
730
    /// [name]: std::thread#naming-threads
731
0
    pub fn with_thread_names(
732
0
        self,
733
0
        display_thread_names: bool,
734
0
    ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> {
735
0
        SubscriberBuilder {
736
0
            inner: self.inner.with_thread_names(display_thread_names),
737
0
            ..self
738
0
        }
739
0
    }
740
741
    /// Sets whether or not the [thread ID] of the current thread is displayed
742
    /// when formatting events.
743
    ///
744
    /// [thread ID]: std::thread::ThreadId
745
0
    pub fn with_thread_ids(
746
0
        self,
747
0
        display_thread_ids: bool,
748
0
    ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> {
749
0
        SubscriberBuilder {
750
0
            inner: self.inner.with_thread_ids(display_thread_ids),
751
0
            ..self
752
0
        }
753
0
    }
754
755
    /// Sets the subscriber being built to use a less verbose formatter.
756
    ///
757
    /// See [`format::Compact`].
758
0
    pub fn compact(self) -> SubscriberBuilder<N, format::Format<format::Compact, T>, F, W>
759
0
    where
760
0
        N: for<'writer> FormatFields<'writer> + 'static,
761
    {
762
0
        SubscriberBuilder {
763
0
            filter: self.filter,
764
0
            inner: self.inner.compact(),
765
0
        }
766
0
    }
767
768
    /// Sets the subscriber being built to use an [excessively pretty, human-readable formatter](crate::fmt::format::Pretty).
769
    #[cfg(feature = "ansi")]
770
    #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))]
771
    pub fn pretty(
772
        self,
773
    ) -> SubscriberBuilder<format::Pretty, format::Format<format::Pretty, T>, F, W> {
774
        SubscriberBuilder {
775
            filter: self.filter,
776
            inner: self.inner.pretty(),
777
        }
778
    }
779
780
    /// Sets the subscriber being built to use a JSON formatter.
781
    ///
782
    /// See [`format::Json`] for details.
783
    #[cfg(feature = "json")]
784
    #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
785
    pub fn json(
786
        self,
787
    ) -> SubscriberBuilder<format::JsonFields, format::Format<format::Json, T>, F, W>
788
    where
789
        N: for<'writer> FormatFields<'writer> + 'static,
790
    {
791
        SubscriberBuilder {
792
            filter: self.filter,
793
            inner: self.inner.json(),
794
        }
795
    }
796
}
797
798
#[cfg(feature = "json")]
799
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
800
impl<T, F, W> SubscriberBuilder<format::JsonFields, format::Format<format::Json, T>, F, W> {
801
    /// Sets the json subscriber being built to flatten event metadata.
802
    ///
803
    /// See [`format::Json`] for details.
804
    pub fn flatten_event(
805
        self,
806
        flatten_event: bool,
807
    ) -> SubscriberBuilder<format::JsonFields, format::Format<format::Json, T>, F, W> {
808
        SubscriberBuilder {
809
            filter: self.filter,
810
            inner: self.inner.flatten_event(flatten_event),
811
        }
812
    }
813
814
    /// Sets whether or not the JSON subscriber being built will include the current span
815
    /// in formatted events.
816
    ///
817
    /// See [`format::Json`] for details.
818
    pub fn with_current_span(
819
        self,
820
        display_current_span: bool,
821
    ) -> SubscriberBuilder<format::JsonFields, format::Format<format::Json, T>, F, W> {
822
        SubscriberBuilder {
823
            filter: self.filter,
824
            inner: self.inner.with_current_span(display_current_span),
825
        }
826
    }
827
828
    /// Sets whether or not the JSON subscriber being built will include a list (from
829
    /// root to leaf) of all currently entered spans in formatted events.
830
    ///
831
    /// See [`format::Json`] for details.
832
    pub fn with_span_list(
833
        self,
834
        display_span_list: bool,
835
    ) -> SubscriberBuilder<format::JsonFields, format::Format<format::Json, T>, F, W> {
836
        SubscriberBuilder {
837
            filter: self.filter,
838
            inner: self.inner.with_span_list(display_span_list),
839
        }
840
    }
841
}
842
843
#[cfg(feature = "env-filter")]
844
#[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))]
845
impl<N, E, W> SubscriberBuilder<N, E, crate::EnvFilter, W>
846
where
847
    Formatter<N, E, W>: tracing_core::Subscriber + 'static,
848
{
849
    /// Configures the subscriber being built to allow filter reloading at
850
    /// runtime.
851
    pub fn with_filter_reloading(
852
        self,
853
    ) -> SubscriberBuilder<N, E, crate::reload::Layer<crate::EnvFilter, Formatter<N, E, W>>, W>
854
    {
855
        let (filter, _) = crate::reload::Layer::new(self.filter);
856
        SubscriberBuilder {
857
            filter,
858
            inner: self.inner,
859
        }
860
    }
861
}
862
863
#[cfg(feature = "env-filter")]
864
#[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))]
865
impl<N, E, W> SubscriberBuilder<N, E, crate::reload::Layer<crate::EnvFilter, Formatter<N, E, W>>, W>
866
where
867
    Formatter<N, E, W>: tracing_core::Subscriber + 'static,
868
{
869
    /// Returns a `Handle` that may be used to reload the constructed subscriber's
870
    /// filter.
871
    pub fn reload_handle(&self) -> crate::reload::Handle<crate::EnvFilter, Formatter<N, E, W>> {
872
        self.filter.handle()
873
    }
874
}
875
876
impl<N, E, F, W> SubscriberBuilder<N, E, F, W> {
877
    /// Sets the field formatter that the subscriber being built will use to record
878
    /// fields.
879
    ///
880
    /// For example:
881
    /// ```rust
882
    /// use tracing_subscriber::fmt::format;
883
    /// use tracing_subscriber::prelude::*;
884
    ///
885
    /// let formatter =
886
    ///     // Construct a custom formatter for `Debug` fields
887
    ///     format::debug_fn(|writer, field, value| write!(writer, "{}: {:?}", field, value))
888
    ///         // Use the `tracing_subscriber::MakeFmtExt` trait to wrap the
889
    ///         // formatter so that a delimiter is added between fields.
890
    ///         .delimited(", ");
891
    ///
892
    /// let subscriber = tracing_subscriber::fmt()
893
    ///     .fmt_fields(formatter)
894
    ///     .finish();
895
    /// # drop(subscriber)
896
    /// ```
897
0
    pub fn fmt_fields<N2>(self, fmt_fields: N2) -> SubscriberBuilder<N2, E, F, W>
898
0
    where
899
0
        N2: for<'writer> FormatFields<'writer> + 'static,
900
    {
901
0
        SubscriberBuilder {
902
0
            filter: self.filter,
903
0
            inner: self.inner.fmt_fields(fmt_fields),
904
0
        }
905
0
    }
906
907
    /// Sets the [`EnvFilter`] that the subscriber will use to determine if
908
    /// a span or event is enabled.
909
    ///
910
    /// Note that this method requires the "env-filter" feature flag to be enabled.
911
    ///
912
    /// If a filter was previously set, or a maximum level was set by the
913
    /// [`with_max_level`] method, that value is replaced by the new filter.
914
    ///
915
    /// # Examples
916
    ///
917
    /// Setting a filter based on the value of the `RUST_LOG` environment
918
    /// variable:
919
    /// ```rust
920
    /// use tracing_subscriber::{fmt, EnvFilter};
921
    ///
922
    /// fmt()
923
    ///     .with_env_filter(EnvFilter::from_default_env())
924
    ///     .init();
925
    /// ```
926
    ///
927
    /// Setting a filter based on a pre-set filter directive string:
928
    /// ```rust
929
    /// use tracing_subscriber::fmt;
930
    ///
931
    /// fmt()
932
    ///     .with_env_filter("my_crate=info,my_crate::my_mod=debug,[my_span]=trace")
933
    ///     .init();
934
    /// ```
935
    ///
936
    /// Adding additional directives to a filter constructed from an env var:
937
    /// ```rust
938
    /// use tracing_subscriber::{fmt, filter::{EnvFilter, LevelFilter}};
939
    ///
940
    /// # fn filter() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
941
    /// let filter = EnvFilter::try_from_env("MY_CUSTOM_FILTER_ENV_VAR")?
942
    ///     // Set the base level when not matched by other directives to WARN.
943
    ///     .add_directive(LevelFilter::WARN.into())
944
    ///     // Set the max level for `my_crate::my_mod` to DEBUG, overriding
945
    ///     // any directives parsed from the env variable.
946
    ///     .add_directive("my_crate::my_mod=debug".parse()?);
947
    ///
948
    /// fmt()
949
    ///     .with_env_filter(filter)
950
    ///     .try_init()?;
951
    /// # Ok(())}
952
    /// ```
953
    /// [`EnvFilter`]: super::filter::EnvFilter
954
    /// [`with_max_level`]: SubscriberBuilder::with_max_level()
955
    #[cfg(feature = "env-filter")]
956
    #[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))]
957
    pub fn with_env_filter(
958
        self,
959
        filter: impl Into<crate::EnvFilter>,
960
    ) -> SubscriberBuilder<N, E, crate::EnvFilter, W>
961
    where
962
        Formatter<N, E, W>: tracing_core::Subscriber + 'static,
963
    {
964
        let filter = filter.into();
965
        SubscriberBuilder {
966
            filter,
967
            inner: self.inner,
968
        }
969
    }
970
971
    /// Sets the maximum [verbosity level] that will be enabled by the
972
    /// subscriber.
973
    ///
974
    /// If the max level has already been set, or a [`EnvFilter`] was added by
975
    /// [`with_env_filter`], this replaces that configuration with the new
976
    /// maximum level.
977
    ///
978
    /// # Examples
979
    ///
980
    /// Enable up to the `DEBUG` verbosity level:
981
    /// ```rust
982
    /// use tracing_subscriber::fmt;
983
    /// use tracing::Level;
984
    ///
985
    /// fmt()
986
    ///     .with_max_level(Level::DEBUG)
987
    ///     .init();
988
    /// ```
989
    /// This subscriber won't record any spans or events!
990
    /// ```rust
991
    /// use tracing_subscriber::{fmt, filter::LevelFilter};
992
    ///
993
    /// let subscriber = fmt()
994
    ///     .with_max_level(LevelFilter::OFF)
995
    ///     .finish();
996
    /// ```
997
    /// [verbosity level]: tracing_core::Level
998
    /// [`EnvFilter`]: struct@crate::filter::EnvFilter
999
    /// [`with_env_filter`]: fn@Self::with_env_filter
1000
0
    pub fn with_max_level(
1001
0
        self,
1002
0
        filter: impl Into<LevelFilter>,
1003
0
    ) -> SubscriberBuilder<N, E, LevelFilter, W> {
1004
0
        let filter = filter.into();
1005
0
        SubscriberBuilder {
1006
0
            filter,
1007
0
            inner: self.inner,
1008
0
        }
1009
0
    }
1010
1011
    /// Sets the [event formatter][`FormatEvent`] that the subscriber being built
1012
    /// will use to format events that occur.
1013
    ///
1014
    /// The event formatter may be any type implementing the [`FormatEvent`]
1015
    /// trait, which is implemented for all functions taking a [`FmtContext`], a
1016
    /// [`Writer`], and an [`Event`].
1017
    ///
1018
    /// # Examples
1019
    ///
1020
    /// Setting a type implementing [`FormatEvent`] as the formatter:
1021
    ///
1022
    /// ```rust
1023
    /// use tracing_subscriber::fmt::format;
1024
    ///
1025
    /// let subscriber = tracing_subscriber::fmt()
1026
    ///     .event_format(format().compact())
1027
    ///     .finish();
1028
    /// ```
1029
    ///
1030
    /// [`Writer`]: struct@self::format::Writer
1031
0
    pub fn event_format<E2>(self, fmt_event: E2) -> SubscriberBuilder<N, E2, F, W>
1032
0
    where
1033
0
        E2: FormatEvent<Registry, N> + 'static,
1034
0
        N: for<'writer> FormatFields<'writer> + 'static,
1035
0
        W: for<'writer> MakeWriter<'writer> + 'static,
1036
    {
1037
0
        SubscriberBuilder {
1038
0
            filter: self.filter,
1039
0
            inner: self.inner.event_format(fmt_event),
1040
0
        }
1041
0
    }
1042
1043
    /// Sets the [`MakeWriter`] that the subscriber being built will use to write events.
1044
    ///
1045
    /// # Examples
1046
    ///
1047
    /// Using `stderr` rather than `stdout`:
1048
    ///
1049
    /// ```rust
1050
    /// use tracing_subscriber::fmt;
1051
    /// use std::io;
1052
    ///
1053
    /// fmt()
1054
    ///     .with_writer(io::stderr)
1055
    ///     .init();
1056
    /// ```
1057
0
    pub fn with_writer<W2>(self, make_writer: W2) -> SubscriberBuilder<N, E, F, W2>
1058
0
    where
1059
0
        W2: for<'writer> MakeWriter<'writer> + 'static,
1060
    {
1061
0
        SubscriberBuilder {
1062
0
            filter: self.filter,
1063
0
            inner: self.inner.with_writer(make_writer),
1064
0
        }
1065
0
    }
1066
1067
    /// Configures the subscriber to support [`libtest`'s output capturing][capturing] when used in
1068
    /// unit tests.
1069
    ///
1070
    /// See [`TestWriter`] for additional details.
1071
    ///
1072
    /// # Examples
1073
    ///
1074
    /// Using [`TestWriter`] to let `cargo test` capture test output. Note that we do not install it
1075
    /// globally as it may cause conflicts.
1076
    ///
1077
    /// ```rust
1078
    /// use tracing_subscriber::fmt;
1079
    /// use tracing::subscriber;
1080
    ///
1081
    /// subscriber::set_default(
1082
    ///     fmt()
1083
    ///         .with_test_writer()
1084
    ///         .finish()
1085
    /// );
1086
    /// ```
1087
    ///
1088
    /// [capturing]:
1089
    /// https://doc.rust-lang.org/book/ch11-02-running-tests.html#showing-function-output
1090
    /// [`TestWriter`]: writer::TestWriter
1091
0
    pub fn with_test_writer(self) -> SubscriberBuilder<N, E, F, TestWriter> {
1092
0
        SubscriberBuilder {
1093
0
            filter: self.filter,
1094
0
            inner: self.inner.with_writer(TestWriter::default()),
1095
0
        }
1096
0
    }
1097
1098
    /// Updates the event formatter by applying a function to the existing event formatter.
1099
    ///
1100
    /// This sets the event formatter that the subscriber being built will use to record fields.
1101
    ///
1102
    /// # Examples
1103
    ///
1104
    /// Updating an event formatter:
1105
    ///
1106
    /// ```rust
1107
    /// let subscriber = tracing_subscriber::fmt()
1108
    ///     .map_event_format(|e| e.compact())
1109
    ///     .finish();
1110
    /// ```
1111
0
    pub fn map_event_format<E2>(self, f: impl FnOnce(E) -> E2) -> SubscriberBuilder<N, E2, F, W>
1112
0
    where
1113
0
        E2: FormatEvent<Registry, N> + 'static,
1114
0
        N: for<'writer> FormatFields<'writer> + 'static,
1115
0
        W: for<'writer> MakeWriter<'writer> + 'static,
1116
    {
1117
0
        SubscriberBuilder {
1118
0
            filter: self.filter,
1119
0
            inner: self.inner.map_event_format(f),
1120
0
        }
1121
0
    }
1122
1123
    /// Updates the field formatter by applying a function to the existing field formatter.
1124
    ///
1125
    /// This sets the field formatter that the subscriber being built will use to record fields.
1126
    ///
1127
    /// # Examples
1128
    ///
1129
    /// Updating a field formatter:
1130
    ///
1131
    /// ```rust
1132
    /// use tracing_subscriber::field::MakeExt;
1133
    /// let subscriber = tracing_subscriber::fmt()
1134
    ///     .map_fmt_fields(|f| f.debug_alt())
1135
    ///     .finish();
1136
    /// ```
1137
0
    pub fn map_fmt_fields<N2>(self, f: impl FnOnce(N) -> N2) -> SubscriberBuilder<N2, E, F, W>
1138
0
    where
1139
0
        N2: for<'writer> FormatFields<'writer> + 'static,
1140
    {
1141
0
        SubscriberBuilder {
1142
0
            filter: self.filter,
1143
0
            inner: self.inner.map_fmt_fields(f),
1144
0
        }
1145
0
    }
1146
1147
    /// Updates the [`MakeWriter`] by applying a function to the existing [`MakeWriter`].
1148
    ///
1149
    /// This sets the [`MakeWriter`] that the subscriber being built will use to write events.
1150
    ///
1151
    /// # Examples
1152
    ///
1153
    /// Redirect output to stderr if level is <= WARN:
1154
    ///
1155
    /// ```rust
1156
    /// use tracing::Level;
1157
    /// use tracing_subscriber::fmt::{self, writer::MakeWriterExt};
1158
    ///
1159
    /// let stderr = std::io::stderr.with_max_level(Level::WARN);
1160
    /// let layer = tracing_subscriber::fmt()
1161
    ///     .map_writer(move |w| stderr.or_else(w))
1162
    ///     .finish();
1163
    /// ```
1164
0
    pub fn map_writer<W2>(self, f: impl FnOnce(W) -> W2) -> SubscriberBuilder<N, E, F, W2>
1165
0
    where
1166
0
        W2: for<'writer> MakeWriter<'writer> + 'static,
1167
    {
1168
0
        SubscriberBuilder {
1169
0
            filter: self.filter,
1170
0
            inner: self.inner.map_writer(f),
1171
0
        }
1172
0
    }
1173
}
1174
1175
/// Install a global tracing subscriber that listens for events and
1176
/// filters based on the value of the [`RUST_LOG` environment variable],
1177
/// if one is not already set.
1178
///
1179
/// If the `tracing-log` feature is enabled, this will also install
1180
/// the [`LogTracer`] to convert `log` records into `tracing` `Event`s.
1181
///
1182
/// This is shorthand for
1183
///
1184
/// ```rust
1185
/// # fn doc() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
1186
/// tracing_subscriber::fmt().try_init()
1187
/// # }
1188
/// ```
1189
///
1190
///
1191
/// # Errors
1192
///
1193
/// Returns an Error if the initialization was unsuccessful,
1194
/// likely because a global subscriber was already installed by another
1195
/// call to `try_init`.
1196
///
1197
/// [`LogTracer`]:
1198
///     https://docs.rs/tracing-log/0.1.0/tracing_log/struct.LogTracer.html
1199
/// [`RUST_LOG` environment variable]: crate::filter::EnvFilter::DEFAULT_ENV
1200
0
pub fn try_init() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
1201
0
    let builder = Subscriber::builder();
1202
1203
    #[cfg(feature = "env-filter")]
1204
    let builder = builder.with_env_filter(crate::EnvFilter::from_default_env());
1205
1206
    // If `env-filter` is disabled, remove the default max level filter from the
1207
    // subscriber; it will be added to the `Targets` filter instead if no filter
1208
    // is set in `RUST_LOG`.
1209
    // Replacing the default `LevelFilter` with an `EnvFilter` would imply this,
1210
    // but we can't replace the builder's filter with a `Targets` filter yet.
1211
    #[cfg(not(feature = "env-filter"))]
1212
0
    let builder = builder.with_max_level(LevelFilter::TRACE);
1213
1214
0
    let subscriber = builder.finish();
1215
    #[cfg(not(feature = "env-filter"))]
1216
0
    let subscriber = {
1217
        use crate::{filter::Targets, layer::SubscriberExt};
1218
        use std::{env, eprintln, str::FromStr};
1219
0
        let targets = match env::var("RUST_LOG") {
1220
0
            Ok(var) => Targets::from_str(&var)
1221
0
                .map_err(|e| {
1222
0
                    eprintln!("Ignoring `RUST_LOG={:?}`: {}", var, e);
1223
0
                })
1224
0
                .unwrap_or_default(),
1225
            Err(env::VarError::NotPresent) => {
1226
0
                Targets::new().with_default(Subscriber::DEFAULT_MAX_LEVEL)
1227
            }
1228
0
            Err(e) => {
1229
0
                eprintln!("Ignoring `RUST_LOG`: {}", e);
1230
0
                Targets::new().with_default(Subscriber::DEFAULT_MAX_LEVEL)
1231
            }
1232
        };
1233
0
        subscriber.with(targets)
1234
    };
1235
1236
0
    subscriber.try_init().map_err(Into::into)
1237
0
}
1238
1239
/// Install a global tracing subscriber that listens for events and
1240
/// filters based on the value of the [`RUST_LOG` environment variable].
1241
///
1242
/// The configuration of the subscriber initialized by this function
1243
/// depends on what [feature flags](crate#feature-flags) are enabled.
1244
///
1245
/// If the `tracing-log` feature is enabled, this will also install
1246
/// the LogTracer to convert `Log` records into `tracing` `Event`s.
1247
///
1248
/// If the `env-filter` feature is enabled, this is shorthand for
1249
///
1250
/// ```rust
1251
/// # use tracing_subscriber::EnvFilter;
1252
/// tracing_subscriber::fmt()
1253
///     .with_env_filter(EnvFilter::from_default_env())
1254
///     .init();
1255
/// ```
1256
///
1257
/// # Panics
1258
/// Panics if the initialization was unsuccessful, likely because a
1259
/// global subscriber was already installed by another call to `try_init`.
1260
///
1261
/// [`RUST_LOG` environment variable]: crate::filter::EnvFilter::DEFAULT_ENV
1262
0
pub fn init() {
1263
0
    try_init().expect("Unable to install global subscriber")
1264
0
}
1265
1266
#[cfg(test)]
1267
mod test {
1268
    use crate::{
1269
        filter::LevelFilter,
1270
        fmt::{
1271
            format::{self, Format},
1272
            time,
1273
            writer::MakeWriter,
1274
            Subscriber,
1275
        },
1276
    };
1277
    use alloc::{borrow::ToOwned, string::String, vec::Vec};
1278
    use std::{
1279
        io,
1280
        sync::{Arc, Mutex, MutexGuard, TryLockError},
1281
    };
1282
    use tracing_core::dispatcher::Dispatch;
1283
1284
    pub(crate) struct MockWriter {
1285
        buf: Arc<Mutex<Vec<u8>>>,
1286
    }
1287
1288
    impl MockWriter {
1289
        pub(crate) fn new(buf: Arc<Mutex<Vec<u8>>>) -> Self {
1290
            Self { buf }
1291
        }
1292
1293
        pub(crate) fn map_error<Guard>(err: TryLockError<Guard>) -> io::Error {
1294
            match err {
1295
                TryLockError::WouldBlock => io::Error::from(io::ErrorKind::WouldBlock),
1296
                TryLockError::Poisoned(_) => io::Error::from(io::ErrorKind::Other),
1297
            }
1298
        }
1299
1300
        pub(crate) fn buf(&self) -> io::Result<MutexGuard<'_, Vec<u8>>> {
1301
            self.buf.try_lock().map_err(Self::map_error)
1302
        }
1303
    }
1304
1305
    impl io::Write for MockWriter {
1306
        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1307
            self.buf()?.write(buf)
1308
        }
1309
1310
        fn flush(&mut self) -> io::Result<()> {
1311
            self.buf()?.flush()
1312
        }
1313
    }
1314
1315
    #[derive(Clone, Default)]
1316
    pub(crate) struct MockMakeWriter {
1317
        buf: Arc<Mutex<Vec<u8>>>,
1318
    }
1319
1320
    impl MockMakeWriter {
1321
        pub(crate) fn new(buf: Arc<Mutex<Vec<u8>>>) -> Self {
1322
            Self { buf }
1323
        }
1324
1325
        // this is currently only used by the JSON formatter tests. if we need
1326
        // it elsewhere in the future, feel free to remove the `#[cfg]`
1327
        // attribute!
1328
        #[cfg(feature = "json")]
1329
        pub(crate) fn buf(&self) -> MutexGuard<'_, Vec<u8>> {
1330
            self.buf.lock().unwrap()
1331
        }
1332
1333
        pub(crate) fn get_string(&self) -> String {
1334
            let mut buf = self.buf.lock().expect("lock shouldn't be poisoned");
1335
            let string = std::str::from_utf8(&buf[..])
1336
                .expect("formatter should not have produced invalid utf-8")
1337
                .to_owned();
1338
            buf.clear();
1339
            string
1340
        }
1341
    }
1342
1343
    impl<'a> MakeWriter<'a> for MockMakeWriter {
1344
        type Writer = MockWriter;
1345
1346
        fn make_writer(&'a self) -> Self::Writer {
1347
            MockWriter::new(self.buf.clone())
1348
        }
1349
    }
1350
1351
    #[test]
1352
    fn impls() {
1353
        let f = Format::default().with_timer(time::Uptime::default());
1354
        let subscriber = Subscriber::builder().event_format(f).finish();
1355
        let _dispatch = Dispatch::new(subscriber);
1356
1357
        let f = format::Format::default();
1358
        let subscriber = Subscriber::builder().event_format(f).finish();
1359
        let _dispatch = Dispatch::new(subscriber);
1360
1361
        let f = format::Format::default().compact();
1362
        let subscriber = Subscriber::builder().event_format(f).finish();
1363
        let _dispatch = Dispatch::new(subscriber);
1364
    }
1365
1366
    #[test]
1367
    fn subscriber_downcasts() {
1368
        let subscriber = Subscriber::builder().finish();
1369
        let dispatch = Dispatch::new(subscriber);
1370
        assert!(dispatch.downcast_ref::<Subscriber>().is_some());
1371
    }
1372
1373
    #[test]
1374
    fn subscriber_downcasts_to_parts() {
1375
        let subscriber = Subscriber::new();
1376
        let dispatch = Dispatch::new(subscriber);
1377
        assert!(dispatch.downcast_ref::<format::DefaultFields>().is_some());
1378
        assert!(dispatch.downcast_ref::<LevelFilter>().is_some());
1379
        assert!(dispatch.downcast_ref::<format::Format>().is_some())
1380
    }
1381
1382
    #[test]
1383
    fn is_lookup_span() {
1384
        fn assert_lookup_span<T: for<'a> crate::registry::LookupSpan<'a>>(_: T) {}
1385
        let subscriber = Subscriber::new();
1386
        assert_lookup_span(subscriber)
1387
    }
1388
}