Coverage Report

Created: 2025-12-08 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/env_logger-0.11.8/src/logger.rs
Line
Count
Source
1
use std::{borrow::Cow, cell::RefCell, env, io};
2
3
use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};
4
5
use crate::fmt;
6
use crate::fmt::writer::{self, Writer};
7
use crate::fmt::{FormatFn, Formatter};
8
9
/// The default name for the environment variable to read filters from.
10
pub const DEFAULT_FILTER_ENV: &str = "RUST_LOG";
11
12
/// The default name for the environment variable to read style preferences from.
13
pub 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)]
38
pub struct Builder {
39
    filter: env_filter::Builder,
40
    writer: writer::Builder,
41
    format: fmt::Builder,
42
    built: bool,
43
}
44
45
impl 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
4
    pub fn new() -> Builder {
73
4
        Default::default()
74
4
    }
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
4
    pub fn from_env<'a, E>(env: E) -> Self
105
4
    where
106
4
        E: Into<Env<'a>>,
107
    {
108
4
        let mut builder = Builder::new();
109
4
        builder.parse_env(env);
110
4
        builder
111
4
    }
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
4
    pub fn parse_env<'a, E>(&mut self, env: E) -> &mut Self
150
4
    where
151
4
        E: Into<Env<'a>>,
152
    {
153
4
        let env = env.into();
154
155
4
        if let Some(s) = env.get_filter() {
156
0
            self.parse_filters(&s);
157
4
        }
158
159
4
        if let Some(s) = env.get_write_style() {
160
0
            self.parse_write_style(&s);
161
4
        }
162
163
4
        self
164
4
    }
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
4
    pub fn from_default_env() -> Self {
185
4
        Self::from_env(Env::default())
186
4
    }
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
0
    pub fn parse_default_env(&mut self) -> &mut Self {
211
0
        self.parse_env(Env::default())
212
0
    }
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
0
    pub fn format<F>(&mut self, format: F) -> &mut Self
244
0
    where
