env_logger/
lib.rs

1// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
4// option. This file may not be copied, modified, or distributed
5// except according to those terms.
6
7//! A simple logger that can be configured via environment variables, for use
8//! with the logging facade exposed by the [`log` crate][log-crate-url].
9//!
10//! Despite having "env" in its name, **`env_logger`** can also be configured by
11//! other means besides environment variables. See [the examples][gh-repo-examples]
12//! in the source repository for more approaches.
13//!
14//! By default, `env_logger` writes logs to `stderr`, but can be configured to
15//! instead write them to `stdout`.
16//!
17//! ## Example
18//!
19//! ```
20//! use log::{debug, error, log_enabled, info, Level};
21//!
22//! env_logger::init();
23//!
24//! debug!("this is a debug {}", "message");
25//! error!("this is printed by default");
26//!
27//! if log_enabled!(Level::Info) {
28//!     let x = 3 * 4; // expensive computation
29//!     info!("the answer was: {}", x);
30//! }
31//! ```
32//!
33//! Assumes the binary is `main`:
34//!
35//! ```{.bash}
36//! $ RUST_LOG=error ./main
37//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
38//! ```
39//!
40//! ```{.bash}
41//! $ RUST_LOG=info ./main
42//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
43//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
44//! ```
45//!
46//! ```{.bash}
47//! $ RUST_LOG=debug ./main
48//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message
49//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
50//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
51//! ```
52//!
53//! You can also set the log level on a per module basis:
54//!
55//! ```{.bash}
56//! $ RUST_LOG=main=info ./main
57//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
58//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
59//! ```
60//!
61//! And enable all logging:
62//!
63//! ```{.bash}
64//! $ RUST_LOG=main ./main
65//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message
66//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
67//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
68//! ```
69//!
70//! If the binary name contains hyphens, you will need to replace
71//! them with underscores:
72//!
73//! ```{.bash}
74//! $ RUST_LOG=my_app ./my-app
75//! [2017-11-09T02:12:24Z DEBUG my_app] this is a debug message
76//! [2017-11-09T02:12:24Z ERROR my_app] this is printed by default
77//! [2017-11-09T02:12:24Z INFO my_app] the answer was: 12
78//! ```
79//!
80//! This is because Rust modules and crates cannot contain hyphens
81//! in their name, although `cargo` continues to accept them.
82//!
83//! See the documentation for the [`log` crate][log-crate-url] for more
84//! information about its API.
85//!
86//! ## Enabling logging
87//!
88//! Log levels are controlled on a per-module basis, and **by default all
89//! logging is disabled except for the `error` level**.
90//!
91//! Logging is controlled via the **`RUST_LOG`** environment variable. The
92//! value of this environment variable is a comma-separated list of *logging
93//! directives*. A logging directive is of the form:
94//!
95//! ```text
96//! example::log::target=level
97//! ```
98//!
99//! The log target is typically equal to the path of the module the message
100//! in question originated from, though it can be overriden.
101//!
102//! The path is rooted in the name of the crate it was compiled for, so if
103//! your program is in a file called, for example, `hello.rs`, the path would
104//! simply be be `hello`.
105//!
106//! Furthermore, the log can be filtered using prefix-search based on the
107//! specified log target. A value of, for example, `RUST_LOG=example`, would
108//! match all of the messages with targets:
109//!
110//! * `example`
111//! * `example::test`
112//! * `example::test::module::submodule`
113//! * `examples::and_more_examples`
114//!
115//! When providing the crate name or a module path, explicitly specifying the
116//! log level is optional. If omitted, all logging for the item will be
117//! enabled.
118//!
119//! The names of the log levels that may be specified correspond to the
120//! variations of the [`log::Level`][level-enum] enum from the `log`
121//! crate. They are:
122//!
123//! * `error`
124//! * `warn`
125//! * `info`
126//! * `debug`
127//! * `trace`
128//!
129//! There is also a pseudo logging level, `off`, which may be specified to
130//! disable all logging for a given module or for the entire application. As
131//! with the logging levels, the letter case is not significant[^fn-off].
132//!
133//! [^fn-off]: Similar to the universe of log level names, the `off` pseudo
134//!    log level feature is also provided by the underlying `log` crate.
135//!
136//! The letter case is not significant for the logging level names; e.g.,
137//! `debug`, `DEBUG`, and `dEbuG` all represent the same logging level. For
138//! consistency, our convention is to use the lower case names. Where our docs
139//! do use other forms, they do so in the context of specific examples, so you
140//! won't be surprised if you see similar usage in the wild.
141//!
142//! As the log level for a module is optional, the module to enable logging for
143//! is also optional. **If only a level is provided, then the global log
144//! level for all modules is set to this value.**
145//!
146//! Some examples of valid values of `RUST_LOG` are:
147//!
148//! * `hello` turns on all logging for the 'hello' module
149//! * `trace` turns on all logging for the application, regardless of its name
150//! * `TRACE` turns on all logging for the application, regardless of its name (same as previous)
151//! * `info` turns on all info logging
152//! * `INFO` turns on all info logging (same as previous)
153//! * `hello=debug` turns on debug logging for 'hello'
154//! * `hello=DEBUG` turns on debug logging for 'hello' (same as previous)
155//! * `hello,std::option` turns on hello, and std's option logging
156//! * `error,hello=warn` turn on global error logging and also warn for hello
157//! * `error,hello=off`  turn on global error logging, but turn off logging for hello
158//! * `off` turns off all logging for the application
159//! * `OFF` turns off all logging for the application (same as previous)
160//!
161//! ## Filtering results
162//!
163//! A `RUST_LOG` directive may include a regex filter. The syntax is to append `/`
164//! followed by a regex. Each message is checked against the regex, and is only
165//! logged if it matches. Note that the matching is done after formatting the
166//! log string but before adding any logging meta-data. There is a single filter
167//! for all modules.
168//!
169//! Some examples:
170//!
171//! * `hello/foo` turns on all logging for the 'hello' module where the log
172//!   message includes 'foo'.
173//! * `info/f.o` turns on all info logging where the log message includes 'foo',
174//!   'f1o', 'fao', etc.
175//! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the log
176//!   message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc.
177//! * `error,hello=warn/[0-9]scopes` turn on global error logging and also
178//!   warn for hello. In both cases the log message must include a single digit
179//!   number followed by 'scopes'.
180//!
181//! ## Capturing logs in tests
182//!
183//! Records logged during `cargo test` will not be captured by the test harness by default.
184//! The [`Builder::is_test`] method can be used in unit tests to ensure logs will be captured:
185//!
186//! ```
187//! # #[macro_use] extern crate log;
188//! #[cfg(test)]
189//! mod tests {
190//!     fn init() {
191//!         let _ = env_logger::builder().is_test(true).try_init();
192//!     }
193//!
194//!     #[test]
195//!     fn it_works() {
196//!         init();
197//!
198//!         info!("This record will be captured by `cargo test`");
199//!
200//!         assert_eq!(2, 1 + 1);
201//!     }
202//! }
203//! ```
204//!
205//! Enabling test capturing comes at the expense of color and other style support
206//! and may have performance implications.
207//!
208//! ## Disabling colors
209//!
210//! Colors and other styles can be configured with the `RUST_LOG_STYLE`
211//! environment variable. It accepts the following values:
212//!
213//! * `auto` (default) will attempt to print style characters, but don't force the issue.
214//! If the console isn't available on Windows, or if TERM=dumb, for example, then don't print colors.
215//! * `always` will always print style characters even if they aren't supported by the terminal.
216//! This includes emitting ANSI colors on Windows if the console API is unavailable.
217//! * `never` will never print style characters.
218//!
219//! ## Tweaking the default format
220//!
221//! Parts of the default format can be excluded from the log output using the [`Builder`].
222//! The following example excludes the timestamp from the log output:
223//!
224//! ```
225//! env_logger::builder()
226//!     .format_timestamp(None)
227//!     .init();
228//! ```
229//!
230//! ### Stability of the default format
231//!
232//! The default format won't optimise for long-term stability, and explicitly makes no
233//! guarantees about the stability of its output across major, minor or patch version
234//! bumps during `0.x`.
235//!
236//! If you want to capture or interpret the output of `env_logger` programmatically
237//! then you should use a custom format.
238//!
239//! ### Using a custom format
240//!
241//! Custom formats can be provided as closures to the [`Builder`].
242//! These closures take a [`Formatter`] and `log::Record` as arguments:
243//!
244//! ```
245//! use std::io::Write;
246//!
247//! env_logger::builder()
248//!     .format(|buf, record| {
249//!         writeln!(buf, "{}: {}", record.level(), record.args())
250//!     })
251//!     .init();
252//! ```
253//!
254//! See the [`fmt`] module for more details about custom formats.
255//!
256//! ## Specifying defaults for environment variables
257//!
258//! `env_logger` can read configuration from environment variables.
259//! If these variables aren't present, the default value to use can be tweaked with the [`Env`] type.
260//! The following example defaults to log `warn` and above if the `RUST_LOG` environment variable
261//! isn't set:
262//!
263//! ```
264//! use env_logger::Env;
265//!
266//! env_logger::Builder::from_env(Env::default().default_filter_or("warn")).init();
267//! ```
268//!
269//! [gh-repo-examples]: https://github.com/env-logger-rs/env_logger/tree/main/examples
270//! [level-enum]: https://docs.rs/log/latest/log/enum.Level.html
271//! [log-crate-url]: https://docs.rs/log/
272//! [`Builder`]: struct.Builder.html
273//! [`Builder::is_test`]: struct.Builder.html#method.is_test
274//! [`Env`]: struct.Env.html
275//! [`fmt`]: fmt/index.html
276
277#![doc(
278    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
279    html_favicon_url = "https://www.rust-lang.org/static/images/favicon.ico"
280)]
281// When compiled for the rustc compiler itself we want to make sure that this is
282// an unstable crate
283#![cfg_attr(rustbuild, feature(staged_api, rustc_private))]
284#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))]
285#![deny(missing_debug_implementations, missing_docs)]
286
287use std::{borrow::Cow, cell::RefCell, env, io};
288
289use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};
290
291pub mod filter;
292pub mod fmt;
293
294pub use self::fmt::glob::*;
295
296use self::filter::Filter;
297use self::fmt::writer::{self, Writer};
298use self::fmt::{FormatFn, Formatter};
299
300/// The default name for the environment variable to read filters from.
301pub const DEFAULT_FILTER_ENV: &str = "RUST_LOG";
302
303/// The default name for the environment variable to read style preferences from.
304pub const DEFAULT_WRITE_STYLE_ENV: &str = "RUST_LOG_STYLE";
305
306/// Set of environment variables to configure from.
307///
308/// # Default environment variables
309///
310/// By default, the `Env` will read the following environment variables:
311///
312/// - `RUST_LOG`: the level filter
313/// - `RUST_LOG_STYLE`: whether or not to print styles with records.
314///
315/// These sources can be configured using the builder methods on `Env`.
316#[derive(Debug)]
317pub struct Env<'a> {
318    filter: Var<'a>,
319    write_style: Var<'a>,
320}
321
322#[derive(Debug)]
323struct Var<'a> {
324    name: Cow<'a, str>,
325    default: Option<Cow<'a, str>>,
326}
327
328/// The env logger.
329///
330/// This struct implements the `Log` trait from the [`log` crate][log-crate-url],
331/// which allows it to act as a logger.
332///
333/// The [`init()`], [`try_init()`], [`Builder::init()`] and [`Builder::try_init()`]
334/// methods will each construct a `Logger` and immediately initialize it as the
335/// default global logger.
336///
337/// If you'd instead need access to the constructed `Logger`, you can use
338/// the associated [`Builder`] and install it with the
339/// [`log` crate][log-crate-url] directly.
340///
341/// [log-crate-url]: https://docs.rs/log/
342/// [`init()`]: fn.init.html
343/// [`try_init()`]: fn.try_init.html
344/// [`Builder::init()`]: struct.Builder.html#method.init
345/// [`Builder::try_init()`]: struct.Builder.html#method.try_init
346/// [`Builder`]: struct.Builder.html
347pub struct Logger {
348    writer: Writer,
349    filter: Filter,
350    format: FormatFn,
351}
352
353/// `Builder` acts as builder for initializing a `Logger`.
354///
355/// It can be used to customize the log format, change the environment variable used
356/// to provide the logging directives and also set the default log level filter.
357///
358/// # Examples
359///
360/// ```
361/// # #[macro_use] extern crate log;
362/// # use std::io::Write;
363/// use env_logger::Builder;
364/// use log::LevelFilter;
365///
366/// let mut builder = Builder::from_default_env();
367///
368/// builder
369///     .format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args()))
370///     .filter(None, LevelFilter::Info)
371///     .init();
372///
373/// error!("error message");
374/// info!("info message");
375/// ```
376#[derive(Default)]
377pub struct Builder {
378    filter: filter::Builder,
379    writer: writer::Builder,
380    format: fmt::Builder,
381    built: bool,
382}
383
384impl Builder {
385    /// Initializes the log builder with defaults.
386    ///
387    /// **NOTE:** This method won't read from any environment variables.
388    /// Use the [`filter`] and [`write_style`] methods to configure the builder
389    /// or use [`from_env`] or [`from_default_env`] instead.
390    ///
391    /// # Examples
392    ///
393    /// Create a new builder and configure filters and style:
394    ///
395    /// ```
396    /// use log::LevelFilter;
397    /// use env_logger::{Builder, WriteStyle};
398    ///
399    /// let mut builder = Builder::new();
400    ///
401    /// builder
402    ///     .filter(None, LevelFilter::Info)
403    ///     .write_style(WriteStyle::Always)
404    ///     .init();
405    /// ```
406    ///
407    /// [`filter`]: #method.filter
408    /// [`write_style`]: #method.write_style
409    /// [`from_env`]: #method.from_env
410    /// [`from_default_env`]: #method.from_default_env
411    pub fn new() -> Builder {
412        Default::default()
413    }
414
415    /// Initializes the log builder from the environment.
416    ///
417    /// The variables used to read configuration from can be tweaked before
418    /// passing in.
419    ///
420    /// # Examples
421    ///
422    /// Initialise a logger reading the log filter from an environment variable
423    /// called `MY_LOG`:
424    ///
425    /// ```
426    /// use env_logger::Builder;
427    ///
428    /// let mut builder = Builder::from_env("MY_LOG");
429    /// builder.init();
430    /// ```
431    ///
432    /// Initialise a logger using the `MY_LOG` variable for filtering and
433    /// `MY_LOG_STYLE` for whether or not to write styles:
434    ///
435    /// ```
436    /// use env_logger::{Builder, Env};
437    ///
438    /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
439    ///
440    /// let mut builder = Builder::from_env(env);
441    /// builder.init();
442    /// ```
443    pub fn from_env<'a, E>(env: E) -> Self
444    where
445        E: Into<Env<'a>>,
446    {
447        let mut builder = Builder::new();
448        builder.parse_env(env);
449        builder
450    }
451
452    /// Applies the configuration from the environment.
453    ///
454    /// This function allows a builder to be configured with default parameters,
455    /// to be then overridden by the environment.
456    ///
457    /// # Examples
458    ///
459    /// Initialise a logger with filter level `Off`, then override the log
460    /// filter from an environment variable called `MY_LOG`:
461    ///
462    /// ```
463    /// use log::LevelFilter;
464    /// use env_logger::Builder;
465    ///
466    /// let mut builder = Builder::new();
467    ///
468    /// builder.filter_level(LevelFilter::Off);
469    /// builder.parse_env("MY_LOG");
470    /// builder.init();
471    /// ```
472    ///
473    /// Initialise a logger with filter level `Off`, then use the `MY_LOG`
474    /// variable to override filtering and `MY_LOG_STYLE` to override  whether
475    /// or not to write styles:
476    ///
477    /// ```
478    /// use log::LevelFilter;
479    /// use env_logger::{Builder, Env};
480    ///
481    /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
482    ///
483    /// let mut builder = Builder::new();
484    /// builder.filter_level(LevelFilter::Off);
485    /// builder.parse_env(env);
486    /// builder.init();
487    /// ```
488    pub fn parse_env<'a, E>(&mut self, env: E) -> &mut Self
489    where
490        E: Into<Env<'a>>,
491    {
492        let env = env.into();
493
494        if let Some(s) = env.get_filter() {
495            self.parse_filters(&s);
496        }
497
498        if let Some(s) = env.get_write_style() {
499            self.parse_write_style(&s);
500        }
501
502        self
503    }
504
505    /// Initializes the log builder from the environment using default variable names.
506    ///
507    /// This method is a convenient way to call `from_env(Env::default())` without
508    /// having to use the `Env` type explicitly. The builder will use the
509    /// [default environment variables].
510    ///
511    /// # Examples
512    ///
513    /// Initialise a logger using the default environment variables:
514    ///
515    /// ```
516    /// use env_logger::Builder;
517    ///
518    /// let mut builder = Builder::from_default_env();
519    /// builder.init();
520    /// ```
521    ///
522    /// [default environment variables]: struct.Env.html#default-environment-variables
523    pub fn from_default_env() -> Self {
524        Self::from_env(Env::default())
525    }
526
527    /// Applies the configuration from the environment using default variable names.
528    ///
529    /// This method is a convenient way to call `parse_env(Env::default())` without
530    /// having to use the `Env` type explicitly. The builder will use the
531    /// [default environment variables].
532    ///
533    /// # Examples
534    ///
535    /// Initialise a logger with filter level `Off`, then configure it using the
536    /// default environment variables:
537    ///
538    /// ```
539    /// use log::LevelFilter;
540    /// use env_logger::Builder;
541    ///
542    /// let mut builder = Builder::new();
543    /// builder.filter_level(LevelFilter::Off);
544    /// builder.parse_default_env();
545    /// builder.init();
546    /// ```
547    ///
548    /// [default environment variables]: struct.Env.html#default-environment-variables
549    pub fn parse_default_env(&mut self) -> &mut Self {
550        self.parse_env(Env::default())
551    }
552
553    /// Sets the format function for formatting the log output.
554    ///
555    /// This function is called on each record logged and should format the
556    /// log record and output it to the given [`Formatter`].
557    ///
558    /// The format function is expected to output the string directly to the
559    /// `Formatter` so that implementations can use the [`std::fmt`] macros
560    /// to format and output without intermediate heap allocations. The default
561    /// `env_logger` formatter takes advantage of this.
562    ///
563    /// # Examples
564    ///
565    /// Use a custom format to write only the log message:
566    ///
567    /// ```
568    /// use std::io::Write;
569    /// use env_logger::Builder;
570    ///
571    /// let mut builder = Builder::new();
572    ///
573    /// builder.format(|buf, record| writeln!(buf, "{}", record.args()));
574    /// ```
575    ///
576    /// [`Formatter`]: fmt/struct.Formatter.html
577    /// [`String`]: https://doc.rust-lang.org/stable/std/string/struct.String.html
578    /// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html
579    pub fn format<F: 'static>(&mut self, format: F) -> &mut Self
580    where
581        F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send,
582    {
583        self.format.custom_format = Some(Box::new(format));
584        self
585    }
586
587    /// Use the default format.
588    ///
589    /// This method will clear any custom format set on the builder.
590    pub fn default_format(&mut self) -> &mut Self {
591        self.format = Default::default();
592        self
593    }
594
595    /// Whether or not to write the level in the default format.
596    pub fn format_level(&mut self, write: bool) -> &mut Self {
597        self.format.format_level = write;
598        self
599    }
600
601    /// Whether or not to write the module path in the default format.
602    pub fn format_module_path(&mut self, write: bool) -> &mut Self {
603        self.format.format_module_path = write;
604        self
605    }
606
607    /// Whether or not to write the target in the default format.
608    pub fn format_target(&mut self, write: bool) -> &mut Self {
609        self.format.format_target = write;
610        self
611    }
612
613    /// Configures the amount of spaces to use to indent multiline log records.
614    /// A value of `None` disables any kind of indentation.
615    pub fn format_indent(&mut self, indent: Option<usize>) -> &mut Self {
616        self.format.format_indent = indent;
617        self
618    }
619
620    /// Configures if timestamp should be included and in what precision.
621    pub fn format_timestamp(&mut self, timestamp: Option<fmt::TimestampPrecision>) -> &mut Self {
622        self.format.format_timestamp = timestamp;
623        self
624    }
625
626    /// Configures the timestamp to use second precision.
627    pub fn format_timestamp_secs(&mut self) -> &mut Self {
628        self.format_timestamp(Some(fmt::TimestampPrecision::Seconds))
629    }
630
631    /// Configures the timestamp to use millisecond precision.
632    pub fn format_timestamp_millis(&mut self) -> &mut Self {
633        self.format_timestamp(Some(fmt::TimestampPrecision::Millis))
634    }
635
636    /// Configures the timestamp to use microsecond precision.
637    pub fn format_timestamp_micros(&mut self) -> &mut Self {
638        self.format_timestamp(Some(fmt::TimestampPrecision::Micros))
639    }
640
641    /// Configures the timestamp to use nanosecond precision.
642    pub fn format_timestamp_nanos(&mut self) -> &mut Self {
643        self.format_timestamp(Some(fmt::TimestampPrecision::Nanos))
644    }
645
646    /// Configures the end of line suffix.
647    pub fn format_suffix(&mut self, suffix: &'static str) -> &mut Self {
648        self.format.format_suffix = suffix;
649        self
650    }
651
652    /// Adds a directive to the filter for a specific module.
653    ///
654    /// # Examples
655    ///
656    /// Only include messages for info and above for logs in `path::to::module`:
657    ///
658    /// ```
659    /// use env_logger::Builder;
660    /// use log::LevelFilter;
661    ///
662    /// let mut builder = Builder::new();
663    ///
664    /// builder.filter_module("path::to::module", LevelFilter::Info);
665    /// ```
666    pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self {
667        self.filter.filter_module(module, level);
668        self
669    }
670
671    /// Adds a directive to the filter for all modules.
672    ///
673    /// # Examples
674    ///
675    /// Only include messages for info and above for logs globally:
676    ///
677    /// ```
678    /// use env_logger::Builder;
679    /// use log::LevelFilter;
680    ///
681    /// let mut builder = Builder::new();
682    ///
683    /// builder.filter_level(LevelFilter::Info);
684    /// ```
685    pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self {
686        self.filter.filter_level(level);
687        self
688    }
689
690    /// Adds filters to the logger.
691    ///
692    /// The given module (if any) will log at most the specified level provided.
693    /// If no module is provided then the filter will apply to all log messages.
694    ///
695    /// # Examples
696    ///
697    /// Only include messages for info and above for logs in `path::to::module`:
698    ///
699    /// ```
700    /// use env_logger::Builder;
701    /// use log::LevelFilter;
702    ///
703    /// let mut builder = Builder::new();
704    ///
705    /// builder.filter(Some("path::to::module"), LevelFilter::Info);
706    /// ```
707    pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self {
708        self.filter.filter(module, level);
709        self
710    }
711
712    /// Parses the directives string in the same form as the `RUST_LOG`
713    /// environment variable.
714    ///
715    /// See the module documentation for more details.
716    pub fn parse_filters(&mut self, filters: &str) -> &mut Self {
717        self.filter.parse(filters);
718        self
719    }
720
721    /// Sets the target for the log output.
722    ///
723    /// Env logger can log to either stdout, stderr or a custom pipe. The default is stderr.
724    ///
725    /// The custom pipe can be used to send the log messages to a custom sink (for example a file).
726    /// Do note that direct writes to a file can become a bottleneck due to IO operation times.
727    ///
728    /// # Examples
729    ///
730    /// Write log message to `stdout`:
731    ///
732    /// ```
733    /// use env_logger::{Builder, Target};
734    ///
735    /// let mut builder = Builder::new();
736    ///
737    /// builder.target(Target::Stdout);
738    /// ```
739    pub fn target(&mut self, target: fmt::Target) -> &mut Self {
740        self.writer.target(target);
741        self
742    }
743
744    /// Sets whether or not styles will be written.
745    ///
746    /// This can be useful in environments that don't support control characters
747    /// for setting colors.
748    ///
749    /// # Examples
750    ///
751    /// Never attempt to write styles:
752    ///
753    /// ```
754    /// use env_logger::{Builder, WriteStyle};
755    ///
756    /// let mut builder = Builder::new();
757    ///
758    /// builder.write_style(WriteStyle::Never);
759    /// ```
760    pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self {
761        self.writer.write_style(write_style);
762        self
763    }
764
765    /// Parses whether or not to write styles in the same form as the `RUST_LOG_STYLE`
766    /// environment variable.
767    ///
768    /// See the module documentation for more details.
769    pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self {
770        self.writer.parse_write_style(write_style);
771        self
772    }
773
774    /// Sets whether or not the logger will be used in unit tests.
775    ///
776    /// If `is_test` is `true` then the logger will allow the testing framework to
777    /// capture log records rather than printing them to the terminal directly.
778    pub fn is_test(&mut self, is_test: bool) -> &mut Self {
779        self.writer.is_test(is_test);
780        self
781    }
782
783    /// Initializes the global logger with the built env logger.
784    ///
785    /// This should be called early in the execution of a Rust program. Any log
786    /// events that occur before initialization will be ignored.
787    ///
788    /// # Errors
789    ///
790    /// This function will fail if it is called more than once, or if another
791    /// library has already initialized a global logger.
792    pub fn try_init(&mut self) -> Result<(), SetLoggerError> {
793        let logger = self.build();
794
795        let max_level = logger.filter();
796        let r = log::set_boxed_logger(Box::new(logger));
797
798        if r.is_ok() {
799            log::set_max_level(max_level);
800        }
801
802        r
803    }
804
805    /// Initializes the global logger with the built env logger.
806    ///
807    /// This should be called early in the execution of a Rust program. Any log
808    /// events that occur before initialization will be ignored.
809    ///
810    /// # Panics
811    ///
812    /// This function will panic if it is called more than once, or if another
813    /// library has already initialized a global logger.
814    pub fn init(&mut self) {
815        self.try_init()
816            .expect("Builder::init should not be called after logger initialized");
817    }
818
819    /// Build an env logger.
820    ///
821    /// The returned logger implements the `Log` trait and can be installed manually
822    /// or nested within another logger.
823    pub fn build(&mut self) -> Logger {
824        assert!(!self.built, "attempt to re-use consumed builder");
825        self.built = true;
826
827        Logger {
828            writer: self.writer.build(),
829            filter: self.filter.build(),
830            format: self.format.build(),
831        }
832    }
833}
834
835impl Logger {
836    /// Creates the logger from the environment.
837    ///
838    /// The variables used to read configuration from can be tweaked before
839    /// passing in.
840    ///
841    /// # Examples
842    ///
843    /// Create a logger reading the log filter from an environment variable
844    /// called `MY_LOG`:
845    ///
846    /// ```
847    /// use env_logger::Logger;
848    ///
849    /// let logger = Logger::from_env("MY_LOG");
850    /// ```
851    ///
852    /// Create a logger using the `MY_LOG` variable for filtering and
853    /// `MY_LOG_STYLE` for whether or not to write styles:
854    ///
855    /// ```
856    /// use env_logger::{Logger, Env};
857    ///
858    /// let env = Env::new().filter_or("MY_LOG", "info").write_style_or("MY_LOG_STYLE", "always");
859    ///
860    /// let logger = Logger::from_env(env);
861    /// ```
862    pub fn from_env<'a, E>(env: E) -> Self
863    where
864        E: Into<Env<'a>>,
865    {
866        Builder::from_env(env).build()
867    }
868
869    /// Creates the logger from the environment using default variable names.
870    ///
871    /// This method is a convenient way to call `from_env(Env::default())` without
872    /// having to use the `Env` type explicitly. The logger will use the
873    /// [default environment variables].
874    ///
875    /// # Examples
876    ///
877    /// Creates a logger using the default environment variables:
878    ///
879    /// ```
880    /// use env_logger::Logger;
881    ///
882    /// let logger = Logger::from_default_env();
883    /// ```
884    ///
885    /// [default environment variables]: struct.Env.html#default-environment-variables
886    pub fn from_default_env() -> Self {
887        Builder::from_default_env().build()
888    }
889
890    /// Returns the maximum `LevelFilter` that this env logger instance is
891    /// configured to output.
892    pub fn filter(&self) -> LevelFilter {
893        self.filter.filter()
894    }
895
896    /// Checks if this record matches the configured filter.
897    pub fn matches(&self, record: &Record) -> bool {
898        self.filter.matches(record)
899    }
900}
901
902impl Log for Logger {
903    fn enabled(&self, metadata: &Metadata) -> bool {
904        self.filter.enabled(metadata)
905    }
906
907    fn log(&self, record: &Record) {
908        if self.matches(record) {
909            // Log records are written to a thread-local buffer before being printed
910            // to the terminal. We clear these buffers afterwards, but they aren't shrinked
911            // so will always at least have capacity for the largest log record formatted
912            // on that thread.
913            //
914            // If multiple `Logger`s are used by the same threads then the thread-local
915            // formatter might have different color support. If this is the case the
916            // formatter and its buffer are discarded and recreated.
917
918            thread_local! {
919                static FORMATTER: RefCell<Option<Formatter>> = RefCell::new(None);
920            }
921
922            let print = |formatter: &mut Formatter, record: &Record| {
923                let _ =
924                    (self.format)(formatter, record).and_then(|_| formatter.print(&self.writer));
925
926                // Always clear the buffer afterwards
927                formatter.clear();
928            };
929
930            let printed = FORMATTER
931                .try_with(|tl_buf| {
932                    match tl_buf.try_borrow_mut() {
933                        // There are no active borrows of the buffer
934                        Ok(mut tl_buf) => match *tl_buf {
935                            // We have a previously set formatter
936                            Some(ref mut formatter) => {
937                                // Check the buffer style. If it's different from the logger's
938                                // style then drop the buffer and recreate it.
939                                if formatter.write_style() != self.writer.write_style() {
940                                    *formatter = Formatter::new(&self.writer);
941                                }
942
943                                print(formatter, record);
944                            }
945                            // We don't have a previously set formatter
946                            None => {
947                                let mut formatter = Formatter::new(&self.writer);
948                                print(&mut formatter, record);
949
950                                *tl_buf = Some(formatter);
951                            }
952                        },
953                        // There's already an active borrow of the buffer (due to re-entrancy)
954                        Err(_) => {
955                            print(&mut Formatter::new(&self.writer), record);
956                        }
957                    }
958                })
959                .is_ok();
960
961            if !printed {
962                // The thread-local storage was not available (because its
963                // destructor has already run). Create a new single-use
964                // Formatter on the stack for this call.
965                print(&mut Formatter::new(&self.writer), record);
966            }
967        }
968    }
969
970    fn flush(&self) {}
971}
972
973impl<'a> Env<'a> {
974    /// Get a default set of environment variables.
975    pub fn new() -> Self {
976        Self::default()
977    }
978
979    /// Specify an environment variable to read the filter from.
980    pub fn filter<E>(mut self, filter_env: E) -> Self
981    where
982        E: Into<Cow<'a, str>>,
983    {
984        self.filter = Var::new(filter_env);
985
986        self
987    }
988
989    /// Specify an environment variable to read the filter from.
990    ///
991    /// If the variable is not set, the default value will be used.
992    pub fn filter_or<E, V>(mut self, filter_env: E, default: V) -> Self
993    where
994        E: Into<Cow<'a, str>>,
995        V: Into<Cow<'a, str>>,
996    {
997        self.filter = Var::new_with_default(filter_env, default);
998
999        self
1000    }
1001
1002    /// Use the default environment variable to read the filter from.
1003    ///
1004    /// If the variable is not set, the default value will be used.
1005    pub fn default_filter_or<V>(mut self, default: V) -> Self
1006    where
1007        V: Into<Cow<'a, str>>,
1008    {
1009        self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default);
1010
1011        self
1012    }
1013
1014    fn get_filter(&self) -> Option<String> {
1015        self.filter.get()
1016    }
1017
1018    /// Specify an environment variable to read the style from.
1019    pub fn write_style<E>(mut self, write_style_env: E) -> Self
1020    where
1021        E: Into<Cow<'a, str>>,
1022    {
1023        self.write_style = Var::new(write_style_env);
1024
1025        self
1026    }
1027
1028    /// Specify an environment variable to read the style from.
1029    ///
1030    /// If the variable is not set, the default value will be used.
1031    pub fn write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self
1032    where
1033        E: Into<Cow<'a, str>>,
1034        V: Into<Cow<'a, str>>,
1035    {
1036        self.write_style = Var::new_with_default(write_style_env, default);
1037
1038        self
1039    }
1040
1041    /// Use the default environment variable to read the style from.
1042    ///
1043    /// If the variable is not set, the default value will be used.
1044    pub fn default_write_style_or<V>(mut self, default: V) -> Self
1045    where
1046        V: Into<Cow<'a, str>>,
1047    {
1048        self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default);
1049
1050        self
1051    }
1052
1053    fn get_write_style(&self) -> Option<String> {
1054        self.write_style.get()
1055    }
1056}
1057
1058impl<'a> Var<'a> {
1059    fn new<E>(name: E) -> Self
1060    where
1061        E: Into<Cow<'a, str>>,
1062    {
1063        Var {
1064            name: name.into(),
1065            default: None,
1066        }
1067    }
1068
1069    fn new_with_default<E, V>(name: E, default: V) -> Self
1070    where
1071        E: Into<Cow<'a, str>>,
1072        V: Into<Cow<'a, str>>,
1073    {
1074        Var {
1075            name: name.into(),
1076            default: Some(default.into()),
1077        }
1078    }
1079
1080    fn get(&self) -> Option<String> {
1081        env::var(&*self.name)
1082            .ok()
1083            .or_else(|| self.default.to_owned().map(|v| v.into_owned()))
1084    }
1085}
1086
1087impl<'a, T> From<T> for Env<'a>
1088where
1089    T: Into<Cow<'a, str>>,
1090{
1091    fn from(filter_env: T) -> Self {
1092        Env::default().filter(filter_env.into())
1093    }
1094}
1095
1096impl<'a> Default for Env<'a> {
1097    fn default() -> Self {
1098        Env {
1099            filter: Var::new(DEFAULT_FILTER_ENV),
1100            write_style: Var::new(DEFAULT_WRITE_STYLE_ENV),
1101        }
1102    }
1103}
1104
1105mod std_fmt_impls {
1106    use super::*;
1107    use std::fmt;
1108
1109    impl fmt::Debug for Logger {
1110        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1111            f.debug_struct("Logger")
1112                .field("filter", &self.filter)
1113                .finish()
1114        }
1115    }
1116
1117    impl fmt::Debug for Builder {
1118        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1119            if self.built {
1120                f.debug_struct("Logger").field("built", &true).finish()
1121            } else {
1122                f.debug_struct("Logger")
1123                    .field("filter", &self.filter)
1124                    .field("writer", &self.writer)
1125                    .finish()
1126            }
1127        }
1128    }
1129}
1130
1131/// Attempts to initialize the global logger with an env logger.
1132///
1133/// This should be called early in the execution of a Rust program. Any log
1134/// events that occur before initialization will be ignored.
1135///
1136/// # Errors
1137///
1138/// This function will fail if it is called more than once, or if another
1139/// library has already initialized a global logger.
1140pub fn try_init() -> Result<(), SetLoggerError> {
1141    try_init_from_env(Env::default())
1142}
1143
1144/// Initializes the global logger with an env logger.
1145///
1146/// This should be called early in the execution of a Rust program. Any log
1147/// events that occur before initialization will be ignored.
1148///
1149/// # Panics
1150///
1151/// This function will panic if it is called more than once, or if another
1152/// library has already initialized a global logger.
1153pub fn init() {
1154    try_init().expect("env_logger::init should not be called after logger initialized");
1155}
1156
1157/// Attempts to initialize the global logger with an env logger from the given
1158/// environment variables.
1159///
1160/// This should be called early in the execution of a Rust program. Any log
1161/// events that occur before initialization will be ignored.
1162///
1163/// # Examples
1164///
1165/// Initialise a logger using the `MY_LOG` environment variable for filters
1166/// and `MY_LOG_STYLE` for writing colors:
1167///
1168/// ```
1169/// use env_logger::{Builder, Env};
1170///
1171/// # fn run() -> Result<(), Box<::std::error::Error>> {
1172/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
1173///
1174/// env_logger::try_init_from_env(env)?;
1175///
1176/// Ok(())
1177/// # }
1178/// # run().unwrap();
1179/// ```
1180///
1181/// # Errors
1182///
1183/// This function will fail if it is called more than once, or if another
1184/// library has already initialized a global logger.
1185pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError>
1186where
1187    E: Into<Env<'a>>,
1188{
1189    let mut builder = Builder::from_env(env);
1190
1191    builder.try_init()
1192}
1193
1194/// Initializes the global logger with an env logger from the given environment
1195/// variables.
1196///
1197/// This should be called early in the execution of a Rust program. Any log
1198/// events that occur before initialization will be ignored.
1199///
1200/// # Examples
1201///
1202/// Initialise a logger using the `MY_LOG` environment variable for filters
1203/// and `MY_LOG_STYLE` for writing colors:
1204///
1205/// ```
1206/// use env_logger::{Builder, Env};
1207///
1208/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
1209///
1210/// env_logger::init_from_env(env);
1211/// ```
1212///
1213/// # Panics
1214///
1215/// This function will panic if it is called more than once, or if another
1216/// library has already initialized a global logger.
1217pub fn init_from_env<'a, E>(env: E)
1218where
1219    E: Into<Env<'a>>,
1220{
1221    try_init_from_env(env)
1222        .expect("env_logger::init_from_env should not be called after logger initialized");
1223}
1224
1225/// Create a new builder with the default environment variables.
1226///
1227/// The builder can be configured before being initialized.
1228/// This is a convenient way of calling [`Builder::from_default_env`].
1229///
1230/// [`Builder::from_default_env`]: struct.Builder.html#method.from_default_env
1231pub fn builder() -> Builder {
1232    Builder::from_default_env()
1233}
1234
1235/// Create a builder from the given environment variables.
1236///
1237/// The builder can be configured before being initialized.
1238#[deprecated(
1239    since = "0.8.0",
1240    note = "Prefer `env_logger::Builder::from_env()` instead."
1241)]
1242pub fn from_env<'a, E>(env: E) -> Builder
1243where
1244    E: Into<Env<'a>>,
1245{
1246    Builder::from_env(env)
1247}
1248
1249#[cfg(test)]
1250mod tests {
1251    use super::*;
1252
1253    #[test]
1254    fn env_get_filter_reads_from_var_if_set() {
1255        env::set_var("env_get_filter_reads_from_var_if_set", "from var");
1256
1257        let env = Env::new().filter_or("env_get_filter_reads_from_var_if_set", "from default");
1258
1259        assert_eq!(Some("from var".to_owned()), env.get_filter());
1260    }
1261
1262    #[test]
1263    fn env_get_filter_reads_from_default_if_var_not_set() {
1264        env::remove_var("env_get_filter_reads_from_default_if_var_not_set");
1265
1266        let env = Env::new().filter_or(
1267            "env_get_filter_reads_from_default_if_var_not_set",
1268            "from default",
1269        );
1270
1271        assert_eq!(Some("from default".to_owned()), env.get_filter());
1272    }
1273
1274    #[test]
1275    fn env_get_write_style_reads_from_var_if_set() {
1276        env::set_var("env_get_write_style_reads_from_var_if_set", "from var");
1277
1278        let env =
1279            Env::new().write_style_or("env_get_write_style_reads_from_var_if_set", "from default");
1280
1281        assert_eq!(Some("from var".to_owned()), env.get_write_style());
1282    }
1283
1284    #[test]
1285    fn env_get_write_style_reads_from_default_if_var_not_set() {
1286        env::remove_var("env_get_write_style_reads_from_default_if_var_not_set");
1287
1288        let env = Env::new().write_style_or(
1289            "env_get_write_style_reads_from_default_if_var_not_set",
1290            "from default",
1291        );
1292
1293        assert_eq!(Some("from default".to_owned()), env.get_write_style());
1294    }
1295
1296    #[test]
1297    fn builder_parse_env_overrides_existing_filters() {
1298        env::set_var(
1299            "builder_parse_default_env_overrides_existing_filters",
1300            "debug",
1301        );
1302        let env = Env::new().filter("builder_parse_default_env_overrides_existing_filters");
1303
1304        let mut builder = Builder::new();
1305        builder.filter_level(LevelFilter::Trace);
1306        // Overrides global level to debug
1307        builder.parse_env(env);
1308
1309        assert_eq!(builder.filter.build().filter(), LevelFilter::Debug);
1310    }
1311}