env_logger/
logger.rs

1use std::{borrow::Cow, cell::RefCell, env, io};
2
3use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};
4
5use crate::filter;
6use crate::filter::Filter;
7use crate::fmt;
8use crate::fmt::writer::{self, Writer};
9use crate::fmt::{FormatFn, Formatter};
10
11/// The default name for the environment variable to read filters from.
12pub const DEFAULT_FILTER_ENV: &str = "RUST_LOG";
13
14/// The default name for the environment variable to read style preferences from.
15pub 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)]
40pub struct Builder {
41    filter: filter::Builder,
42    writer: writer::Builder,
43    format: fmt::Builder,
44    built: bool,
45}
46
47impl 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
74    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    /// ```
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    /// ```
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
186    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
212    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
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.
253    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.
259    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.
265    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.
271    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.
278    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.
284    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.
290    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.
295    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.
300    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.
305    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.
310    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    /// ```
329    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    /// ```
348    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    /// ```
370    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.
379    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    /// ```
402    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    /// ```
423    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.
432    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.
441    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.
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.
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.
486    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
498impl std::fmt::Debug for Builder {
499    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
530pub struct Logger {
531    writer: Writer,
532    filter: Filter,
533    format: FormatFn,
534}
535
536impl 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    /// ```
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
587    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.
593    pub fn filter(&self) -> LevelFilter {
594        self.filter.filter()
595    }
596
597    /// Checks if this record matches the configured filter.
598    pub fn matches(&self, record: &Record) -> bool {
599        self.filter.matches(record)
600    }
601}
602
603impl Log for Logger {
604    fn enabled(&self, metadata: &Metadata) -> bool {
605        self.filter.enabled(metadata)
606    }
607
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
671    fn flush(&self) {}
672}
673
674impl std::fmt::Debug for Logger {
675    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)]
693pub struct Env<'a> {
694    filter: Var<'a>,
695    write_style: Var<'a>,
696}
697
698impl<'a> Env<'a> {
699    /// Get a default set of environment variables.
700    pub fn new() -> Self {
701        Self::default()
702    }
703
704    /// Specify an environment variable to read the filter from.
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.
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.
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
739    fn get_filter(&self) -> Option<String> {
740        self.filter.get()
741    }
742
743    /// Specify an environment variable to read the style from.
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.
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.
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
778    fn get_write_style(&self) -> Option<String> {
779        self.write_style.get()
780    }
781}
782
783impl<'a, T> From<T> for Env<'a>
784where
785    T: Into<Cow<'a, str>>,
786{
787    fn from(filter_env: T) -> Self {
788        Env::default().filter(filter_env.into())
789    }
790}
791
792impl<'a> Default for Env<'a> {
793    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)]
802struct Var<'a> {
803    name: Cow<'a, str>,
804    default: Option<Cow<'a, str>>,
805}
806
807impl<'a> Var<'a> {
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
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
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.
845pub 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.
858pub 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.
890pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError>
891where
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.
922pub fn init_from_env<'a, E>(env: E)
923where
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
936pub 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)]
947pub fn from_env<'a, E>(env: E) -> Builder
948where
949    E: Into<Env<'a>>,
950{
951    Builder::from_env(env)
952}
953
954#[cfg(test)]
955mod tests {
956    use super::*;
957
958    #[test]
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]
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]
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]
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]
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}