245
0
        F: Fn(&mut Formatter, &Record<'_>) -> io::Result<()> + Sync + Send + 'static,
246
    {
247
0
        self.format.custom_format = Some(Box::new(format));
248
0
        self
249
0
    }
250
251
    /// Use the default format.
252
    ///
253
    /// This method will clear any custom format set on the builder.
254
0
    pub fn default_format(&mut self) -> &mut Self {
255
0
        self.format = Default::default();
256
0
        self
257
0
    }
258
259
    /// Whether or not to write the level in the default format.
260
0
    pub fn format_level(&mut self, write: bool) -> &mut Self {
261
0
        self.format.default_format.level(write);
262
0
        self
263
0
    }
264
265
    /// Whether or not to write the source file path in the default format.
266
0
    pub fn format_file(&mut self, write: bool) -> &mut Self {
267
0
        self.format.default_format.file(write);
268
0
        self
269
0
    }
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
0
    pub fn format_line_number(&mut self, write: bool) -> &mut Self {
275
0
        self.format.default_format.line_number(write);
276
0
        self
277
0
    }
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
0
    pub fn format_source_path(&mut self, write: bool) -> &mut Self {
284
0
        self.format_file(write).format_line_number(write);
285
0
        self
286
0
    }
287
288
    /// Whether or not to write the module path in the default format.
289
0
    pub fn format_module_path(&mut self, write: bool) -> &mut Self {
290
0
        self.format.default_format.module_path(write);
291
0
        self
292
0
    }
293
294
    /// Whether or not to write the target in the default format.
295
0
    pub fn format_target(&mut self, write: bool) -> &mut Self {
296
0
        self.format.default_format.target(write);
297
0
        self
298
0
    }
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
0
    pub fn format_indent(&mut self, indent: Option<usize>) -> &mut Self {
303
0
        self.format.default_format.indent(indent);
304
0
        self
305
0
    }
306
307
    /// Configures if timestamp should be included and in what precision.
308
4
    pub fn format_timestamp(&mut self, timestamp: Option<fmt::TimestampPrecision>) -> &mut Self {
309
4
        self.format.default_format.timestamp(timestamp);
310
4
        self
311
4
    }
312
313
    /// Configures the timestamp to use second precision.
314
0
    pub fn format_timestamp_secs(&mut self) -> &mut Self {
315
0
        self.format_timestamp(Some(fmt::TimestampPrecision::Seconds))
316
0
    }
317
318
    /// Configures the timestamp to use millisecond precision.
319
0
    pub fn format_timestamp_millis(&mut self) -> &mut Self {
320
0
        self.format_timestamp(Some(fmt::TimestampPrecision::Millis))
321
0
    }
322
323
    /// Configures the timestamp to use microsecond precision.
324
0
    pub fn format_timestamp_micros(&mut self) -> &mut Self {
325
0
        self.format_timestamp(Some(fmt::TimestampPrecision::Micros))
326
0
    }
327
328
    /// Configures the timestamp to use nanosecond precision.
329
4
    pub fn format_timestamp_nanos(&mut self) -> &mut Self {
330
4
        self.format_timestamp(Some(fmt::TimestampPrecision::Nanos))
331
4
    }
332
333
    /// Configures the end of line suffix.
334
0
    pub fn format_suffix(&mut self, suffix: &'static str) -> &mut Self {
335
0
        self.format.default_format.suffix(suffix);
336
0
        self
337
0
    }
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
0
    pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self {
373
0
        self.filter.filter_module(module, level);
374
0
        self
375
0
    }
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
0
    pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self {
392
0
        self.filter.filter_level(level);
393
0
        self
394
0
    }
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
0
    pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self {
414
0
        self.filter.filter(module, level);
415
0
        self
416
0
    }
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
0
    pub fn parse_filters(&mut self, filters: &str) -> &mut Self {
423
0
        self.filter.parse(filters);
424
0
        self
425
0
    }
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
0
    pub fn target(&mut self, target: fmt::Target) -> &mut Self {
446
0
        self.writer.target(target);
447
0
        self
448
0
    }
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
0
    pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self {
467
0
        self.writer.write_style(write_style);
468
0
        self
469
0
    }
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
0
    pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self {
476
0
        self.writer.parse_write_style(write_style);
477
0
        self
478
0
    }
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
0
    pub fn is_test(&mut self, is_test: bool) -> &mut Self {
485
0
        self.writer.is_test(is_test);
486
0
        self
487
0
    }
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
4
    pub fn try_init(&mut self) -> Result<(), SetLoggerError> {
499
4
        let logger = self.build();
500
501
4
        let max_level = logger.filter();
502
4
        let r = log::set_boxed_logger(Box::new(logger));
503
504
4
        if r.is_ok() {
505
4
            log::set_max_level(max_level);
506
4
        }
507
508
4
        r
509
4
    }
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
4
    pub fn init(&mut self) {
521
4
        self.try_init()
522
4
            .expect("Builder::init should not be called after logger initialized");
523
4
    }
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
4
    pub fn build(&mut self) -> Logger {
530
4
        assert!(!self.built, "attempt to re-use consumed builder");
531
4
        self.built = true;
532
533
4
        Logger {
534
4
            writer: self.writer.build(),
535
4
            filter: self.filter.build(),
536
4
            format: self.format.build(),
537
4
        }
538
4
    }
539
}
540
541
impl std::fmt::Debug for Builder {
542
0
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
543
0
        if self.built {
544
0
            f.debug_struct("Logger").field("built", &true).finish()
545
        } else {
546
0
            f.debug_struct("Logger")
547
0
                .field("filter", &self.filter)
548
0
                .field("writer", &self.writer)
549
0
                .finish()
550
        }
551
0
    }
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
573
pub struct Logger {
574
    writer: Writer,
575
    filter: env_filter::Filter,
576
    format: FormatFn,
577
}
578
579
impl 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
0
    pub fn from_env<'a, E>(env: E) -> Self
