tracing_subscriber_init/format/
pretty.rs

1// Copyright (c) 2023 tracing-subscriber-init developers
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9use tracing::{Subscriber, metadata::LevelFilter};
10use tracing_subscriber::{
11    Layer,
12    filter::Filtered,
13    fmt::{
14        self,
15        format::{Format, Pretty},
16    },
17};
18
19use crate::{TracingConfig, utils::get_effective_level};
20
21/// Create a [`Pretty`](tracing_subscriber::fmt::format::Pretty) format layer configured from the given [`TracingConfig`].
22///
23/// # Example
24/// ```rust
25/// # use anyhow::Result;
26/// # use tracing::info;
27/// # use tracing_subscriber::Layer;
28/// # use tracing_subscriber_init::{pretty, set_default, TestAll, TracingConfig};
29/// #
30/// # pub fn main() -> Result<()> {
31/// let config = TestAll;
32/// let (layer, level_filter) = pretty(&config);
33/// let layer = layer.with_filter(level_filter);
34/// let _unused = set_default(vec![layer.boxed()]);
35/// info!("info level");
36/// #   Ok(())
37/// # }
38/// ```
39pub fn pretty<C, S>(config: &C) -> (fmt::Layer<S, Pretty, Format<Pretty>>, LevelFilter)
40where
41    C: TracingConfig,
42    S: Subscriber,
43    for<'a> S: tracing_subscriber::registry::LookupSpan<'a>,
44{
45    let layer = fmt::layer()
46        .pretty()
47        .with_ansi(config.with_ansi())
48        .with_file(config.with_file())
49        .with_level(config.with_level())
50        .with_target(config.with_target())
51        .with_thread_ids(config.with_thread_ids())
52        .with_thread_names(config.with_thread_names())
53        .with_line_number(config.with_line_number());
54    let layer = if let Some(fmt_span) = config.with_span_events() {
55        layer.with_span_events(fmt_span)
56    } else {
57        layer
58    };
59    let level = get_effective_level(config.quiet(), config.verbose());
60    let level_filter = LevelFilter::from(level);
61    (layer, level_filter)
62}
63
64/// Create a [`Pretty`](tracing_subscriber::fmt::format::Pretty) format filtered layer configured from the given [`TracingConfig`].
65///
66/// # Example
67/// ```rust
68/// # use anyhow::Result;
69/// # use tracing::info;
70/// # use tracing_subscriber::Layer;
71/// # use tracing_subscriber_init::{pretty_filtered, set_default, TestAll, TracingConfig};
72/// #
73/// # pub fn main() -> Result<()> {
74/// let config = TestAll;
75/// let layer = pretty_filtered(&config);
76/// let _unused = set_default(vec![layer.boxed()]);
77/// info!("info level");
78/// #   Ok(())
79/// # }
80/// ```
81pub fn filtered<C, S>(config: &C) -> Filtered<fmt::Layer<S, Pretty, Format<Pretty>>, LevelFilter, S>
82where
83    C: TracingConfig,
84    S: Subscriber,
85    for<'a> S: tracing_subscriber::registry::LookupSpan<'a>,
86{
87    let (layer, level_filter) = pretty(config);
88    layer.with_filter(level_filter)
89}
90
91#[cfg(test)]
92mod test {
93    use tracing::{Level, debug, error, info, span, trace, warn};
94    use tracing_subscriber::Layer;
95
96    use super::filtered as pretty_filtered;
97
98    use crate::{TestAll, set_default, utils::test::TestConfig};
99
100    #[test]
101    fn pretty_filtered_works() {
102        let config = TestConfig;
103        let layer = pretty_filtered(&config);
104        let _unused = set_default(vec![layer.boxed()]);
105        let span = span!(Level::INFO, "pretty_filtered_works");
106        let _enter = span.enter();
107        error!("error level");
108        warn!("warn level");
109        info!("info level");
110        debug!("debug level");
111        trace!("trace level");
112    }
113
114    #[test]
115    fn pretty_filtered_all_works() {
116        let config = TestAll;
117        let layer = pretty_filtered(&config);
118        let _unused = set_default(vec![layer.boxed()]);
119        let span = span!(Level::TRACE, "pretty_filtered_all_works");
120        let _enter = span.enter();
121        error!("error level");
122        warn!("warn level");
123        info!("info level");
124        debug!("debug level");
125        trace!("trace level");
126    }
127
128    #[cfg(feature = "tstime")]
129    #[test]
130    fn pretty_utc_works() {
131        use super::pretty;
132        use time::format_description::well_known::Iso8601;
133        use tracing_subscriber::fmt::time::UtcTime;
134
135        let config = TestConfig;
136        let (layer, level_filter) = pretty(&config);
137        let filtered_layer = layer
138            .with_timer(UtcTime::new(Iso8601::DEFAULT))
139            .with_filter(level_filter);
140        let _unused = set_default(vec![filtered_layer.boxed()]);
141        let span = span!(Level::INFO, "pretty_utc_works");
142        let _enter = span.enter();
143        error!("error level");
144        warn!("warn level");
145        info!("info level");
146        debug!("debug level");
147        trace!("trace level");
148    }
149}