• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
287 use std::{borrow::Cow, cell::RefCell, env, io};
288 
289 use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};
290 
291 pub mod filter;
292 pub mod fmt;
293 
294 pub use self::fmt::glob::*;
295 
296 use self::filter::Filter;
297 use self::fmt::writer::{self, Writer};
298 use self::fmt::{FormatFn, Formatter};
299 
300 /// The default name for the environment variable to read filters from.
301 pub const DEFAULT_FILTER_ENV: &str = "RUST_LOG";
302 
303 /// The default name for the environment variable to read style preferences from.
304 pub 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)]
317 pub struct Env<'a> {
318     filter: Var<'a>,
319     write_style: Var<'a>,
320 }
321 
322 #[derive(Debug)]
323 struct 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
347 pub 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)]
377 pub struct Builder {
378     filter: filter::Builder,
379     writer: writer::Builder,
380     format: fmt::Builder,
381     built: bool,
382 }
383 
384 impl 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
new() -> Builder411     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     /// ```
from_env<'a, E>(env: E) -> Self where E: Into<Env<'a>>,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     /// ```
parse_env<'a, E>(&mut self, env: E) -> &mut Self where E: Into<Env<'a>>,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
from_default_env() -> Self523     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
parse_default_env(&mut self) -> &mut Self549     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
format<F: 'static>(&mut self, format: F) -> &mut Self where F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send,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.
default_format(&mut self) -> &mut Self590     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.
format_level(&mut self, write: bool) -> &mut Self596     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.
format_module_path(&mut self, write: bool) -> &mut Self602     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.
format_target(&mut self, write: bool) -> &mut Self608     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.
format_indent(&mut self, indent: Option<usize>) -> &mut Self615     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.
format_timestamp(&mut self, timestamp: Option<fmt::TimestampPrecision>) -> &mut Self621     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.
format_timestamp_secs(&mut self) -> &mut Self627     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.
format_timestamp_millis(&mut self) -> &mut Self632     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.
format_timestamp_micros(&mut self) -> &mut Self637     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.
format_timestamp_nanos(&mut self) -> &mut Self642     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.
format_suffix(&mut self, suffix: &'static str) -> &mut Self647     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     /// ```
filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self666     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     /// ```
filter_level(&mut self, level: LevelFilter) -> &mut Self685     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     /// ```
filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self707     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.
parse_filters(&mut self, filters: &str) -> &mut Self716     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     /// ```
target(&mut self, target: fmt::Target) -> &mut Self739     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     /// ```
write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self760     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.
parse_write_style(&mut self, write_style: &str) -> &mut Self769     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.
is_test(&mut self, is_test: bool) -> &mut Self778     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.
try_init(&mut self) -> Result<(), SetLoggerError>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.
init(&mut self)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.
build(&mut self) -> Logger823     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 
835 impl 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     /// ```
from_env<'a, E>(env: E) -> Self where E: Into<Env<'a>>,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
from_default_env() -> Self886     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.
filter(&self) -> LevelFilter892     pub fn filter(&self) -> LevelFilter {
893         self.filter.filter()
894     }
895 
896     /// Checks if this record matches the configured filter.
matches(&self, record: &Record) -> bool897     pub fn matches(&self, record: &Record) -> bool {
898         self.filter.matches(record)
899     }
900 }
901 
902 impl Log for Logger {
enabled(&self, metadata: &Metadata) -> bool903     fn enabled(&self, metadata: &Metadata) -> bool {
904         self.filter.enabled(metadata)
905     }
906 
log(&self, record: &Record)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 
flush(&self)970     fn flush(&self) {}
971 }
972 
973 impl<'a> Env<'a> {
974     /// Get a default set of environment variables.
new() -> Self975     pub fn new() -> Self {
976         Self::default()
977     }
978 
979     /// Specify an environment variable to read the filter from.
filter<E>(mut self, filter_env: E) -> Self where E: Into<Cow<'a, str>>,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.
filter_or<E, V>(mut self, filter_env: E, default: V) -> Self where E: Into<Cow<'a, str>>, V: Into<Cow<'a, str>>,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.
default_filter_or<V>(mut self, default: V) -> Self where V: Into<Cow<'a, str>>,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 
get_filter(&self) -> Option<String>1014     fn get_filter(&self) -> Option<String> {
1015         self.filter.get()
1016     }
1017 
1018     /// Specify an environment variable to read the style from.
write_style<E>(mut self, write_style_env: E) -> Self where E: Into<Cow<'a, str>>,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.
write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self where E: Into<Cow<'a, str>>, V: Into<Cow<'a, str>>,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.
default_write_style_or<V>(mut self, default: V) -> Self where V: Into<Cow<'a, str>>,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 
get_write_style(&self) -> Option<String>1053     fn get_write_style(&self) -> Option<String> {
1054         self.write_style.get()
1055     }
1056 }
1057 
1058 impl<'a> Var<'a> {
new<E>(name: E) -> Self where E: Into<Cow<'a, str>>,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 
new_with_default<E, V>(name: E, default: V) -> Self where E: Into<Cow<'a, str>>, V: Into<Cow<'a, str>>,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 
get(&self) -> Option<String>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 
1087 impl<'a, T> From<T> for Env<'a>
1088 where
1089     T: Into<Cow<'a, str>>,
1090 {
from(filter_env: T) -> Self1091     fn from(filter_env: T) -> Self {
1092         Env::default().filter(filter_env.into())
1093     }
1094 }
1095 
1096 impl<'a> Default for Env<'a> {
default() -> Self1097     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 
1105 mod std_fmt_impls {
1106     use super::*;
1107     use std::fmt;
1108 
1109     impl fmt::Debug for Logger {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1110         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 {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1118         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.
try_init() -> Result<(), SetLoggerError>1140 pub 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.
init()1153 pub 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.
try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError> where E: Into<Env<'a>>,1185 pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError>
1186 where
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.
init_from_env<'a, E>(env: E) where E: Into<Env<'a>>,1217 pub fn init_from_env<'a, E>(env: E)
1218 where
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
builder() -> Builder1231 pub 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 )]
from_env<'a, E>(env: E) -> Builder where E: Into<Env<'a>>,1242 pub fn from_env<'a, E>(env: E) -> Builder
1243 where
1244     E: Into<Env<'a>>,
1245 {
1246     Builder::from_env(env)
1247 }
1248 
1249 #[cfg(test)]
1250 mod tests {
1251     use super::*;
1252 
1253     #[test]
env_get_filter_reads_from_var_if_set()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]
env_get_filter_reads_from_default_if_var_not_set()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]
env_get_write_style_reads_from_var_if_set()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]
env_get_write_style_reads_from_default_if_var_not_set()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]
builder_parse_env_overrides_existing_filters()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 }
1312