607
0
    where
608
0
        E: Into<Env<'a>>,
609
    {
610
0
        Builder::from_env(env).build()
611
0
    }
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
0
    pub fn from_default_env() -> Self {
631
0
        Builder::from_default_env().build()
632
0
    }
633
634
    /// Returns the maximum `LevelFilter` that this env logger instance is
635
    /// configured to output.
636
4
    pub fn filter(&self) -> LevelFilter {
637
4
        self.filter.filter()
638
4
    }
639
640
    /// Checks if this record matches the configured filter.
641
0
    pub fn matches(&self, record: &Record<'_>) -> bool {
642
0
        self.filter.matches(record)
643
0
    }
644
}
645
646
impl Log for Logger {
647
0
    fn enabled(&self, metadata: &Metadata<'_>) -> bool {
648
0
        self.filter.enabled(metadata)
649
0
    }
650
651
0
    fn log(&self, record: &Record<'_>) {
652
0
        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
0
            let print = |formatter: &mut Formatter, record: &Record<'_>| {
667
0
                let _ = self
668
0
                    .format
669
0
                    .format(formatter, record)
670
0
                    .and_then(|_| formatter.print(&self.writer));
671
672
                // Always clear the buffer afterwards
673
0
                formatter.clear();
674
0
            };
675
676
0
            let printed = FORMATTER
677
0
                .try_with(|tl_buf| {
678
0
                    if let Ok(mut tl_buf) = tl_buf.try_borrow_mut() {
679
                        // There are no active borrows of the buffer
680
0
                        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
0
                            if formatter.write_style() != self.writer.write_style() {
686
0
                                *formatter = Formatter::new(&self.writer);
687
0
                            }
688
689
0
                            print(formatter, record);
690
0
                        } else {
691
0
                            // We don't have a previously set formatter
692
0
                            let mut formatter = Formatter::new(&self.writer);
693
0
                            print(&mut formatter, record);
694
0
695
0
                            *tl_buf = Some(formatter);
696
0
                        }
697
0
                    } else {
698
0
                        // There's already an active borrow of the buffer (due to re-entrancy)
699
0
                        print(&mut Formatter::new(&self.writer), record);
700
0
                    }
701
0
                })
702
0
                .is_ok();
703
704
0
            if !printed {
705
0
                // The thread-local storage was not available (because its
706
0
                // destructor has already run). Create a new single-use
707
0
                // Formatter on the stack for this call.
708
0
                print(&mut Formatter::new(&self.writer), record);
709
0
            }
710
0
        }
711
0
    }
712
713
0
    fn flush(&self) {}
714
}
715
716
impl std::fmt::Debug for Logger {
717
0
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
718
0
        f.debug_struct("Logger")
719
0
            .field("filter", &self.filter)
720
0
            .finish()
721
0
    }
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)]
735
pub struct Env<'a> {
736
    filter: Var<'a>,
737
    write_style: Var<'a>,
738
}
739
740
impl<'a> Env<'a> {
741
    /// Get a default set of environment variables.
742
0
    pub fn new() -> Self {
743
0
        Self::default()
744
0
    }
745
746
    /// Specify an environment variable to read the filter from.
747
0
    pub fn filter<E>(mut self, filter_env: E) -> Self
748
0
    where
749
0
        E: Into<Cow<'a, str>>,
750
    {
751
0
        self.filter = Var::new(filter_env);
752
753
0
        self
754
0
    }
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
0
    pub fn filter_or<E, V>(mut self, filter_env: E, default: V) -> Self
760
0
    where
761
0
        E: Into<Cow<'a, str>>,
762
0
        V: Into<Cow<'a, str>>,
763
    {
764
0
        self.filter = Var::new_with_default(filter_env, default);
765
766
0
        self
767
0
    }
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
0
    pub fn default_filter_or<V>(mut self, default: V) -> Self
773
0
    where
774
0
        V: Into<Cow<'a, str>>,
775
    {
776
0
        self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default);
777
778
0
        self
779
0
    }
