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