env_logger/
lib.rs

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