780
781
4
    fn get_filter(&self) -> Option<String> {
782
4
        self.filter.get()
783
4
    }
784
785
    /// Specify an environment variable to read the style from.
786
0
    pub fn write_style<E>(mut self, write_style_env: E) -> Self
787
0
    where
788
0
        E: Into<Cow<'a, str>>,
789
    {
790
0
        self.write_style = Var::new(write_style_env);
791
792
0
        self
793
0
    }
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
0
    pub fn write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self
799
0
    where
800
0
        E: Into<Cow<'a, str>>,
801
0
        V: Into<Cow<'a, str>>,
802
    {
803
0
        self.write_style = Var::new_with_default(write_style_env, default);
804
805
0
        self
806
0
    }
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
0
    pub fn default_write_style_or<V>(mut self, default: V) -> Self
812
0
    where
813
0
        V: Into<Cow<'a, str>>,
814
    {
815
0
        self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default);
816
817
0
        self
818
0
    }
819
820
4
    fn get_write_style(&self) -> Option<String> {
821
4
        self.write_style.get()
822
4
    }
823
}
824
825
impl<'a, T> From<T> for Env<'a>
826
where
827
    T: Into<Cow<'a, str>>,
828
{
829
0
    fn from(filter_env: T) -> Self {
830
0
        Env::default().filter(filter_env.into())
831
0
    }
832
}
833
834
impl Default for Env<'_> {
835
4
    fn default() -> Self {
836
4
        Env {
837
4
            filter: Var::new(DEFAULT_FILTER_ENV),
838
4
            write_style: Var::new(DEFAULT_WRITE_STYLE_ENV),
839
4
        }
840
4
    }
841
}
842
843
#[derive(Debug)]
844
struct Var<'a> {
845
    name: Cow<'a, str>,
846
    default: Option<Cow<'a, str>>,
847
}
848
849
impl<'a> Var<'a> {
850
8
    fn new<E>(name: E) -> Self
851
8
    where
852
8
        E: Into<Cow<'a, str>>,
853
    {
854
8
        Var {
855
8
            name: name.into(),
856
8
            default: None,
857
8
        }
858
8
    }
859
860
0
    fn new_with_default<E, V>(name: E, default: V) -> Self
861
0
    where
862
0
        E: Into<Cow<'a, str>>,
863
0
        V: Into<Cow<'a, str>>,
864
    {
865
0
        Var {
866
0
            name: name.into(),
867
0
            default: Some(default.into()),
868
0
        }
869
0
    }
870
871
8
    fn get(&self) -> Option<String> {
872
8
        env::var(&*self.name)
873
8
            .ok()
874
8
            .or_else(|| self.default.clone().map(|v| v.into_owned()))
875
8
    }
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.
887
0
pub fn try_init() -> Result<(), SetLoggerError> {
888
0
    try_init_from_env(Env::default())
889
0
}
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.
900
0
pub fn init() {
901
0
    try_init().expect("env_logger::init should not be called after logger initialized");
902
0
}
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.
932
0
pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError>
933
0
where
934
0
    E: Into<Env<'a>>,
935
{
936
0
    let mut builder = Builder::from_env(env);
937
938
0
    builder.try_init()
939
0
}
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.
964
0
pub fn init_from_env<'a, E>(env: E)
965
0
where
966
0
    E: Into<Env<'a>>,
967
{
968
0
    try_init_from_env(env)
969
0
        .expect("env_logger::init_from_env should not be called after logger initialized");
970
0
}
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
978
4
pub fn builder() -> Builder {
979
4
    Builder::from_default_env()
980
4
}
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
)]
989
0
pub fn from_env<'a, E>(env: E) -> Builder
990
0
where
991
0
    E: Into<Env<'a>>,
992
{
993
0
    Builder::from_env(env)
994
0
}
995
996
#[cfg(test)]
997
mod 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
}