1 use std::{borrow::Cow, cell::RefCell, env, io};
2 
3 use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};
4 
5 use crate::filter;
6 use crate::filter::Filter;
7 use crate::fmt;
8 use crate::fmt::writer::{self, Writer};
9 use crate::fmt::{FormatFn, Formatter};
10 
11 /// The default name for the environment variable to read filters from.
12 pub const DEFAULT_FILTER_ENV: &str = "RUST_LOG";
13 
14 /// The default name for the environment variable to read style preferences from.
15 pub const DEFAULT_WRITE_STYLE_ENV: &str = "RUST_LOG_STYLE";
16 
17 /// `Builder` acts as builder for initializing a `Logger`.
18 ///
19 /// It can be used to customize the log format, change the environment variable used
20 /// to provide the logging directives and also set the default log level filter.
21 ///
22 /// # Examples
23 ///
24 /// ```
25 /// # use std::io::Write;
26 /// use env_logger::Builder;
27 /// use log::{LevelFilter, error, info};
28 ///
29 /// let mut builder = Builder::from_default_env();
30 ///
31 /// builder
32 ///     .format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args()))
33 ///     .filter(None, LevelFilter::Info)
34 ///     .init();
35 ///
36 /// error!("error message");
37 /// info!("info message");
38 /// ```
39 #[derive(Default)]
40 pub struct Builder {
41     filter: filter::Builder,
42     writer: writer::Builder,
43     format: fmt::Builder,
44     built: bool,
45 }
46 
47 impl Builder {
48     /// Initializes the log builder with defaults.
49     ///
50     /// **NOTE:** This method won't read from any environment variables.
51     /// Use the [`filter`] and [`write_style`] methods to configure the builder
52     /// or use [`from_env`] or [`from_default_env`] instead.
53     ///
54     /// # Examples
55     ///
56     /// Create a new builder and configure filters and style:
57     ///
58     /// ```
59     /// use log::LevelFilter;
60     /// use env_logger::{Builder, WriteStyle};
61     ///
62     /// let mut builder = Builder::new();
63     ///
64     /// builder
65     ///     .filter(None, LevelFilter::Info)
66     ///     .write_style(WriteStyle::Always)
67     ///     .init();
68     /// ```
69     ///
70     /// [`filter`]: #method.filter
71     /// [`write_style`]: #method.write_style
72     /// [`from_env`]: #method.from_env
73     /// [`from_default_env`]: #method.from_default_env
new() -> Builder74     pub fn new() -> Builder {
75         Default::default()
76     }
77 
78     /// Initializes the log builder from the environment.
79     ///
80     /// The variables used to read configuration from can be tweaked before
81     /// passing in.
82     ///
83     /// # Examples
84     ///
85     /// Initialise a logger reading the log filter from an environment variable
86     /// called `MY_LOG`:
87     ///
88     /// ```
89     /// use env_logger::Builder;
90     ///
91     /// let mut builder = Builder::from_env("MY_LOG");
92     /// builder.init();
93     /// ```
94     ///
95     /// Initialise a logger using the `MY_LOG` variable for filtering and
96     /// `MY_LOG_STYLE` for whether or not to write styles:
97     ///
98     /// ```
99     /// use env_logger::{Builder, Env};
100     ///
101     /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
102     ///
103     /// let mut builder = Builder::from_env(env);
104     /// builder.init();
105     /// ```
from_env<'a, E>(env: E) -> Self where E: Into<Env<'a>>,106     pub fn from_env<'a, E>(env: E) -> Self
107     where
108         E: Into<Env<'a>>,
109     {
110         let mut builder = Builder::new();
111         builder.parse_env(env);
112         builder
113     }
114 
115     /// Applies the configuration from the environment.
116     ///
117     /// This function allows a builder to be configured with default parameters,
118     /// to be then overridden by the environment.
119     ///
120     /// # Examples
121     ///
122     /// Initialise a logger with filter level `Off`, then override the log
123     /// filter from an environment variable called `MY_LOG`:
124     ///
125     /// ```
126     /// use log::LevelFilter;
127     /// use env_logger::Builder;
128     ///
129     /// let mut builder = Builder::new();
130     ///
131     /// builder.filter_level(LevelFilter::Off);
132     /// builder.parse_env("MY_LOG");
133     /// builder.init();
134     /// ```
135     ///
136     /// Initialise a logger with filter level `Off`, then use the `MY_LOG`
137     /// variable to override filtering and `MY_LOG_STYLE` to override  whether
138     /// or not to write styles:
139     ///
140     /// ```
141     /// use log::LevelFilter;
142     /// use env_logger::{Builder, Env};
143     ///
144     /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
145     ///
146     /// let mut builder = Builder::new();
147     /// builder.filter_level(LevelFilter::Off);
148     /// builder.parse_env(env);
149     /// builder.init();
150     /// ```
parse_env<'a, E>(&mut self, env: E) -> &mut Self where E: Into<Env<'a>>,151     pub fn parse_env<'a, E>(&mut self, env: E) -> &mut Self
152     where
153         E: Into<Env<'a>>,
154     {
155         let env = env.into();
156 
157         if let Some(s) = env.get_filter() {
158             self.parse_filters(&s);
159         }
160 
161         if let Some(s) = env.get_write_style() {
162             self.parse_write_style(&s);
163         }
164 
165         self
166     }
167 
168     /// Initializes the log builder from the environment using default variable names.
169     ///
170     /// This method is a convenient way to call `from_env(Env::default())` without
171     /// having to use the `Env` type explicitly. The builder will use the
172     /// [default environment variables].
173     ///
174     /// # Examples
175     ///
176     /// Initialise a logger using the default environment variables:
177     ///
178     /// ```
179     /// use env_logger::Builder;
180     ///
181     /// let mut builder = Builder::from_default_env();
182     /// builder.init();
183     /// ```
184     ///
185     /// [default environment variables]: struct.Env.html#default-environment-variables
from_default_env() -> Self186     pub fn from_default_env() -> Self {
187         Self::from_env(Env::default())
188     }
189 
190     /// Applies the configuration from the environment using default variable names.
191     ///
192     /// This method is a convenient way to call `parse_env(Env::default())` without
193     /// having to use the `Env` type explicitly. The builder will use the
194     /// [default environment variables].
195     ///
196     /// # Examples
197     ///
198     /// Initialise a logger with filter level `Off`, then configure it using the
199     /// default environment variables:
200     ///
201     /// ```
202     /// use log::LevelFilter;
203     /// use env_logger::Builder;
204     ///
205     /// let mut builder = Builder::new();
206     /// builder.filter_level(LevelFilter::Off);
207     /// builder.parse_default_env();
208     /// builder.init();
209     /// ```
210     ///
211     /// [default environment variables]: struct.Env.html#default-environment-variables
parse_default_env(&mut self) -> &mut Self212     pub fn parse_default_env(&mut self) -> &mut Self {
213         self.parse_env(Env::default())
214     }
215 
216     /// Sets the format function for formatting the log output.
217     ///
218     /// This function is called on each record logged and should format the
219     /// log record and output it to the given [`Formatter`].
220     ///
221     /// The format function is expected to output the string directly to the
222     /// `Formatter` so that implementations can use the [`std::fmt`] macros
223     /// to format and output without intermediate heap allocations. The default
224     /// `env_logger` formatter takes advantage of this.
225     ///
226     /// # Examples
227     ///
228     /// Use a custom format to write only the log message:
229     ///
230     /// ```
231     /// use std::io::Write;
232     /// use env_logger::Builder;
233     ///
234     /// let mut builder = Builder::new();
235     ///
236     /// builder.format(|buf, record| writeln!(buf, "{}", record.args()));
237     /// ```
238     ///
239     /// [`Formatter`]: fmt/struct.Formatter.html
240     /// [`String`]: https://doc.rust-lang.org/stable/std/string/struct.String.html
241     /// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html
format<F: 'static>(&mut self, format: F) -> &mut Self where F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send,242     pub fn format<F: 'static>(&mut self, format: F) -> &mut Self
243     where
244         F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send,
245     {
246         self.format.custom_format = Some(Box::new(format));
247         self
248     }
249 
250     /// Use the default format.
251     ///
252     /// This method will clear any custom format set on the builder.
default_format(&mut self) -> &mut Self253     pub fn default_format(&mut self) -> &mut Self {
254         self.format = Default::default();
255         self
256     }
257 
258     /// Whether or not to write the level in the default format.
format_level(&mut self, write: bool) -> &mut Self259     pub fn format_level(&mut self, write: bool) -> &mut Self {
260         self.format.format_level = write;
261         self
262     }
263 
264     /// Whether or not to write the module path in the default format.
format_module_path(&mut self, write: bool) -> &mut Self265     pub fn format_module_path(&mut self, write: bool) -> &mut Self {
266         self.format.format_module_path = write;
267         self
268     }
269 
270     /// Whether or not to write the target in the default format.
format_target(&mut self, write: bool) -> &mut Self271     pub fn format_target(&mut self, write: bool) -> &mut Self {
272         self.format.format_target = write;
273         self
274     }
275 
276     /// Configures the amount of spaces to use to indent multiline log records.
277     /// A value of `None` disables any kind of indentation.
format_indent(&mut self, indent: Option<usize>) -> &mut Self278     pub fn format_indent(&mut self, indent: Option<usize>) -> &mut Self {
279         self.format.format_indent = indent;
280         self
281     }
282 
283     /// Configures if timestamp should be included and in what precision.
format_timestamp(&mut self, timestamp: Option<fmt::TimestampPrecision>) -> &mut Self284     pub fn format_timestamp(&mut self, timestamp: Option<fmt::TimestampPrecision>) -> &mut Self {
285         self.format.format_timestamp = timestamp;
286         self
287     }
288 
289     /// Configures the timestamp to use second precision.
format_timestamp_secs(&mut self) -> &mut Self290     pub fn format_timestamp_secs(&mut self) -> &mut Self {
291         self.format_timestamp(Some(fmt::TimestampPrecision::Seconds))
292     }
293 
294     /// Configures the timestamp to use millisecond precision.
format_timestamp_millis(&mut self) -> &mut Self295     pub fn format_timestamp_millis(&mut self) -> &mut Self {
296         self.format_timestamp(Some(fmt::TimestampPrecision::Millis))
297     }
298 
299     /// Configures the timestamp to use microsecond precision.
format_timestamp_micros(&mut self) -> &mut Self300     pub fn format_timestamp_micros(&mut self) -> &mut Self {
301         self.format_timestamp(Some(fmt::TimestampPrecision::Micros))
302     }
303 
304     /// Configures the timestamp to use nanosecond precision.
format_timestamp_nanos(&mut self) -> &mut Self305     pub fn format_timestamp_nanos(&mut self) -> &mut Self {
306         self.format_timestamp(Some(fmt::TimestampPrecision::Nanos))
307     }
308 
309     /// Configures the end of line suffix.
format_suffix(&mut self, suffix: &'static str) -> &mut Self310     pub fn format_suffix(&mut self, suffix: &'static str) -> &mut Self {
311         self.format.format_suffix = suffix;
312         self
313     }
314 
315     /// Adds a directive to the filter for a specific module.
316     ///
317     /// # Examples
318     ///
319     /// Only include messages for info and above for logs in `path::to::module`:
320     ///
321     /// ```
322     /// use env_logger::Builder;
323     /// use log::LevelFilter;
324     ///
325     /// let mut builder = Builder::new();
326     ///
327     /// builder.filter_module("path::to::module", LevelFilter::Info);
328     /// ```
filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self329     pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self {
330         self.filter.filter_module(module, level);
331         self
332     }
333 
334     /// Adds a directive to the filter for all modules.
335     ///
336     /// # Examples
337     ///
338     /// Only include messages for info and above for logs globally:
339     ///
340     /// ```
341     /// use env_logger::Builder;
342     /// use log::LevelFilter;
343     ///
344     /// let mut builder = Builder::new();
345     ///
346     /// builder.filter_level(LevelFilter::Info);
347     /// ```
filter_level(&mut self, level: LevelFilter) -> &mut Self348     pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self {
349         self.filter.filter_level(level);
350         self
351     }
352 
353     /// Adds filters to the logger.
354     ///
355     /// The given module (if any) will log at most the specified level provided.
356     /// If no module is provided then the filter will apply to all log messages.
357     ///
358     /// # Examples
359     ///
360     /// Only include messages for info and above for logs in `path::to::module`:
361     ///
362     /// ```
363     /// use env_logger::Builder;
364     /// use log::LevelFilter;
365     ///
366     /// let mut builder = Builder::new();
367     ///
368     /// builder.filter(Some("path::to::module"), LevelFilter::Info);
369     /// ```
filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self370     pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self {
371         self.filter.filter(module, level);
372         self
373     }
374 
375     /// Parses the directives string in the same form as the `RUST_LOG`
376     /// environment variable.
377     ///
378     /// See the module documentation for more details.
parse_filters(&mut self, filters: &str) -> &mut Self379     pub fn parse_filters(&mut self, filters: &str) -> &mut Self {
380         self.filter.parse(filters);
381         self
382     }
383 
384     /// Sets the target for the log output.
385     ///
386     /// Env logger can log to either stdout, stderr or a custom pipe. The default is stderr.
387     ///
388     /// The custom pipe can be used to send the log messages to a custom sink (for example a file).
389     /// Do note that direct writes to a file can become a bottleneck due to IO operation times.
390     ///
391     /// # Examples
392     ///
393     /// Write log message to `stdout`:
394     ///
395     /// ```
396     /// use env_logger::{Builder, Target};
397     ///
398     /// let mut builder = Builder::new();
399     ///
400     /// builder.target(Target::Stdout);
401     /// ```
target(&mut self, target: fmt::Target) -> &mut Self402     pub fn target(&mut self, target: fmt::Target) -> &mut Self {
403         self.writer.target(target);
404         self
405     }
406 
407     /// Sets whether or not styles will be written.
408     ///
409     /// This can be useful in environments that don't support control characters
410     /// for setting colors.
411     ///
412     /// # Examples
413     ///
414     /// Never attempt to write styles:
415     ///
416     /// ```
417     /// use env_logger::{Builder, WriteStyle};
418     ///
419     /// let mut builder = Builder::new();
420     ///
421     /// builder.write_style(WriteStyle::Never);
422     /// ```
write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self423     pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self {
424         self.writer.write_style(write_style);
425         self
426     }
427 
428     /// Parses whether or not to write styles in the same form as the `RUST_LOG_STYLE`
429     /// environment variable.
430     ///
431     /// See the module documentation for more details.
parse_write_style(&mut self, write_style: &str) -> &mut Self432     pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self {
433         self.writer.parse_write_style(write_style);
434         self
435     }
436 
437     /// Sets whether or not the logger will be used in unit tests.
438     ///
439     /// If `is_test` is `true` then the logger will allow the testing framework to
440     /// capture log records rather than printing them to the terminal directly.
is_test(&mut self, is_test: bool) -> &mut Self441     pub fn is_test(&mut self, is_test: bool) -> &mut Self {
442         self.writer.is_test(is_test);
443         self
444     }
445 
446     /// Initializes the global logger with the built env logger.
447     ///
448     /// This should be called early in the execution of a Rust program. Any log
449     /// events that occur before initialization will be ignored.
450     ///
451     /// # Errors
452     ///
453     /// This function will fail if it is called more than once, or if another
454     /// library has already initialized a global logger.
try_init(&mut self) -> Result<(), SetLoggerError>455     pub fn try_init(&mut self) -> Result<(), SetLoggerError> {
456         let logger = self.build();
457 
458         let max_level = logger.filter();
459         let r = log::set_boxed_logger(Box::new(logger));
460 
461         if r.is_ok() {
462             log::set_max_level(max_level);
463         }
464 
465         r
466     }
467 
468     /// Initializes the global logger with the built env logger.
469     ///
470     /// This should be called early in the execution of a Rust program. Any log
471     /// events that occur before initialization will be ignored.
472     ///
473     /// # Panics
474     ///
475     /// This function will panic if it is called more than once, or if another
476     /// library has already initialized a global logger.
init(&mut self)477     pub fn init(&mut self) {
478         self.try_init()
479             .expect("Builder::init should not be called after logger initialized");
480     }
481 
482     /// Build an env logger.
483     ///
484     /// The returned logger implements the `Log` trait and can be installed manually
485     /// or nested within another logger.
build(&mut self) -> Logger486     pub fn build(&mut self) -> Logger {
487         assert!(!self.built, "attempt to re-use consumed builder");
488         self.built = true;
489 
490         Logger {
491             writer: self.writer.build(),
492             filter: self.filter.build(),
493             format: self.format.build(),
494         }
495     }
496 }
497 
498 impl std::fmt::Debug for Builder {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result499     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
500         if self.built {
501             f.debug_struct("Logger").field("built", &true).finish()
502         } else {
503             f.debug_struct("Logger")
504                 .field("filter", &self.filter)
505                 .field("writer", &self.writer)
506                 .finish()
507         }
508     }
509 }
510 
511 /// The env logger.
512 ///
513 /// This struct implements the `Log` trait from the [`log` crate][log-crate-url],
514 /// which allows it to act as a logger.
515 ///
516 /// The [`init()`], [`try_init()`], [`Builder::init()`] and [`Builder::try_init()`]
517 /// methods will each construct a `Logger` and immediately initialize it as the
518 /// default global logger.
519 ///
520 /// If you'd instead need access to the constructed `Logger`, you can use
521 /// the associated [`Builder`] and install it with the
522 /// [`log` crate][log-crate-url] directly.
523 ///
524 /// [log-crate-url]: https://docs.rs/log
525 /// [`init()`]: fn.init.html
526 /// [`try_init()`]: fn.try_init.html
527 /// [`Builder::init()`]: struct.Builder.html#method.init
528 /// [`Builder::try_init()`]: struct.Builder.html#method.try_init
529 /// [`Builder`]: struct.Builder.html
530 pub struct Logger {
531     writer: Writer,
532     filter: Filter,
533     format: FormatFn,
534 }
535 
536 impl Logger {
537     /// Creates the logger from the environment.
538     ///
539     /// The variables used to read configuration from can be tweaked before
540     /// passing in.
541     ///
542     /// # Examples
543     ///
544     /// Create a logger reading the log filter from an environment variable
545     /// called `MY_LOG`:
546     ///
547     /// ```
548     /// use env_logger::Logger;
549     ///
550     /// let logger = Logger::from_env("MY_LOG");
551     /// ```
552     ///
553     /// Create a logger using the `MY_LOG` variable for filtering and
554     /// `MY_LOG_STYLE` for whether or not to write styles:
555     ///
556     /// ```
557     /// use env_logger::{Logger, Env};
558     ///
559     /// let env = Env::new().filter_or("MY_LOG", "info").write_style_or("MY_LOG_STYLE", "always");
560     ///
561     /// let logger = Logger::from_env(env);
562     /// ```
from_env<'a, E>(env: E) -> Self where E: Into<Env<'a>>,563     pub fn from_env<'a, E>(env: E) -> Self
564     where
565         E: Into<Env<'a>>,
566     {
567         Builder::from_env(env).build()
568     }
569 
570     /// Creates the logger from the environment using default variable names.
571     ///
572     /// This method is a convenient way to call `from_env(Env::default())` without
573     /// having to use the `Env` type explicitly. The logger will use the
574     /// [default environment variables].
575     ///
576     /// # Examples
577     ///
578     /// Creates a logger using the default environment variables:
579     ///
580     /// ```
581     /// use env_logger::Logger;
582     ///
583     /// let logger = Logger::from_default_env();
584     /// ```
585     ///
586     /// [default environment variables]: struct.Env.html#default-environment-variables
from_default_env() -> Self587     pub fn from_default_env() -> Self {
588         Builder::from_default_env().build()
589     }
590 
591     /// Returns the maximum `LevelFilter` that this env logger instance is
592     /// configured to output.
filter(&self) -> LevelFilter593     pub fn filter(&self) -> LevelFilter {
594         self.filter.filter()
595     }
596 
597     /// Checks if this record matches the configured filter.
matches(&self, record: &Record) -> bool598     pub fn matches(&self, record: &Record) -> bool {
599         self.filter.matches(record)
600     }
601 }
602 
603 impl Log for Logger {
enabled(&self, metadata: &Metadata) -> bool604     fn enabled(&self, metadata: &Metadata) -> bool {
605         self.filter.enabled(metadata)
606     }
607 
log(&self, record: &Record)608     fn log(&self, record: &Record) {
609         if self.matches(record) {
610             // Log records are written to a thread-local buffer before being printed
611             // to the terminal. We clear these buffers afterwards, but they aren't shrunk
612             // so will always at least have capacity for the largest log record formatted
613             // on that thread.
614             //
615             // If multiple `Logger`s are used by the same threads then the thread-local
616             // formatter might have different color support. If this is the case the
617             // formatter and its buffer are discarded and recreated.
618 
619             thread_local! {
620                 static FORMATTER: RefCell<Option<Formatter>> = RefCell::new(None);
621             }
622 
623             let print = |formatter: &mut Formatter, record: &Record| {
624                 let _ =
625                     (self.format)(formatter, record).and_then(|_| formatter.print(&self.writer));
626 
627                 // Always clear the buffer afterwards
628                 formatter.clear();
629             };
630 
631             let printed = FORMATTER
632                 .try_with(|tl_buf| {
633                     match tl_buf.try_borrow_mut() {
634                         // There are no active borrows of the buffer
635                         Ok(mut tl_buf) => match *tl_buf {
636                             // We have a previously set formatter
637                             Some(ref mut formatter) => {
638                                 // Check the buffer style. If it's different from the logger's
639                                 // style then drop the buffer and recreate it.
640                                 if formatter.write_style() != self.writer.write_style() {
641                                     *formatter = Formatter::new(&self.writer);
642                                 }
643 
644                                 print(formatter, record);
645                             }
646                             // We don't have a previously set formatter
647                             None => {
648                                 let mut formatter = Formatter::new(&self.writer);
649                                 print(&mut formatter, record);
650 
651                                 *tl_buf = Some(formatter);
652                             }
653                         },
654                         // There's already an active borrow of the buffer (due to re-entrancy)
655                         Err(_) => {
656                             print(&mut Formatter::new(&self.writer), record);
657                         }
658                     }
659                 })
660                 .is_ok();
661 
662             if !printed {
663                 // The thread-local storage was not available (because its
664                 // destructor has already run). Create a new single-use
665                 // Formatter on the stack for this call.
666                 print(&mut Formatter::new(&self.writer), record);
667             }
668         }
669     }
670 
flush(&self)671     fn flush(&self) {}
672 }
673 
674 impl std::fmt::Debug for Logger {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result675     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
676         f.debug_struct("Logger")
677             .field("filter", &self.filter)
678             .finish()
679     }
680 }
681 
682 /// Set of environment variables to configure from.
683 ///
684 /// # Default environment variables
685 ///
686 /// By default, the `Env` will read the following environment variables:
687 ///
688 /// - `RUST_LOG`: the level filter
689 /// - `RUST_LOG_STYLE`: whether or not to print styles with records.
690 ///
691 /// These sources can be configured using the builder methods on `Env`.
692 #[derive(Debug)]
693 pub struct Env<'a> {
694     filter: Var<'a>,
695     write_style: Var<'a>,
696 }
697 
698 impl<'a> Env<'a> {
699     /// Get a default set of environment variables.
new() -> Self700     pub fn new() -> Self {
701         Self::default()
702     }
703 
704     /// Specify an environment variable to read the filter from.
filter<E>(mut self, filter_env: E) -> Self where E: Into<Cow<'a, str>>,705     pub fn filter<E>(mut self, filter_env: E) -> Self
706     where
707         E: Into<Cow<'a, str>>,
708     {
709         self.filter = Var::new(filter_env);
710 
711         self
712     }
713 
714     /// Specify an environment variable to read the filter from.
715     ///
716     /// If the variable is not set, the default value will be used.
filter_or<E, V>(mut self, filter_env: E, default: V) -> Self where E: Into<Cow<'a, str>>, V: Into<Cow<'a, str>>,717     pub fn filter_or<E, V>(mut self, filter_env: E, default: V) -> Self
718     where
719         E: Into<Cow<'a, str>>,
720         V: Into<Cow<'a, str>>,
721     {
722         self.filter = Var::new_with_default(filter_env, default);
723 
724         self
725     }
726 
727     /// Use the default environment variable to read the filter from.
728     ///
729     /// If the variable is not set, the default value will be used.
default_filter_or<V>(mut self, default: V) -> Self where V: Into<Cow<'a, str>>,730     pub fn default_filter_or<V>(mut self, default: V) -> Self
731     where
732         V: Into<Cow<'a, str>>,
733     {
734         self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default);
735 
736         self
737     }
738 
get_filter(&self) -> Option<String>739     fn get_filter(&self) -> Option<String> {
740         self.filter.get()
741     }
742 
743     /// Specify an environment variable to read the style from.
write_style<E>(mut self, write_style_env: E) -> Self where E: Into<Cow<'a, str>>,744     pub fn write_style<E>(mut self, write_style_env: E) -> Self
745     where
746         E: Into<Cow<'a, str>>,
747     {
748         self.write_style = Var::new(write_style_env);
749 
750         self
751     }
752 
753     /// Specify an environment variable to read the style from.
754     ///
755     /// If the variable is not set, the default value will be used.
write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self where E: Into<Cow<'a, str>>, V: Into<Cow<'a, str>>,756     pub fn write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self
757     where
758         E: Into<Cow<'a, str>>,
759         V: Into<Cow<'a, str>>,
760     {
761         self.write_style = Var::new_with_default(write_style_env, default);
762 
763         self
764     }
765 
766     /// Use the default environment variable to read the style from.
767     ///
768     /// If the variable is not set, the default value will be used.
default_write_style_or<V>(mut self, default: V) -> Self where V: Into<Cow<'a, str>>,769     pub fn default_write_style_or<V>(mut self, default: V) -> Self
770     where
771         V: Into<Cow<'a, str>>,
772     {
773         self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default);
774 
775         self
776     }
777 
get_write_style(&self) -> Option<String>778     fn get_write_style(&self) -> Option<String> {
779         self.write_style.get()
780     }
781 }
782 
783 impl<'a, T> From<T> for Env<'a>
784 where
785     T: Into<Cow<'a, str>>,
786 {
from(filter_env: T) -> Self787     fn from(filter_env: T) -> Self {
788         Env::default().filter(filter_env.into())
789     }
790 }
791 
792 impl<'a> Default for Env<'a> {
default() -> Self793     fn default() -> Self {
794         Env {
795             filter: Var::new(DEFAULT_FILTER_ENV),
796             write_style: Var::new(DEFAULT_WRITE_STYLE_ENV),
797         }
798     }
799 }
800 
801 #[derive(Debug)]
802 struct Var<'a> {
803     name: Cow<'a, str>,
804     default: Option<Cow<'a, str>>,
805 }
806 
807 impl<'a> Var<'a> {
new<E>(name: E) -> Self where E: Into<Cow<'a, str>>,808     fn new<E>(name: E) -> Self
809     where
810         E: Into<Cow<'a, str>>,
811     {
812         Var {
813             name: name.into(),
814             default: None,
815         }
816     }
817 
new_with_default<E, V>(name: E, default: V) -> Self where E: Into<Cow<'a, str>>, V: Into<Cow<'a, str>>,818     fn new_with_default<E, V>(name: E, default: V) -> Self
819     where
820         E: Into<Cow<'a, str>>,
821         V: Into<Cow<'a, str>>,
822     {
823         Var {
824             name: name.into(),
825             default: Some(default.into()),
826         }
827     }
828 
get(&self) -> Option<String>829     fn get(&self) -> Option<String> {
830         env::var(&*self.name)
831             .ok()
832             .or_else(|| self.default.to_owned().map(|v| v.into_owned()))
833     }
834 }
835 
836 /// Attempts to initialize the global logger with an env logger.
837 ///
838 /// This should be called early in the execution of a Rust program. Any log
839 /// events that occur before initialization will be ignored.
840 ///
841 /// # Errors
842 ///
843 /// This function will fail if it is called more than once, or if another
844 /// library has already initialized a global logger.
try_init() -> Result<(), SetLoggerError>845 pub fn try_init() -> Result<(), SetLoggerError> {
846     try_init_from_env(Env::default())
847 }
848 
849 /// Initializes the global logger with an env logger.
850 ///
851 /// This should be called early in the execution of a Rust program. Any log
852 /// events that occur before initialization will be ignored.
853 ///
854 /// # Panics
855 ///
856 /// This function will panic if it is called more than once, or if another
857 /// library has already initialized a global logger.
init()858 pub fn init() {
859     try_init().expect("env_logger::init should not be called after logger initialized");
860 }
861 
862 /// Attempts to initialize the global logger with an env logger from the given
863 /// environment variables.
864 ///
865 /// This should be called early in the execution of a Rust program. Any log
866 /// events that occur before initialization will be ignored.
867 ///
868 /// # Examples
869 ///
870 /// Initialise a logger using the `MY_LOG` environment variable for filters
871 /// and `MY_LOG_STYLE` for writing colors:
872 ///
873 /// ```
874 /// use env_logger::{Builder, Env};
875 ///
876 /// # fn run() -> Result<(), Box<dyn ::std::error::Error>> {
877 /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
878 ///
879 /// env_logger::try_init_from_env(env)?;
880 ///
881 /// Ok(())
882 /// # }
883 /// # run().unwrap();
884 /// ```
885 ///
886 /// # Errors
887 ///
888 /// This function will fail if it is called more than once, or if another
889 /// library has already initialized a global logger.
try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError> where E: Into<Env<'a>>,890 pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError>
891 where
892     E: Into<Env<'a>>,
893 {
894     let mut builder = Builder::from_env(env);
895 
896     builder.try_init()
897 }
898 
899 /// Initializes the global logger with an env logger from the given environment
900 /// variables.
901 ///
902 /// This should be called early in the execution of a Rust program. Any log
903 /// events that occur before initialization will be ignored.
904 ///
905 /// # Examples
906 ///
907 /// Initialise a logger using the `MY_LOG` environment variable for filters
908 /// and `MY_LOG_STYLE` for writing colors:
909 ///
910 /// ```
911 /// use env_logger::{Builder, Env};
912 ///
913 /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
914 ///
915 /// env_logger::init_from_env(env);
916 /// ```
917 ///
918 /// # Panics
919 ///
920 /// This function will panic if it is called more than once, or if another
921 /// library has already initialized a global logger.
init_from_env<'a, E>(env: E) where E: Into<Env<'a>>,922 pub fn init_from_env<'a, E>(env: E)
923 where
924     E: Into<Env<'a>>,
925 {
926     try_init_from_env(env)
927         .expect("env_logger::init_from_env should not be called after logger initialized");
928 }
929 
930 /// Create a new builder with the default environment variables.
931 ///
932 /// The builder can be configured before being initialized.
933 /// This is a convenient way of calling [`Builder::from_default_env`].
934 ///
935 /// [`Builder::from_default_env`]: struct.Builder.html#method.from_default_env
builder() -> Builder936 pub fn builder() -> Builder {
937     Builder::from_default_env()
938 }
939 
940 /// Create a builder from the given environment variables.
941 ///
942 /// The builder can be configured before being initialized.
943 #[deprecated(
944     since = "0.8.0",
945     note = "Prefer `env_logger::Builder::from_env()` instead."
946 )]
from_env<'a, E>(env: E) -> Builder where E: Into<Env<'a>>,947 pub fn from_env<'a, E>(env: E) -> Builder
948 where
949     E: Into<Env<'a>>,
950 {
951     Builder::from_env(env)
952 }
953 
954 #[cfg(test)]
955 mod tests {
956     use super::*;
957 
958     #[test]
env_get_filter_reads_from_var_if_set()959     fn env_get_filter_reads_from_var_if_set() {
960         env::set_var("env_get_filter_reads_from_var_if_set", "from var");
961 
962         let env = Env::new().filter_or("env_get_filter_reads_from_var_if_set", "from default");
963 
964         assert_eq!(Some("from var".to_owned()), env.get_filter());
965     }
966 
967     #[test]
env_get_filter_reads_from_default_if_var_not_set()968     fn env_get_filter_reads_from_default_if_var_not_set() {
969         env::remove_var("env_get_filter_reads_from_default_if_var_not_set");
970 
971         let env = Env::new().filter_or(
972             "env_get_filter_reads_from_default_if_var_not_set",
973             "from default",
974         );
975 
976         assert_eq!(Some("from default".to_owned()), env.get_filter());
977     }
978 
979     #[test]
env_get_write_style_reads_from_var_if_set()980     fn env_get_write_style_reads_from_var_if_set() {
981         env::set_var("env_get_write_style_reads_from_var_if_set", "from var");
982 
983         let env =
984             Env::new().write_style_or("env_get_write_style_reads_from_var_if_set", "from default");
985 
986         assert_eq!(Some("from var".to_owned()), env.get_write_style());
987     }
988 
989     #[test]
env_get_write_style_reads_from_default_if_var_not_set()990     fn env_get_write_style_reads_from_default_if_var_not_set() {
991         env::remove_var("env_get_write_style_reads_from_default_if_var_not_set");
992 
993         let env = Env::new().write_style_or(
994             "env_get_write_style_reads_from_default_if_var_not_set",
995             "from default",
996         );
997 
998         assert_eq!(Some("from default".to_owned()), env.get_write_style());
999     }
1000 
1001     #[test]
builder_parse_env_overrides_existing_filters()1002     fn builder_parse_env_overrides_existing_filters() {
1003         env::set_var(
1004             "builder_parse_default_env_overrides_existing_filters",
1005             "debug",
1006         );
1007         let env = Env::new().filter("builder_parse_default_env_overrides_existing_filters");
1008 
1009         let mut builder = Builder::new();
1010         builder.filter_level(LevelFilter::Trace);
1011         // Overrides global level to debug
1012         builder.parse_env(env);
1013 
1014         assert_eq!(builder.filter.build().filter(), LevelFilter::Debug);
1015     }
1016 }
1017