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