env_logger/
logger.rs

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