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