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.format_level = write;
262        self
263    }
264
265    /// Whether or not to write the module path in the default format.
266    pub fn format_module_path(&mut self, write: bool) -> &mut Self {
267        self.format.format_module_path = write;
268        self
269    }
270
271    /// Whether or not to write the target in the default format.
272    pub fn format_target(&mut self, write: bool) -> &mut Self {
273        self.format.format_target = write;
274        self
275    }
276
277    /// Configures the amount of spaces to use to indent multiline log records.
278    /// A value of `None` disables any kind of indentation.
279    pub fn format_indent(&mut self, indent: Option<usize>) -> &mut Self {
280        self.format.format_indent = indent;
281        self
282    }
283
284    /// Configures if timestamp should be included and in what precision.
285    pub fn format_timestamp(&mut self, timestamp: Option<fmt::TimestampPrecision>) -> &mut Self {
286        self.format.format_timestamp = timestamp;
287        self
288    }
289
290    /// Configures the timestamp to use second precision.
291    pub fn format_timestamp_secs(&mut self) -> &mut Self {
292        self.format_timestamp(Some(fmt::TimestampPrecision::Seconds))
293    }
294
295    /// Configures the timestamp to use millisecond precision.
296    pub fn format_timestamp_millis(&mut self) -> &mut Self {
297        self.format_timestamp(Some(fmt::TimestampPrecision::Millis))
298    }
299
300    /// Configures the timestamp to use microsecond precision.
301    pub fn format_timestamp_micros(&mut self) -> &mut Self {
302        self.format_timestamp(Some(fmt::TimestampPrecision::Micros))
303    }
304
305    /// Configures the timestamp to use nanosecond precision.
306    pub fn format_timestamp_nanos(&mut self) -> &mut Self {
307        self.format_timestamp(Some(fmt::TimestampPrecision::Nanos))
308    }
309
310    /// Configures the end of line suffix.
311    pub fn format_suffix(&mut self, suffix: &'static str) -> &mut Self {
312        self.format.format_suffix = suffix;
313        self
314    }
315
316    /// Set the format for structured key/value pairs in the log record
317    ///
318    /// With the default format, this function is called for each record and should format
319    /// the structured key-value pairs as returned by [`log::Record::key_values`].
320    ///
321    /// The format function is expected to output the string directly to the `Formatter` so that
322    /// implementations can use the [`std::fmt`] macros, similar to the main format function.
323    ///
324    /// The default format uses a space to separate each key-value pair, with an "=" between
325    /// the key and value.
326    #[cfg(feature = "unstable-kv")]
327    pub fn format_key_values<F>(&mut self, format: F) -> &mut Self
328    where
329        F: Fn(&mut Formatter, &dyn log::kv::Source) -> io::Result<()> + Sync + Send + 'static,
330    {
331        self.format.kv_format = Some(Box::new(format));
332        self
333    }
334
335    /// Adds a directive to the filter for a specific module.
336    ///
337    /// # Examples
338    ///
339    /// Only include messages for info and above for logs in `path::to::module`:
340    ///
341    /// ```
342    /// use env_logger::Builder;
343    /// use log::LevelFilter;
344    ///
345    /// let mut builder = Builder::new();
346    ///
347    /// builder.filter_module("path::to::module", LevelFilter::Info);
348    /// ```
349    pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self {
350        self.filter.filter_module(module, level);
351        self
352    }
353
354    /// Adds a directive to the filter for all modules.
355    ///
356    /// # Examples
357    ///
358    /// Only include messages for info and above for logs globally:
359    ///
360    /// ```
361    /// use env_logger::Builder;
362    /// use log::LevelFilter;
363    ///
364    /// let mut builder = Builder::new();
365    ///
366    /// builder.filter_level(LevelFilter::Info);
367    /// ```
368    pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self {
369        self.filter.filter_level(level);
370        self
371    }
372
373    /// Adds filters to the logger.
374    ///
375    /// The given module (if any) will log at most the specified level provided.
376    /// If no module is provided then the filter will apply to all log messages.
377    ///
378    /// # Examples
379    ///
380    /// Only include messages for info and above for logs in `path::to::module`:
381    ///
382    /// ```
383    /// use env_logger::Builder;
384    /// use log::LevelFilter;
385    ///
386    /// let mut builder = Builder::new();
387    ///
388    /// builder.filter(Some("path::to::module"), LevelFilter::Info);
389    /// ```
390    pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self {
391        self.filter.filter(module, level);
392        self
393    }
394
395    /// Parses the directives string in the same form as the `RUST_LOG`
396    /// environment variable.
397    ///
398    /// See the module documentation for more details.
399    pub fn parse_filters(&mut self, filters: &str) -> &mut Self {
400        self.filter.parse(filters);
401        self
402    }
403
404    /// Sets the target for the log output.
405    ///
406    /// Env logger can log to either stdout, stderr or a custom pipe. The default is stderr.
407    ///
408    /// The custom pipe can be used to send the log messages to a custom sink (for example a file).
409    /// Do note that direct writes to a file can become a bottleneck due to IO operation times.
410    ///
411    /// # Examples
412    ///
413    /// Write log message to `stdout`:
414    ///
415    /// ```
416    /// use env_logger::{Builder, Target};
417    ///
418    /// let mut builder = Builder::new();
419    ///
420    /// builder.target(Target::Stdout);
421    /// ```
422    pub fn target(&mut self, target: fmt::Target) -> &mut Self {
423        self.writer.target(target);
424        self
425    }
426
427    /// Sets whether or not styles will be written.
428    ///
429    /// This can be useful in environments that don't support control characters
430    /// for setting colors.
431    ///
432    /// # Examples
433    ///
434    /// Never attempt to write styles:
435    ///
436    /// ```
437    /// use env_logger::{Builder, WriteStyle};
438    ///
439    /// let mut builder = Builder::new();
440    ///
441    /// builder.write_style(WriteStyle::Never);
442    /// ```
443    pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self {
444        self.writer.write_style(write_style);
445        self
446    }
447
448    /// Parses whether or not to write styles in the same form as the `RUST_LOG_STYLE`
449    /// environment variable.
450    ///
451    /// See the module documentation for more details.
452    pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self {
453        self.writer.parse_write_style(write_style);
454        self
455    }
456
457    /// Sets whether or not the logger will be used in unit tests.
458    ///
459    /// If `is_test` is `true` then the logger will allow the testing framework to
460    /// capture log records rather than printing them to the terminal directly.
461    pub fn is_test(&mut self, is_test: bool) -> &mut Self {
462        self.writer.is_test(is_test);
463        self
464    }
465
466    /// Initializes the global logger with the built env logger.
467    ///
468    /// This should be called early in the execution of a Rust program. Any log
469    /// events that occur before initialization will be ignored.
470    ///
471    /// # Errors
472    ///
473    /// This function will fail if it is called more than once, or if another
474    /// library has already initialized a global logger.
475    pub fn try_init(&mut self) -> Result<(), SetLoggerError> {
476        let logger = self.build();
477
478        let max_level = logger.filter();
479        let r = log::set_boxed_logger(Box::new(logger));
480
481        if r.is_ok() {
482            log::set_max_level(max_level);
483        }
484
485        r
486    }
487
488    /// Initializes the global logger with the built env logger.
489    ///
490    /// This should be called early in the execution of a Rust program. Any log
491    /// events that occur before initialization will be ignored.
492    ///
493    /// # Panics
494    ///
495    /// This function will panic if it is called more than once, or if another
496    /// library has already initialized a global logger.
497    pub fn init(&mut self) {
498        self.try_init()
499            .expect("Builder::init should not be called after logger initialized");
500    }
501
502    /// Build an env logger.
503    ///
504    /// The returned logger implements the `Log` trait and can be installed manually
505    /// or nested within another logger.
506    pub fn build(&mut self) -> Logger {
507        assert!(!self.built, "attempt to re-use consumed builder");
508        self.built = true;
509
510        Logger {
511            writer: self.writer.build(),
512            filter: self.filter.build(),
513            format: self.format.build(),
514        }
515    }
516}
517
518impl std::fmt::Debug for Builder {
519    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
520        if self.built {
521            f.debug_struct("Logger").field("built", &true).finish()
522        } else {
523            f.debug_struct("Logger")
524                .field("filter", &self.filter)
525                .field("writer", &self.writer)
526                .finish()
527        }
528    }
529}
530
531/// The env logger.
532///
533/// This struct implements the `Log` trait from the [`log` crate][log-crate-url],
534/// which allows it to act as a logger.
535///
536/// The [`init()`], [`try_init()`], [`Builder::init()`] and [`Builder::try_init()`]
537/// methods will each construct a `Logger` and immediately initialize it as the
538/// default global logger.
539///
540/// If you'd instead need access to the constructed `Logger`, you can use
541/// the associated [`Builder`] and install it with the
542/// [`log` crate][log-crate-url] directly.
543///
544/// [log-crate-url]: https://docs.rs/log
545/// [`init()`]: fn.init.html
546/// [`try_init()`]: fn.try_init.html
547/// [`Builder::init()`]: struct.Builder.html#method.init
548/// [`Builder::try_init()`]: struct.Builder.html#method.try_init
549/// [`Builder`]: struct.Builder.html
550pub struct Logger {
551    writer: Writer,
552    filter: env_filter::Filter,
553    format: FormatFn,
554}
555
556impl Logger {
557    /// Creates the logger from the environment.
558    ///
559    /// The variables used to read configuration from can be tweaked before
560    /// passing in.
561    ///
562    /// # Examples
563    ///
564    /// Create a logger reading the log filter from an environment variable
565    /// called `MY_LOG`:
566    ///
567    /// ```
568    /// use env_logger::Logger;
569    ///
570    /// let logger = Logger::from_env("MY_LOG");
571    /// ```
572    ///
573    /// Create a logger using the `MY_LOG` variable for filtering and
574    /// `MY_LOG_STYLE` for whether or not to write styles:
575    ///
576    /// ```
577    /// use env_logger::{Logger, Env};
578    ///
579    /// let env = Env::new().filter_or("MY_LOG", "info").write_style_or("MY_LOG_STYLE", "always");
580    ///
581    /// let logger = Logger::from_env(env);
582    /// ```
583    pub fn from_env<'a, E>(env: E) -> Self
584    where
585        E: Into<Env<'a>>,
586    {
587        Builder::from_env(env).build()
588    }
589
590    /// Creates the logger from the environment using default variable names.
591    ///
592    /// This method is a convenient way to call `from_env(Env::default())` without
593    /// having to use the `Env` type explicitly. The logger will use the
594    /// [default environment variables].
595    ///
596    /// # Examples
597    ///
598    /// Creates a logger using the default environment variables:
599    ///
600    /// ```
601    /// use env_logger::Logger;
602    ///
603    /// let logger = Logger::from_default_env();
604    /// ```
605    ///
606    /// [default environment variables]: struct.Env.html#default-environment-variables
607    pub fn from_default_env() -> Self {
608        Builder::from_default_env().build()
609    }
610
611    /// Returns the maximum `LevelFilter` that this env logger instance is
612    /// configured to output.
613    pub fn filter(&self) -> LevelFilter {
614        self.filter.filter()
615    }
616
617    /// Checks if this record matches the configured filter.
618    pub fn matches(&self, record: &Record<'_>) -> bool {
619        self.filter.matches(record)
620    }
621}
622
623impl Log for Logger {
624    fn enabled(&self, metadata: &Metadata<'_>) -> bool {
625        self.filter.enabled(metadata)
626    }
627
628    fn log(&self, record: &Record<'_>) {
629        if self.matches(record) {
630            // Log records are written to a thread-local buffer before being printed
631            // to the terminal. We clear these buffers afterwards, but they aren't shrunk
632            // so will always at least have capacity for the largest log record formatted
633            // on that thread.
634            //
635            // If multiple `Logger`s are used by the same threads then the thread-local
636            // formatter might have different color support. If this is the case the
637            // formatter and its buffer are discarded and recreated.
638
639            thread_local! {
640                static FORMATTER: RefCell<Option<Formatter>> = const { RefCell::new(None) };
641            }
642
643            let print = |formatter: &mut Formatter, record: &Record<'_>| {
644                let _ =
645                    (self.format)(formatter, record).and_then(|_| formatter.print(&self.writer));
646
647                // Always clear the buffer afterwards
648                formatter.clear();
649            };
650
651            let printed = FORMATTER
652                .try_with(|tl_buf| {
653                    if let Ok(mut tl_buf) = tl_buf.try_borrow_mut() {
654                        // There are no active borrows of the buffer
655                        if let Some(ref mut formatter) = *tl_buf {
656                            // We have a previously set formatter
657
658                            // Check the buffer style. If it's different from the logger's
659                            // style then drop the buffer and recreate it.
660                            if formatter.write_style() != self.writer.write_style() {
661                                *formatter = Formatter::new(&self.writer);
662                            }
663
664                            print(formatter, record);
665                        } else {
666                            // We don't have a previously set formatter
667                            let mut formatter = Formatter::new(&self.writer);
668                            print(&mut formatter, record);
669
670                            *tl_buf = Some(formatter);
671                        }
672                    } else {
673                        // There's already an active borrow of the buffer (due to re-entrancy)
674                        print(&mut Formatter::new(&self.writer), record);
675                    }
676                })
677                .is_ok();
678
679            if !printed {
680                // The thread-local storage was not available (because its
681                // destructor has already run). Create a new single-use
682                // Formatter on the stack for this call.
683                print(&mut Formatter::new(&self.writer), record);
684            }
685        }
686    }
687
688    fn flush(&self) {}
689}
690
691impl std::fmt::Debug for Logger {
692    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
693        f.debug_struct("Logger")
694            .field("filter", &self.filter)
695            .finish()
696    }
697}
698
699/// Set of environment variables to configure from.
700///
701/// # Default environment variables
702///
703/// By default, the `Env` will read the following environment variables:
704///
705/// - `RUST_LOG`: the level filter
706/// - `RUST_LOG_STYLE`: whether or not to print styles with records.
707///
708/// These sources can be configured using the builder methods on `Env`.
709#[derive(Debug)]
710pub struct Env<'a> {
711    filter: Var<'a>,
712    write_style: Var<'a>,
713}
714
715impl<'a> Env<'a> {
716    /// Get a default set of environment variables.
717    pub fn new() -> Self {
718        Self::default()
719    }
720
721    /// Specify an environment variable to read the filter from.
722    pub fn filter<E>(mut self, filter_env: E) -> Self
723    where
724        E: Into<Cow<'a, str>>,
725    {
726        self.filter = Var::new(filter_env);
727
728        self
729    }
730
731    /// Specify an environment variable to read the filter from.
732    ///
733    /// If the variable is not set, the default value will be used.
734    pub fn filter_or<E, V>(mut self, filter_env: E, default: V) -> Self
735    where
736        E: Into<Cow<'a, str>>,
737        V: Into<Cow<'a, str>>,
738    {
739        self.filter = Var::new_with_default(filter_env, default);
740
741        self
742    }
743
744    /// Use the default environment variable to read the filter from.
745    ///
746    /// If the variable is not set, the default value will be used.
747    pub fn default_filter_or<V>(mut self, default: V) -> Self
748    where
749        V: Into<Cow<'a, str>>,
750    {
751        self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default);
752
753        self
754    }
755
756    fn get_filter(&self) -> Option<String> {
757        self.filter.get()
758    }
759
760    /// Specify an environment variable to read the style from.
761    pub fn write_style<E>(mut self, write_style_env: E) -> Self
762    where
763        E: Into<Cow<'a, str>>,
764    {
765        self.write_style = Var::new(write_style_env);
766
767        self
768    }
769
770    /// Specify an environment variable to read the style from.
771    ///
772    /// If the variable is not set, the default value will be used.
773    pub fn write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self
774    where
775        E: Into<Cow<'a, str>>,
776        V: Into<Cow<'a, str>>,
777    {
778        self.write_style = Var::new_with_default(write_style_env, default);
779
780        self
781    }
782
783    /// Use the default environment variable to read the style from.
784    ///
785    /// If the variable is not set, the default value will be used.
786    pub fn default_write_style_or<V>(mut self, default: V) -> Self
787    where
788        V: Into<Cow<'a, str>>,
789    {
790        self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default);
791
792        self
793    }
794
795    fn get_write_style(&self) -> Option<String> {
796        self.write_style.get()
797    }
798}
799
800impl<'a, T> From<T> for Env<'a>
801where
802    T: Into<Cow<'a, str>>,
803{
804    fn from(filter_env: T) -> Self {
805        Env::default().filter(filter_env.into())
806    }
807}
808
809impl<'a> Default for Env<'a> {
810    fn default() -> Self {
811        Env {
812            filter: Var::new(DEFAULT_FILTER_ENV),
813            write_style: Var::new(DEFAULT_WRITE_STYLE_ENV),
814        }
815    }
816}
817
818#[derive(Debug)]
819struct Var<'a> {
820    name: Cow<'a, str>,
821    default: Option<Cow<'a, str>>,
822}
823
824impl<'a> Var<'a> {
825    fn new<E>(name: E) -> Self
826    where
827        E: Into<Cow<'a, str>>,
828    {
829        Var {
830            name: name.into(),
831            default: None,
832        }
833    }
834
835    fn new_with_default<E, V>(name: E, default: V) -> Self
836    where
837        E: Into<Cow<'a, str>>,
838        V: Into<Cow<'a, str>>,
839    {
840        Var {
841            name: name.into(),
842            default: Some(default.into()),
843        }
844    }
845
846    fn get(&self) -> Option<String> {
847        env::var(&*self.name)
848            .ok()
849            .or_else(|| self.default.clone().map(|v| v.into_owned()))
850    }
851}
852
853/// Attempts to initialize the global logger with an env logger.
854///
855/// This should be called early in the execution of a Rust program. Any log
856/// events that occur before initialization will be ignored.
857///
858/// # Errors
859///
860/// This function will fail if it is called more than once, or if another
861/// library has already initialized a global logger.
862pub fn try_init() -> Result<(), SetLoggerError> {
863    try_init_from_env(Env::default())
864}
865
866/// Initializes the global logger with an env logger.
867///
868/// This should be called early in the execution of a Rust program. Any log
869/// events that occur before initialization will be ignored.
870///
871/// # Panics
872///
873/// This function will panic if it is called more than once, or if another
874/// library has already initialized a global logger.
875pub fn init() {
876    try_init().expect("env_logger::init should not be called after logger initialized");
877}
878
879/// Attempts to initialize the global logger with an env logger from the given
880/// environment variables.
881///
882/// This should be called early in the execution of a Rust program. Any log
883/// events that occur before initialization will be ignored.
884///
885/// # Examples
886///
887/// Initialise a logger using the `MY_LOG` environment variable for filters
888/// and `MY_LOG_STYLE` for writing colors:
889///
890/// ```
891/// use env_logger::{Builder, Env};
892///
893/// # fn run() -> Result<(), Box<dyn ::std::error::Error>> {
894/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
895///
896/// env_logger::try_init_from_env(env)?;
897///
898/// Ok(())
899/// # }
900/// # run().unwrap();
901/// ```
902///
903/// # Errors
904///
905/// This function will fail if it is called more than once, or if another
906/// library has already initialized a global logger.
907pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError>
908where
909    E: Into<Env<'a>>,
910{
911    let mut builder = Builder::from_env(env);
912
913    builder.try_init()
914}
915
916/// Initializes the global logger with an env logger from the given environment
917/// variables.
918///
919/// This should be called early in the execution of a Rust program. Any log
920/// events that occur before initialization will be ignored.
921///
922/// # Examples
923///
924/// Initialise a logger using the `MY_LOG` environment variable for filters
925/// and `MY_LOG_STYLE` for writing colors:
926///
927/// ```
928/// use env_logger::{Builder, Env};
929///
930/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
931///
932/// env_logger::init_from_env(env);
933/// ```
934///
935/// # Panics
936///
937/// This function will panic if it is called more than once, or if another
938/// library has already initialized a global logger.
939pub fn init_from_env<'a, E>(env: E)
940where
941    E: Into<Env<'a>>,
942{
943    try_init_from_env(env)
944        .expect("env_logger::init_from_env should not be called after logger initialized");
945}
946
947/// Create a new builder with the default environment variables.
948///
949/// The builder can be configured before being initialized.
950/// This is a convenient way of calling [`Builder::from_default_env`].
951///
952/// [`Builder::from_default_env`]: struct.Builder.html#method.from_default_env
953pub fn builder() -> Builder {
954    Builder::from_default_env()
955}
956
957/// Create a builder from the given environment variables.
958///
959/// The builder can be configured before being initialized.
960#[deprecated(
961    since = "0.8.0",
962    note = "Prefer `env_logger::Builder::from_env()` instead."
963)]
964pub fn from_env<'a, E>(env: E) -> Builder
965where
966    E: Into<Env<'a>>,
967{
968    Builder::from_env(env)
969}
970
971#[cfg(test)]
972mod tests {
973    use super::*;
974
975    #[test]
976    fn env_get_filter_reads_from_var_if_set() {
977        env::set_var("env_get_filter_reads_from_var_if_set", "from var");
978
979        let env = Env::new().filter_or("env_get_filter_reads_from_var_if_set", "from default");
980
981        assert_eq!(Some("from var".to_owned()), env.get_filter());
982    }
983
984    #[test]
985    fn env_get_filter_reads_from_default_if_var_not_set() {
986        env::remove_var("env_get_filter_reads_from_default_if_var_not_set");
987
988        let env = Env::new().filter_or(
989            "env_get_filter_reads_from_default_if_var_not_set",
990            "from default",
991        );
992
993        assert_eq!(Some("from default".to_owned()), env.get_filter());
994    }
995
996    #[test]
997    fn env_get_write_style_reads_from_var_if_set() {
998        env::set_var("env_get_write_style_reads_from_var_if_set", "from var");
999
1000        let env =
1001            Env::new().write_style_or("env_get_write_style_reads_from_var_if_set", "from default");
1002
1003        assert_eq!(Some("from var".to_owned()), env.get_write_style());
1004    }
1005
1006    #[test]
1007    fn env_get_write_style_reads_from_default_if_var_not_set() {
1008        env::remove_var("env_get_write_style_reads_from_default_if_var_not_set");
1009
1010        let env = Env::new().write_style_or(
1011            "env_get_write_style_reads_from_default_if_var_not_set",
1012            "from default",
1013        );
1014
1015        assert_eq!(Some("from default".to_owned()), env.get_write_style());
1016    }
1017
1018    #[test]
1019    fn builder_parse_env_overrides_existing_filters() {
1020        env::set_var(
1021            "builder_parse_default_env_overrides_existing_filters",
1022            "debug",
1023        );
1024        let env = Env::new().filter("builder_parse_default_env_overrides_existing_filters");
1025
1026        let mut builder = Builder::new();
1027        builder.filter_level(LevelFilter::Trace);
1028        // Overrides global level to debug
1029        builder.parse_env(env);
1030
1031        assert_eq!(builder.filter.build().filter(), LevelFilter::Debug);
1032    }
1033}