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