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(name:"built", &true).finish()
502 } else {
503 f&mut DebugStruct<'_, '_>.debug_struct("Logger")
504 .field("filter", &self.filter)
505 .field(name:"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&mut DebugStruct<'_, '_>.debug_struct("Logger")
677 .field(name:"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: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(msg:"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 = 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(msg:"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}
1017