]> git.proxmox.com Git - cargo.git/blob - vendor/env_logger/src/lib.rs
New upstream version 0.33.0
[cargo.git] / vendor / env_logger / 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 //! ## Disabling colors
144 //!
145 //! Colors and other styles can be configured with the `RUST_LOG_STYLE`
146 //! environment variable. It accepts the following values:
147 //!
148 //! * `auto` (default) will attempt to print style characters, but don't force the issue.
149 //! If the console isn't available on Windows, or if TERM=dumb, for example, then don't print colors.
150 //! * `always` will always print style characters even if they aren't supported by the terminal.
151 //! This includes emitting ANSI colors on Windows if the console API is unavailable.
152 //! * `never` will never print style characters.
153 //!
154 //! ## Tweaking the default format
155 //!
156 //! Parts of the default format can be excluded from the log output using the [`Builder`].
157 //! The following example excludes the timestamp from the log output:
158 //!
159 //! ```
160 //! use env_logger::Builder;
161 //!
162 //! Builder::from_default_env()
163 //! .default_format_timestamp(false)
164 //! .init();
165 //! ```
166 //!
167 //! ### Stability of the default format
168 //!
169 //! The default format won't optimise for long-term stability, and explicitly makes no
170 //! guarantees about the stability of its output across major, minor or patch version
171 //! bumps during `0.x`.
172 //!
173 //! If you want to capture or interpret the output of `env_logger` programmatically
174 //! then you should use a custom format.
175 //!
176 //! ### Using a custom format
177 //!
178 //! Custom formats can be provided as closures to the [`Builder`].
179 //! These closures take a [`Formatter`] and `log::Record` as arguments:
180 //!
181 //! ```
182 //! use std::io::Write;
183 //! use env_logger::Builder;
184 //!
185 //! Builder::from_default_env()
186 //! .format(|buf, record| {
187 //! writeln!(buf, "{}: {}", record.level(), record.args())
188 //! })
189 //! .init();
190 //! ```
191 //!
192 //! See the [`fmt`] module for more details about custom formats.
193 //!
194 //! ## Specifying defaults for environment variables
195 //!
196 //! `env_logger` can read configuration from environment variables.
197 //! If these variables aren't present, the default value to use can be tweaked with the [`Env`] type.
198 //! The following example defaults to log `warn` and above if the `RUST_LOG` environment variable
199 //! isn't set:
200 //!
201 //! ```
202 //! use env_logger::{Builder, Env};
203 //!
204 //! Builder::from_env(Env::default().default_filter_or("warn")).init();
205 //! ```
206 //!
207 //! [log-crate-url]: https://docs.rs/log/
208 //! [`Builder`]: struct.Builder.html
209 //! [`Env`]: struct.Env.html
210 //! [`fmt`]: fmt/index.html
211
212 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
213 html_favicon_url = "http://www.rust-lang.org/favicon.ico",
214 html_root_url = "https://docs.rs/env_logger/0.6.0")]
215 #![cfg_attr(test, deny(warnings))]
216
217 // When compiled for the rustc compiler itself we want to make sure that this is
218 // an unstable crate
219 #![cfg_attr(rustbuild, feature(staged_api, rustc_private))]
220 #![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))]
221
222 #![deny(missing_debug_implementations, missing_docs, warnings)]
223
224 extern crate log;
225
226 #[cfg(feature = "termcolor")]
227 extern crate termcolor;
228 #[cfg(feature = "humantime")]
229 extern crate humantime;
230 #[cfg(feature = "atty")]
231 extern crate atty;
232
233 use std::{env, io};
234 use std::borrow::Cow;
235 use std::cell::RefCell;
236
237 use log::{Log, LevelFilter, Record, SetLoggerError, Metadata};
238
239 pub mod filter;
240 pub mod fmt;
241
242 pub use self::fmt::glob::*;
243
244 use self::filter::Filter;
245 use self::fmt::Formatter;
246 use self::fmt::writer::{self, Writer};
247
248 /// The default name for the environment variable to read filters from.
249 pub const DEFAULT_FILTER_ENV: &'static str = "RUST_LOG";
250
251 /// The default name for the environment variable to read style preferences from.
252 pub const DEFAULT_WRITE_STYLE_ENV: &'static str = "RUST_LOG_STYLE";
253
254 /// Set of environment variables to configure from.
255 ///
256 /// # Default environment variables
257 ///
258 /// By default, the `Env` will read the following environment variables:
259 ///
260 /// - `RUST_LOG`: the level filter
261 /// - `RUST_LOG_STYLE`: whether or not to print styles with records.
262 ///
263 /// These sources can be configured using the builder methods on `Env`.
264 #[derive(Debug)]
265 pub struct Env<'a> {
266 filter: Var<'a>,
267 write_style: Var<'a>,
268 }
269
270 #[derive(Debug)]
271 struct Var<'a> {
272 name: Cow<'a, str>,
273 default: Option<Cow<'a, str>>,
274 }
275
276 /// The env logger.
277 ///
278 /// This struct implements the `Log` trait from the [`log` crate][log-crate-url],
279 /// which allows it to act as a logger.
280 ///
281 /// The [`init()`], [`try_init()`], [`Builder::init()`] and [`Builder::try_init()`]
282 /// methods will each construct a `Logger` and immediately initialize it as the
283 /// default global logger.
284 ///
285 /// If you'd instead need access to the constructed `Logger`, you can use
286 /// the associated [`Builder`] and install it with the
287 /// [`log` crate][log-crate-url] directly.
288 ///
289 /// [log-crate-url]: https://docs.rs/log/
290 /// [`init()`]: fn.init.html
291 /// [`try_init()`]: fn.try_init.html
292 /// [`Builder::init()`]: struct.Builder.html#method.init
293 /// [`Builder::try_init()`]: struct.Builder.html#method.try_init
294 /// [`Builder`]: struct.Builder.html
295 pub struct Logger {
296 writer: Writer,
297 filter: Filter,
298 format: Box<Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send>,
299 }
300
301 /// `Builder` acts as builder for initializing a `Logger`.
302 ///
303 /// It can be used to customize the log format, change the environment variable used
304 /// to provide the logging directives and also set the default log level filter.
305 ///
306 /// # Examples
307 ///
308 /// ```
309 /// #[macro_use]
310 /// extern crate log;
311 /// extern crate env_logger;
312 ///
313 /// use std::env;
314 /// use std::io::Write;
315 /// use log::LevelFilter;
316 /// use env_logger::Builder;
317 ///
318 /// fn main() {
319 /// let mut builder = Builder::from_default_env();
320 ///
321 /// builder.format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args()))
322 /// .filter(None, LevelFilter::Info)
323 /// .init();
324 ///
325 /// error!("error message");
326 /// info!("info message");
327 /// }
328 /// ```
329 #[derive(Default)]
330 pub struct Builder {
331 filter: filter::Builder,
332 writer: writer::Builder,
333 format: fmt::Builder,
334 built: bool,
335 }
336
337 impl Builder {
338 /// Initializes the log builder with defaults.
339 ///
340 /// **NOTE:** This method won't read from any environment variables.
341 /// Use the [`filter`] and [`write_style`] methods to configure the builder
342 /// or use [`from_env`] or [`from_default_env`] instead.
343 ///
344 /// # Examples
345 ///
346 /// Create a new builder and configure filters and style:
347 ///
348 /// ```
349 /// # extern crate log;
350 /// # extern crate env_logger;
351 /// # fn main() {
352 /// use log::LevelFilter;
353 /// use env_logger::{Builder, WriteStyle};
354 ///
355 /// let mut builder = Builder::new();
356 ///
357 /// builder.filter(None, LevelFilter::Info)
358 /// .write_style(WriteStyle::Always)
359 /// .init();
360 /// # }
361 /// ```
362 ///
363 /// [`filter`]: #method.filter
364 /// [`write_style`]: #method.write_style
365 /// [`from_env`]: #method.from_env
366 /// [`from_default_env`]: #method.from_default_env
367 pub fn new() -> Builder {
368 Default::default()
369 }
370
371 /// Initializes the log builder from the environment.
372 ///
373 /// The variables used to read configuration from can be tweaked before
374 /// passing in.
375 ///
376 /// # Examples
377 ///
378 /// Initialise a logger reading the log filter from an environment variable
379 /// called `MY_LOG`:
380 ///
381 /// ```
382 /// use env_logger::Builder;
383 ///
384 /// let mut builder = Builder::from_env("MY_LOG");
385 /// builder.init();
386 /// ```
387 ///
388 /// Initialise a logger using the `MY_LOG` variable for filtering and
389 /// `MY_LOG_STYLE` for whether or not to write styles:
390 ///
391 /// ```
392 /// use env_logger::{Builder, Env};
393 ///
394 /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
395 ///
396 /// let mut builder = Builder::from_env(env);
397 /// builder.init();
398 /// ```
399 pub fn from_env<'a, E>(env: E) -> Self
400 where
401 E: Into<Env<'a>>
402 {
403 let mut builder = Builder::new();
404 let env = env.into();
405
406 if let Some(s) = env.get_filter() {
407 builder.parse(&s);
408 }
409
410 if let Some(s) = env.get_write_style() {
411 builder.parse_write_style(&s);
412 }
413
414 builder
415 }
416
417 /// Initializes the log builder from the environment using default variable names.
418 ///
419 /// This method is a convenient way to call `from_env(Env::default())` without
420 /// having to use the `Env` type explicitly. The builder will use the
421 /// [default environment variables].
422 ///
423 /// # Examples
424 ///
425 /// Initialise a logger using the default environment variables:
426 ///
427 /// ```
428 /// use env_logger::Builder;
429 ///
430 /// let mut builder = Builder::from_default_env();
431 /// builder.init();
432 /// ```
433 ///
434 /// [default environment variables]: struct.Env.html#default-environment-variables
435 pub fn from_default_env() -> Self {
436 Self::from_env(Env::default())
437 }
438
439 /// Sets the format function for formatting the log output.
440 ///
441 /// This function is called on each record logged and should format the
442 /// log record and output it to the given [`Formatter`].
443 ///
444 /// The format function is expected to output the string directly to the
445 /// `Formatter` so that implementations can use the [`std::fmt`] macros
446 /// to format and output without intermediate heap allocations. The default
447 /// `env_logger` formatter takes advantage of this.
448 ///
449 /// # Examples
450 ///
451 /// Use a custom format to write only the log message:
452 ///
453 /// ```
454 /// use std::io::Write;
455 /// use env_logger::Builder;
456 ///
457 /// let mut builder = Builder::new();
458 ///
459 /// builder.format(|buf, record| writeln!(buf, "{}", record.args()));
460 /// ```
461 ///
462 /// [`Formatter`]: fmt/struct.Formatter.html
463 /// [`String`]: https://doc.rust-lang.org/stable/std/string/struct.String.html
464 /// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html
465 pub fn format<F: 'static>(&mut self, format: F) -> &mut Self
466 where F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send
467 {
468 self.format.custom_format = Some(Box::new(format));
469 self
470 }
471
472 /// Use the default format.
473 ///
474 /// This method will clear any custom format set on the builder.
475 pub fn default_format(&mut self) -> &mut Self {
476 self.format.custom_format = None;
477 self
478 }
479
480 /// Whether or not to write the level in the default format.
481 pub fn default_format_level(&mut self, write: bool) -> &mut Self {
482 self.format.default_format_level = write;
483 self
484 }
485
486 /// Whether or not to write the module path in the default format.
487 pub fn default_format_module_path(&mut self, write: bool) -> &mut Self {
488 self.format.default_format_module_path = write;
489 self
490 }
491
492 /// Whether or not to write the timestamp in the default format.
493 pub fn default_format_timestamp(&mut self, write: bool) -> &mut Self {
494 self.format.default_format_timestamp = write;
495 self
496 }
497
498 /// Whether or not to write the timestamp with nanos.
499 pub fn default_format_timestamp_nanos(&mut self, write: bool) -> &mut Self {
500 self.format.default_format_timestamp_nanos = write;
501 self
502 }
503
504 /// Adds a directive to the filter for a specific module.
505 ///
506 /// # Examples
507 ///
508 /// Only include messages for warning and above for logs in `path::to::module`:
509 ///
510 /// ```
511 /// # extern crate log;
512 /// # extern crate env_logger;
513 /// # fn main() {
514 /// use log::LevelFilter;
515 /// use env_logger::Builder;
516 ///
517 /// let mut builder = Builder::new();
518 ///
519 /// builder.filter_module("path::to::module", LevelFilter::Info);
520 /// # }
521 /// ```
522 pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self {
523 self.filter.filter_module(module, level);
524 self
525 }
526
527 /// Adds a directive to the filter for all modules.
528 ///
529 /// # Examples
530 ///
531 /// Only include messages for warning and above for logs in `path::to::module`:
532 ///
533 /// ```
534 /// # extern crate log;
535 /// # extern crate env_logger;
536 /// # fn main() {
537 /// use log::LevelFilter;
538 /// use env_logger::Builder;
539 ///
540 /// let mut builder = Builder::new();
541 ///
542 /// builder.filter_level(LevelFilter::Info);
543 /// # }
544 /// ```
545 pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self {
546 self.filter.filter_level(level);
547 self
548 }
549
550 /// Adds filters to the logger.
551 ///
552 /// The given module (if any) will log at most the specified level provided.
553 /// If no module is provided then the filter will apply to all log messages.
554 ///
555 /// # Examples
556 ///
557 /// Only include messages for warning and above for logs in `path::to::module`:
558 ///
559 /// ```
560 /// # extern crate log;
561 /// # extern crate env_logger;
562 /// # fn main() {
563 /// use log::LevelFilter;
564 /// use env_logger::Builder;
565 ///
566 /// let mut builder = Builder::new();
567 ///
568 /// builder.filter(Some("path::to::module"), LevelFilter::Info);
569 /// # }
570 /// ```
571 pub fn filter(&mut self,
572 module: Option<&str>,
573 level: LevelFilter) -> &mut Self {
574 self.filter.filter(module, level);
575 self
576 }
577
578 /// Parses the directives string in the same form as the `RUST_LOG`
579 /// environment variable.
580 ///
581 /// See the module documentation for more details.
582 pub fn parse(&mut self, filters: &str) -> &mut Self {
583 self.filter.parse(filters);
584 self
585 }
586
587 /// Sets the target for the log output.
588 ///
589 /// Env logger can log to either stdout or stderr. The default is stderr.
590 ///
591 /// # Examples
592 ///
593 /// Write log message to `stdout`:
594 ///
595 /// ```
596 /// use env_logger::{Builder, Target};
597 ///
598 /// let mut builder = Builder::new();
599 ///
600 /// builder.target(Target::Stdout);
601 /// ```
602 pub fn target(&mut self, target: fmt::Target) -> &mut Self {
603 self.writer.target(target);
604 self
605 }
606
607 /// Sets whether or not styles will be written.
608 ///
609 /// This can be useful in environments that don't support control characters
610 /// for setting colors.
611 ///
612 /// # Examples
613 ///
614 /// Never attempt to write styles:
615 ///
616 /// ```
617 /// use env_logger::{Builder, WriteStyle};
618 ///
619 /// let mut builder = Builder::new();
620 ///
621 /// builder.write_style(WriteStyle::Never);
622 /// ```
623 pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self {
624 self.writer.write_style(write_style);
625 self
626 }
627
628 /// Parses whether or not to write styles in the same form as the `RUST_LOG_STYLE`
629 /// environment variable.
630 ///
631 /// See the module documentation for more details.
632 pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self {
633 self.writer.parse(write_style);
634 self
635 }
636
637 /// Initializes the global logger with the built env logger.
638 ///
639 /// This should be called early in the execution of a Rust program. Any log
640 /// events that occur before initialization will be ignored.
641 ///
642 /// # Errors
643 ///
644 /// This function will fail if it is called more than once, or if another
645 /// library has already initialized a global logger.
646 pub fn try_init(&mut self) -> Result<(), SetLoggerError> {
647 let logger = self.build();
648
649 let max_level = logger.filter();
650 let r = log::set_boxed_logger(Box::new(logger));
651
652 if r.is_ok() {
653 log::set_max_level(max_level);
654 }
655
656 r
657 }
658
659 /// Initializes the global logger with the built env logger.
660 ///
661 /// This should be called early in the execution of a Rust program. Any log
662 /// events that occur before initialization will be ignored.
663 ///
664 /// # Panics
665 ///
666 /// This function will panic if it is called more than once, or if another
667 /// library has already initialized a global logger.
668 pub fn init(&mut self) {
669 self.try_init().expect("Builder::init should not be called after logger initialized");
670 }
671
672 /// Build an env logger.
673 ///
674 /// The returned logger implements the `Log` trait and can be installed manually
675 /// or nested within another logger.
676 pub fn build(&mut self) -> Logger {
677 assert!(!self.built, "attempt to re-use consumed builder");
678 self.built = true;
679
680 Logger {
681 writer: self.writer.build(),
682 filter: self.filter.build(),
683 format: self.format.build(),
684 }
685 }
686 }
687
688 impl Logger {
689 /// Creates the logger from the environment.
690 ///
691 /// The variables used to read configuration from can be tweaked before
692 /// passing in.
693 ///
694 /// # Examples
695 ///
696 /// Create a logger reading the log filter from an environment variable
697 /// called `MY_LOG`:
698 ///
699 /// ```
700 /// use env_logger::Logger;
701 ///
702 /// let logger = Logger::from_env("MY_LOG");
703 /// ```
704 ///
705 /// Create a logger using the `MY_LOG` variable for filtering and
706 /// `MY_LOG_STYLE` for whether or not to write styles:
707 ///
708 /// ```
709 /// use env_logger::{Logger, Env};
710 ///
711 /// let env = Env::new().filter_or("MY_LOG", "info").write_style_or("MY_LOG_STYLE", "always");
712 ///
713 /// let logger = Logger::from_env(env);
714 /// ```
715 pub fn from_env<'a, E>(env: E) -> Self
716 where
717 E: Into<Env<'a>>
718 {
719 Builder::from_env(env).build()
720 }
721
722 /// Creates the logger from the environment using default variable names.
723 ///
724 /// This method is a convenient way to call `from_env(Env::default())` without
725 /// having to use the `Env` type explicitly. The logger will use the
726 /// [default environment variables].
727 ///
728 /// # Examples
729 ///
730 /// Creates a logger using the default environment variables:
731 ///
732 /// ```
733 /// use env_logger::Logger;
734 ///
735 /// let logger = Logger::from_default_env();
736 /// ```
737 ///
738 /// [default environment variables]: struct.Env.html#default-environment-variables
739 pub fn from_default_env() -> Self {
740 Builder::from_default_env().build()
741 }
742
743 /// Returns the maximum `LevelFilter` that this env logger instance is
744 /// configured to output.
745 pub fn filter(&self) -> LevelFilter {
746 self.filter.filter()
747 }
748
749 /// Checks if this record matches the configured filter.
750 pub fn matches(&self, record: &Record) -> bool {
751 self.filter.matches(record)
752 }
753 }
754
755 impl Log for Logger {
756 fn enabled(&self, metadata: &Metadata) -> bool {
757 self.filter.enabled(metadata)
758 }
759
760 fn log(&self, record: &Record) {
761 if self.matches(record) {
762 // Log records are written to a thread-local buffer before being printed
763 // to the terminal. We clear these buffers afterwards, but they aren't shrinked
764 // so will always at least have capacity for the largest log record formatted
765 // on that thread.
766 //
767 // If multiple `Logger`s are used by the same threads then the thread-local
768 // formatter might have different color support. If this is the case the
769 // formatter and its buffer are discarded and recreated.
770
771 thread_local! {
772 static FORMATTER: RefCell<Option<Formatter>> = RefCell::new(None);
773 }
774
775 FORMATTER.with(|tl_buf| {
776 // It's possible for implementations to sometimes
777 // log-while-logging (e.g. a `std::fmt` implementation logs
778 // internally) but it's super rare. If this happens make sure we
779 // at least don't panic and ship some output to the screen.
780 let mut a;
781 let mut b = None;
782 let tl_buf = match tl_buf.try_borrow_mut() {
783 Ok(f) => {
784 a = f;
785 &mut *a
786 }
787 Err(_) => &mut b,
788 };
789
790 // Check the buffer style. If it's different from the logger's
791 // style then drop the buffer and recreate it.
792 match *tl_buf {
793 Some(ref mut formatter) => {
794 if formatter.write_style() != self.writer.write_style() {
795 *formatter = Formatter::new(&self.writer)
796 }
797 },
798 ref mut tl_buf => *tl_buf = Some(Formatter::new(&self.writer))
799 }
800
801 // The format is guaranteed to be `Some` by this point
802 let mut formatter = tl_buf.as_mut().unwrap();
803
804 let _ = (self.format)(&mut formatter, record).and_then(|_| formatter.print(&self.writer));
805
806 // Always clear the buffer afterwards
807 formatter.clear();
808 });
809 }
810 }
811
812 fn flush(&self) {}
813 }
814
815 impl<'a> Env<'a> {
816 /// Get a default set of environment variables.
817 pub fn new() -> Self {
818 Self::default()
819 }
820
821 /// Specify an environment variable to read the filter from.
822 pub fn filter<E>(mut self, filter_env: E) -> Self
823 where
824 E: Into<Cow<'a, str>>
825 {
826 self.filter = Var::new(filter_env);
827
828 self
829 }
830
831 /// Specify an environment variable to read the filter from.
832 ///
833 /// If the variable is not set, the default value will be used.
834 pub fn filter_or<E, V>(mut self, filter_env: E, default: V) -> Self
835 where
836 E: Into<Cow<'a, str>>,
837 V: Into<Cow<'a, str>>,
838 {
839 self.filter = Var::new_with_default(filter_env, default);
840
841 self
842 }
843
844 /// Use the default environment variable to read the filter from.
845 ///
846 /// If the variable is not set, the default value will be used.
847 pub fn default_filter_or<V>(mut self, default: V) -> Self
848 where
849 V: Into<Cow<'a, str>>,
850 {
851 self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default);
852
853 self
854 }
855
856 fn get_filter(&self) -> Option<String> {
857 self.filter.get()
858 }
859
860 /// Specify an environment variable to read the style from.
861 pub fn write_style<E>(mut self, write_style_env: E) -> Self
862 where
863 E: Into<Cow<'a, str>>
864 {
865 self.write_style = Var::new(write_style_env);
866
867 self
868 }
869
870 /// Specify an environment variable to read the style from.
871 ///
872 /// If the variable is not set, the default value will be used.
873 pub fn write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self
874 where
875 E: Into<Cow<'a, str>>,
876 V: Into<Cow<'a, str>>,
877 {
878 self.write_style = Var::new_with_default(write_style_env, default);
879
880 self
881 }
882
883 /// Use the default environment variable to read the style from.
884 ///
885 /// If the variable is not set, the default value will be used.
886 pub fn default_write_style_or<V>(mut self, default: V) -> Self
887 where
888 V: Into<Cow<'a, str>>,
889 {
890 self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default);
891
892 self
893 }
894
895 fn get_write_style(&self) -> Option<String> {
896 self.write_style.get()
897 }
898 }
899
900 impl<'a> Var<'a> {
901 fn new<E>(name: E) -> Self
902 where
903 E: Into<Cow<'a, str>>,
904 {
905 Var {
906 name: name.into(),
907 default: None,
908 }
909 }
910
911 fn new_with_default<E, V>(name: E, default: V) -> Self
912 where
913 E: Into<Cow<'a, str>>,
914 V: Into<Cow<'a, str>>,
915 {
916 Var {
917 name: name.into(),
918 default: Some(default.into()),
919 }
920 }
921
922 fn get(&self) -> Option<String> {
923 env::var(&*self.name)
924 .ok()
925 .or_else(|| self.default
926 .to_owned()
927 .map(|v| v.into_owned()))
928 }
929 }
930
931 impl<'a, T> From<T> for Env<'a>
932 where
933 T: Into<Cow<'a, str>>
934 {
935 fn from(filter_env: T) -> Self {
936 Env::default().filter(filter_env.into())
937 }
938 }
939
940 impl<'a> Default for Env<'a> {
941 fn default() -> Self {
942 Env {
943 filter: Var::new(DEFAULT_FILTER_ENV),
944 write_style: Var::new(DEFAULT_WRITE_STYLE_ENV),
945 }
946 }
947 }
948
949 mod std_fmt_impls {
950 use std::fmt;
951 use super::*;
952
953 impl fmt::Debug for Logger{
954 fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result {
955 f.debug_struct("Logger")
956 .field("filter", &self.filter)
957 .finish()
958 }
959 }
960
961 impl fmt::Debug for Builder{
962 fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result {
963 if self.built {
964 f.debug_struct("Logger")
965 .field("built", &true)
966 .finish()
967 } else {
968 f.debug_struct("Logger")
969 .field("filter", &self.filter)
970 .field("writer", &self.writer)
971 .finish()
972 }
973 }
974 }
975 }
976
977 /// Attempts to initialize the global logger with an env logger.
978 ///
979 /// This should be called early in the execution of a Rust program. Any log
980 /// events that occur before initialization will be ignored.
981 ///
982 /// # Errors
983 ///
984 /// This function will fail if it is called more than once, or if another
985 /// library has already initialized a global logger.
986 pub fn try_init() -> Result<(), SetLoggerError> {
987 try_init_from_env(Env::default())
988 }
989
990 /// Initializes the global logger with an env logger.
991 ///
992 /// This should be called early in the execution of a Rust program. Any log
993 /// events that occur before initialization will be ignored.
994 ///
995 /// # Panics
996 ///
997 /// This function will panic if it is called more than once, or if another
998 /// library has already initialized a global logger.
999 pub fn init() {
1000 try_init().expect("env_logger::init should not be called after logger initialized");
1001 }
1002
1003 /// Attempts to initialize the global logger with an env logger from the given
1004 /// environment variables.
1005 ///
1006 /// This should be called early in the execution of a Rust program. Any log
1007 /// events that occur before initialization will be ignored.
1008 ///
1009 /// # Examples
1010 ///
1011 /// Initialise a logger using the `MY_LOG` environment variable for filters
1012 /// and `MY_LOG_STYLE` for writing colors:
1013 ///
1014 /// ```
1015 /// # extern crate env_logger;
1016 /// use env_logger::{Builder, Env};
1017 ///
1018 /// # fn run() -> Result<(), Box<::std::error::Error>> {
1019 /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
1020 ///
1021 /// env_logger::try_init_from_env(env)?;
1022 ///
1023 /// Ok(())
1024 /// # }
1025 /// # fn main() { run().unwrap(); }
1026 /// ```
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_from_env<'a, E>(env: E) -> Result<(), SetLoggerError>
1033 where
1034 E: Into<Env<'a>>
1035 {
1036 let mut builder = Builder::from_env(env);
1037
1038 builder.try_init()
1039 }
1040
1041 /// Initializes the global logger with an env logger from the given environment
1042 /// variables.
1043 ///
1044 /// This should be called early in the execution of a Rust program. Any log
1045 /// events that occur before initialization will be ignored.
1046 ///
1047 /// # Examples
1048 ///
1049 /// Initialise a logger using the `MY_LOG` environment variable for filters
1050 /// and `MY_LOG_STYLE` for writing colors:
1051 ///
1052 /// ```
1053 /// use env_logger::{Builder, Env};
1054 ///
1055 /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
1056 ///
1057 /// env_logger::init_from_env(env);
1058 /// ```
1059 ///
1060 /// # Panics
1061 ///
1062 /// This function will panic if it is called more than once, or if another
1063 /// library has already initialized a global logger.
1064 pub fn init_from_env<'a, E>(env: E)
1065 where
1066 E: Into<Env<'a>>
1067 {
1068 try_init_from_env(env).expect("env_logger::init_from_env should not be called after logger initialized");
1069 }
1070
1071 #[cfg(test)]
1072 mod tests {
1073 use super::*;
1074
1075 #[test]
1076 fn env_get_filter_reads_from_var_if_set() {
1077 env::set_var("env_get_filter_reads_from_var_if_set", "from var");
1078
1079 let env = Env::new().filter_or("env_get_filter_reads_from_var_if_set", "from default");
1080
1081 assert_eq!(Some("from var".to_owned()), env.get_filter());
1082 }
1083
1084 #[test]
1085 fn env_get_filter_reads_from_default_if_var_not_set() {
1086 env::remove_var("env_get_filter_reads_from_default_if_var_not_set");
1087
1088 let env = Env::new().filter_or("env_get_filter_reads_from_default_if_var_not_set", "from default");
1089
1090 assert_eq!(Some("from default".to_owned()), env.get_filter());
1091 }
1092
1093 #[test]
1094 fn env_get_write_style_reads_from_var_if_set() {
1095 env::set_var("env_get_write_style_reads_from_var_if_set", "from var");
1096
1097 let env = Env::new().write_style_or("env_get_write_style_reads_from_var_if_set", "from default");
1098
1099 assert_eq!(Some("from var".to_owned()), env.get_write_style());
1100 }
1101
1102 #[test]
1103 fn env_get_write_style_reads_from_default_if_var_not_set() {
1104 env::remove_var("env_get_write_style_reads_from_default_if_var_not_set");
1105
1106 let env = Env::new().write_style_or("env_get_write_style_reads_from_default_if_var_not_set", "from default");
1107
1108 assert_eq!(Some("from default".to_owned()), env.get_write_style());
1109 }
1110 }