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