Coverage Report

Created: 2025-07-23 07:16

/rust/registry/src/index.crates.io-6f17d22bba15001f/env_logger-0.9.3/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
4
// option. This file may not be copied, modified, or distributed
5
// except according to those terms.
6
7
//! A simple logger that can be configured via environment variables, for use
8
//! with the logging facade exposed by the [`log` crate][log-crate-url].
9
//!
10
//! Despite having "env" in its name, **`env_logger`** can also be configured by
11
//! other means besides environment variables. See [the examples][gh-repo-examples]
12
//! in the source repository for more approaches.
13
//!
14
//! By default, `env_logger` writes logs to `stderr`, but can be configured to
15
//! instead write them to `stdout`.
16
//!
17
//! ## Example
18
//!
19
//! ```
20
//! use log::{debug, error, log_enabled, info, Level};
21
//!
22
//! env_logger::init();
23
//!
24
//! debug!("this is a debug {}", "message");
25
//! error!("this is printed by default");
26
//!
27
//! if log_enabled!(Level::Info) {
28
//!     let x = 3 * 4; // expensive computation
29
//!     info!("the answer was: {}", x);
30
//! }
31
//! ```
32
//!
33
//! Assumes the binary is `main`:
34
//!
35
//! ```{.bash}
36
//! $ RUST_LOG=error ./main
37
//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
38
//! ```
39
//!
40
//! ```{.bash}
41
//! $ RUST_LOG=info ./main
42
//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
43
//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
44
//! ```
45
//!
46
//! ```{.bash}
47
//! $ RUST_LOG=debug ./main
48
//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message
49
//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
50
//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
51
//! ```
52
//!
53
//! You can also set the log level on a per module basis:
54
//!
55
//! ```{.bash}
56
//! $ RUST_LOG=main=info ./main
57
//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
58
//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
59
//! ```
60
//!
61
//! And enable all logging:
62
//!
63
//! ```{.bash}
64
//! $ RUST_LOG=main ./main
65
//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message
66
//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
67
//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
68
//! ```
69
//!
70
//! If the binary name contains hyphens, you will need to replace
71
//! them with underscores:
72
//!
73
//! ```{.bash}
74
//! $ RUST_LOG=my_app ./my-app
75
//! [2017-11-09T02:12:24Z DEBUG my_app] this is a debug message
76
//! [2017-11-09T02:12:24Z ERROR my_app] this is printed by default
77
//! [2017-11-09T02:12:24Z INFO my_app] the answer was: 12
78
//! ```
79
//!
80
//! This is because Rust modules and crates cannot contain hyphens
81
//! in their name, although `cargo` continues to accept them.
82
//!
83
//! See the documentation for the [`log` crate][log-crate-url] for more
84
//! information about its API.
85
//!
86
//! ## Enabling logging
87
//!
88
//! Log levels are controlled on a per-module basis, and **by default all
89
//! logging is disabled except for the `error` level**.
90
//!
91
//! Logging is controlled via the **`RUST_LOG`** environment variable. The
92
//! value of this environment variable is a comma-separated list of *logging
93
//! directives*. A logging directive is of the form:
94
//!
95
//! ```text
96
//! example::log::target=level
97
//! ```
98
//!
99
//! The log target is typically equal to the path of the module the message
100
//! in question originated from, though it can be overriden.
101
//!
102
//! The path is rooted in the name of the crate it was compiled for, so if
103
//! your program is in a file called, for example, `hello.rs`, the path would
104
//! simply be be `hello`.
105
//!
106
//! Furthermore, the log can be filtered using prefix-search based on the
107
//! specified log target. A value of, for example, `RUST_LOG=example`, would
108
//! match all of the messages with targets:
109
//!
110
//! * `example`
111
//! * `example::test`
112
//! * `example::test::module::submodule`
113
//! * `examples::and_more_examples`
114
//!
115
//! When providing the crate name or a module path, explicitly specifying the
116
//! log level is optional. If omitted, all logging for the item will be
117
//! enabled.
118
//!
119
//! The names of the log levels that may be specified correspond to the
120
//! variations of the [`log::Level`][level-enum] enum from the `log`
121
//! crate. They are:
122
//!
123
//! * `error`
124
//! * `warn`
125
//! * `info`
126
//! * `debug`
127
//! * `trace`
128
//!
129
//! There is also a pseudo logging level, `off`, which may be specified to
130
//! disable all logging for a given module or for the entire application. As
131
//! with the logging levels, the letter case is not significant[^fn-off].
132
//!
133
//! [^fn-off]: Similar to the universe of log level names, the `off` pseudo
134
//!    log level feature is also provided by the underlying `log` crate.
135
//!
136
//! The letter case is not significant for the logging level names; e.g.,
137
//! `debug`, `DEBUG`, and `dEbuG` all represent the same logging level. For
138
//! consistency, our convention is to use the lower case names. Where our docs
139
//! do use other forms, they do so in the context of specific examples, so you
140
//! won't be surprised if you see similar usage in the wild.
141
//!
142
//! As the log level for a module is optional, the module to enable logging for
143
//! is also optional. **If only a level is provided, then the global log
144
//! level for all modules is set to this value.**
145
//!
146
//! Some examples of valid values of `RUST_LOG` are:
147
//!
148
//! * `hello` turns on all logging for the 'hello' module
149
//! * `trace` turns on all logging for the application, regardless of its name
150
//! * `TRACE` turns on all logging for the application, regardless of its name (same as previous)
151
//! * `info` turns on all info logging
152
//! * `INFO` turns on all info logging (same as previous)
153
//! * `hello=debug` turns on debug logging for 'hello'
154
//! * `hello=DEBUG` turns on debug logging for 'hello' (same as previous)
155
//! * `hello,std::option` turns on hello, and std's option logging
156
//! * `error,hello=warn` turn on global error logging and also warn for hello
157
//! * `error,hello=off`  turn on global error logging, but turn off logging for hello
158
//! * `off` turns off all logging for the application
159
//! * `OFF` turns off all logging for the application (same as previous)
160
//!
161
//! ## Filtering results
162
//!
163
//! A `RUST_LOG` directive may include a regex filter. The syntax is to append `/`
164
//! followed by a regex. Each message is checked against the regex, and is only
165
//! logged if it matches. Note that the matching is done after formatting the
166
//! log string but before adding any logging meta-data. There is a single filter
167
//! for all modules.
168
//!
169
//! Some examples:
170
//!
171
//! * `hello/foo` turns on all logging for the 'hello' module where the log
172
//!   message includes 'foo'.
173
//! * `info/f.o` turns on all info logging where the log message includes 'foo',
174
//!   'f1o', 'fao', etc.
175
//! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the log
176
//!   message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc.
177
//! * `error,hello=warn/[0-9]scopes` turn on global error logging and also
178
//!   warn for hello. In both cases the log message must include a single digit
179
//!   number followed by 'scopes'.
180
//!
181
//! ## Capturing logs in tests
182
//!
183
//! Records logged during `cargo test` will not be captured by the test harness by default.
184
//! The [`Builder::is_test`] method can be used in unit tests to ensure logs will be captured:
185
//!
186
//! ```
187
//! # #[macro_use] extern crate log;
188
//! #[cfg(test)]
189
//! mod tests {
190
//!     fn init() {
191
//!         let _ = env_logger::builder().is_test(true).try_init();
192
//!     }
193
//!
194
//!     #[test]
195
//!     fn it_works() {
196
//!         init();
197
//!
198
//!         info!("This record will be captured by `cargo test`");
199
//!
200
//!         assert_eq!(2, 1 + 1);
201
//!     }
202
//! }
203
//! ```
204
//!
205
//! Enabling test capturing comes at the expense of color and other style support
206
//! and may have performance implications.
207
//!
208
//! ## Disabling colors
209
//!
210
//! Colors and other styles can be configured with the `RUST_LOG_STYLE`
211
//! environment variable. It accepts the following values:
212
//!
213
//! * `auto` (default) will attempt to print style characters, but don't force the issue.
214
//! If the console isn't available on Windows, or if TERM=dumb, for example, then don't print colors.
215
//! * `always` will always print style characters even if they aren't supported by the terminal.
216
//! This includes emitting ANSI colors on Windows if the console API is unavailable.
217
//! * `never` will never print style characters.
218
//!
219
//! ## Tweaking the default format
220
//!
221
//! Parts of the default format can be excluded from the log output using the [`Builder`].
222
//! The following example excludes the timestamp from the log output:
223
//!
224
//! ```
225
//! env_logger::builder()
226
//!     .format_timestamp(None)
227
//!     .init();
228
//! ```
229
//!
230
//! ### Stability of the default format
231
//!
232
//! The default format won't optimise for long-term stability, and explicitly makes no
233
//! guarantees about the stability of its output across major, minor or patch version
234
//! bumps during `0.x`.
235
//!
236
//! If you want to capture or interpret the output of `env_logger` programmatically
237
//! then you should use a custom format.
238
//!
239
//! ### Using a custom format
240
//!
241
//! Custom formats can be provided as closures to the [`Builder`].
242
//! These closures take a [`Formatter`] and `log::Record` as arguments:
243
//!
244
//! ```
245
//! use std::io::Write;
246
//!
247
//! env_logger::builder()
248
//!     .format(|buf, record| {
249
//!         writeln!(buf, "{}: {}", record.level(), record.args())
250
//!     })
251
//!     .init();
252
//! ```
253
//!
254
//! See the [`fmt`] module for more details about custom formats.
255
//!
256
//! ## Specifying defaults for environment variables
257
//!
258
//! `env_logger` can read configuration from environment variables.
259
//! If these variables aren't present, the default value to use can be tweaked with the [`Env`] type.
260
//! The following example defaults to log `warn` and above if the `RUST_LOG` environment variable
261
//! isn't set:
262
//!
263
//! ```
264
//! use env_logger::Env;
265
//!
266
//! env_logger::Builder::from_env(Env::default().default_filter_or("warn")).init();
267
//! ```
268
//!
269
//! [gh-repo-examples]: https://github.com/env-logger-rs/env_logger/tree/main/examples
270
//! [level-enum]: https://docs.rs/log/latest/log/enum.Level.html
271
//! [log-crate-url]: https://docs.rs/log/
272
//! [`Builder`]: struct.Builder.html
273
//! [`Builder::is_test`]: struct.Builder.html#method.is_test
274
//! [`Env`]: struct.Env.html
275
//! [`fmt`]: fmt/index.html
276
277
#![doc(
278
    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
279
    html_favicon_url = "https://www.rust-lang.org/static/images/favicon.ico"
280
)]
281
// When compiled for the rustc compiler itself we want to make sure that this is
282
// an unstable crate
283
#![cfg_attr(rustbuild, feature(staged_api, rustc_private))]
284
#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))]
285
#![deny(missing_debug_implementations, missing_docs)]
286
287
use std::{borrow::Cow, cell::RefCell, env, io};
288
289
use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};
290
291
pub mod filter;
292
pub mod fmt;
293
294
pub use self::fmt::glob::*;
295
296
use self::filter::Filter;
297
use self::fmt::writer::{self, Writer};
298
use self::fmt::{FormatFn, Formatter};
299
300
/// The default name for the environment variable to read filters from.
301
pub const DEFAULT_FILTER_ENV: &str = "RUST_LOG";
302
303
/// The default name for the environment variable to read style preferences from.
304
pub const DEFAULT_WRITE_STYLE_ENV: &str = "RUST_LOG_STYLE";
305
306
/// Set of environment variables to configure from.
307
///
308
/// # Default environment variables
309
///
310
/// By default, the `Env` will read the following environment variables:
311
///
312
/// - `RUST_LOG`: the level filter
313
/// - `RUST_LOG_STYLE`: whether or not to print styles with records.
314
///
315
/// These sources can be configured using the builder methods on `Env`.
316
#[derive(Debug)]
317
pub struct Env<'a> {
318
    filter: Var<'a>,
319
    write_style: Var<'a>,
320
}
321
322
#[derive(Debug)]
323
struct Var<'a> {
324
    name: Cow<'a, str>,
325
    default: Option<Cow<'a, str>>,
326
}
327
328
/// The env logger.
329
///
330
/// This struct implements the `Log` trait from the [`log` crate][log-crate-url],
331
/// which allows it to act as a logger.
332
///
333
/// The [`init()`], [`try_init()`], [`Builder::init()`] and [`Builder::try_init()`]
334
/// methods will each construct a `Logger` and immediately initialize it as the
335
/// default global logger.
336
///
337
/// If you'd instead need access to the constructed `Logger`, you can use
338
/// the associated [`Builder`] and install it with the
339
/// [`log` crate][log-crate-url] directly.
340
///
341
/// [log-crate-url]: https://docs.rs/log/
342
/// [`init()`]: fn.init.html
343
/// [`try_init()`]: fn.try_init.html
344
/// [`Builder::init()`]: struct.Builder.html#method.init
345
/// [`Builder::try_init()`]: struct.Builder.html#method.try_init
346
/// [`Builder`]: struct.Builder.html
347
pub struct Logger {
348
    writer: Writer,
349
    filter: Filter,
350
    format: FormatFn,
351
}
352
353
/// `Builder` acts as builder for initializing a `Logger`.
354
///
355
/// It can be used to customize the log format, change the environment variable used
356
/// to provide the logging directives and also set the default log level filter.
357
///
358
/// # Examples
359
///
360
/// ```
361
/// # #[macro_use] extern crate log;
362
/// # use std::io::Write;
363
/// use env_logger::Builder;
364
/// use log::LevelFilter;
365
///
366
/// let mut builder = Builder::from_default_env();
367
///
368
/// builder
369
///     .format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args()))
370
///     .filter(None, LevelFilter::Info)
371
///     .init();
372
///
373
/// error!("error message");
374
/// info!("info message");
375
/// ```
376
#[derive(Default)]
377
pub struct Builder {
378
    filter: filter::Builder,
379
    writer: writer::Builder,
380
    format: fmt::Builder,
381
    built: bool,
382
}
383
384
impl Builder {
385
    /// Initializes the log builder with defaults.
386
    ///
387
    /// **NOTE:** This method won't read from any environment variables.
388
    /// Use the [`filter`] and [`write_style`] methods to configure the builder
389
    /// or use [`from_env`] or [`from_default_env`] instead.
390
    ///
391
    /// # Examples
392
    ///
393
    /// Create a new builder and configure filters and style:
394
    ///
395
    /// ```
396
    /// use log::LevelFilter;
397
    /// use env_logger::{Builder, WriteStyle};
398
    ///
399
    /// let mut builder = Builder::new();
400
    ///
401
    /// builder
402
    ///     .filter(None, LevelFilter::Info)
403
    ///     .write_style(WriteStyle::Always)
404
    ///     .init();
405
    /// ```
406
    ///
407
    /// [`filter`]: #method.filter
408
    /// [`write_style`]: #method.write_style
409
    /// [`from_env`]: #method.from_env
410
    /// [`from_default_env`]: #method.from_default_env
411
111k
    pub fn new() -> Builder {
412
111k
        Default::default()
413
111k
    }
414
415
    /// Initializes the log builder from the environment.
416
    ///
417
    /// The variables used to read configuration from can be tweaked before
418
    /// passing in.
419
    ///
420
    /// # Examples
421
    ///
422
    /// Initialise a logger reading the log filter from an environment variable
423
    /// called `MY_LOG`:
424
    ///
425
    /// ```
426
    /// use env_logger::Builder;
427
    ///
428
    /// let mut builder = Builder::from_env("MY_LOG");
429
    /// builder.init();
430
    /// ```
431
    ///
432
    /// Initialise a logger using the `MY_LOG` variable for filtering and
433
    /// `MY_LOG_STYLE` for whether or not to write styles:
434
    ///
435
    /// ```
436
    /// use env_logger::{Builder, Env};
437
    ///
438
    /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
439
    ///
440
    /// let mut builder = Builder::from_env(env);
441
    /// builder.init();
442
    /// ```
443
111k
    pub fn from_env<'a, E>(env: E) -> Self
444
111k
    where
445
111k
        E: Into<Env<'a>>,
446
111k
    {
447
111k
        let mut builder = Builder::new();
448
111k
        builder.parse_env(env);
449
111k
        builder
450
111k
    }
451
452
    /// Applies the configuration from the environment.
453
    ///
454
    /// This function allows a builder to be configured with default parameters,
455
    /// to be then overridden by the environment.
456
    ///
457
    /// # Examples
458
    ///
459
    /// Initialise a logger with filter level `Off`, then override the log
460
    /// filter from an environment variable called `MY_LOG`:
461
    ///
462
    /// ```
463
    /// use log::LevelFilter;
464
    /// use env_logger::Builder;
465
    ///
466
    /// let mut builder = Builder::new();
467
    ///
468
    /// builder.filter_level(LevelFilter::Off);
469
    /// builder.parse_env("MY_LOG");
470
    /// builder.init();
471
    /// ```
472
    ///
473
    /// Initialise a logger with filter level `Off`, then use the `MY_LOG`
474
    /// variable to override filtering and `MY_LOG_STYLE` to override  whether
475
    /// or not to write styles:
476
    ///
477
    /// ```
478
    /// use log::LevelFilter;
479
    /// use env_logger::{Builder, Env};
480
    ///
481
    /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
482
    ///
483
    /// let mut builder = Builder::new();
484
    /// builder.filter_level(LevelFilter::Off);
485
    /// builder.parse_env(env);
486
    /// builder.init();
487
    /// ```
488
111k
    pub fn parse_env<'a, E>(&mut self, env: E) -> &mut Self
489
111k
    where
490
111k
        E: Into<Env<'a>>,
491
111k
    {
492
111k
        let env = env.into();
493
494
111k
        if let Some(s) = env.get_filter() {
495
0
            self.parse_filters(&s);
496
111k
        }
497
498
111k
        if let Some(s) = env.get_write_style() {
499
0
            self.parse_write_style(&s);
500
111k
        }
501
502
111k
        self
503
111k
    }
504
505
    /// Initializes the log builder from the environment using default variable names.
506
    ///
507
    /// This method is a convenient way to call `from_env(Env::default())` without
508
    /// having to use the `Env` type explicitly. The builder will use the
509
    /// [default environment variables].
510
    ///
511
    /// # Examples
512
    ///
513
    /// Initialise a logger using the default environment variables:
514
    ///
515
    /// ```
516
    /// use env_logger::Builder;
517
    ///
518
    /// let mut builder = Builder::from_default_env();
519
    /// builder.init();
520
    /// ```
521
    ///
522
    /// [default environment variables]: struct.Env.html#default-environment-variables
523
0
    pub fn from_default_env() -> Self {
524
0
        Self::from_env(Env::default())
525
0
    }
526
527
    /// Applies the configuration from the environment using default variable names.
528
    ///
529
    /// This method is a convenient way to call `parse_env(Env::default())` without
530
    /// having to use the `Env` type explicitly. The builder will use the
531
    /// [default environment variables].
532
    ///
533
    /// # Examples
534
    ///
535
    /// Initialise a logger with filter level `Off`, then configure it using the
536
    /// default environment variables:
537
    ///
538
    /// ```
539
    /// use log::LevelFilter;
540
    /// use env_logger::Builder;
541
    ///
542
    /// let mut builder = Builder::new();
543
    /// builder.filter_level(LevelFilter::Off);
544
    /// builder.parse_default_env();
545
    /// builder.init();
546
    /// ```
547
    ///
548
    /// [default environment variables]: struct.Env.html#default-environment-variables
549
0
    pub fn parse_default_env(&mut self) -> &mut Self {
550
0
        self.parse_env(Env::default())
551
0
    }
552
553
    /// Sets the format function for formatting the log output.
554
    ///
555
    /// This function is called on each record logged and should format the
556
    /// log record and output it to the given [`Formatter`].
557
    ///
558
    /// The format function is expected to output the string directly to the
559
    /// `Formatter` so that implementations can use the [`std::fmt`] macros
560
    /// to format and output without intermediate heap allocations. The default
561
    /// `env_logger` formatter takes advantage of this.
562
    ///
563
    /// # Examples
564
    ///
565
    /// Use a custom format to write only the log message:
566
    ///
567
    /// ```
568
    /// use std::io::Write;
569
    /// use env_logger::Builder;
570
    ///
571
    /// let mut builder = Builder::new();
572
    ///
573
    /// builder.format(|buf, record| writeln!(buf, "{}", record.args()));
574
    /// ```
575
    ///
576
    /// [`Formatter`]: fmt/struct.Formatter.html
577
    /// [`String`]: https://doc.rust-lang.org/stable/std/string/struct.String.html
578
    /// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html
579
0
    pub fn format<F: 'static>(&mut self, format: F) -> &mut Self
580
0
    where
581
0
        F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send,
582
0
    {
583
0
        self.format.custom_format = Some(Box::new(format));
584
0
        self
585
0
    }
586
587
    /// Use the default format.
588
    ///
589
    /// This method will clear any custom format set on the builder.
590
0
    pub fn default_format(&mut self) -> &mut Self {
591
0
        self.format = Default::default();
592
0
        self
593
0
    }
594
595
    /// Whether or not to write the level in the default format.
596
0
    pub fn format_level(&mut self, write: bool) -> &mut Self {
597
0
        self.format.format_level = write;
598
0
        self
599
0
    }
600
601
    /// Whether or not to write the module path in the default format.
602
0
    pub fn format_module_path(&mut self, write: bool) -> &mut Self {
603
0
        self.format.format_module_path = write;
604
0
        self
605
0
    }
606
607
    /// Whether or not to write the target in the default format.
608
0
    pub fn format_target(&mut self, write: bool) -> &mut Self {
609
0
        self.format.format_target = write;
610
0
        self
611
0
    }
612
613
    /// Configures the amount of spaces to use to indent multiline log records.
614
    /// A value of `None` disables any kind of indentation.
615
0
    pub fn format_indent(&mut self, indent: Option<usize>) -> &mut Self {
616
0
        self.format.format_indent = indent;
617
0
        self
618
0
    }
619
620
    /// Configures if timestamp should be included and in what precision.
621
0
    pub fn format_timestamp(&mut self, timestamp: Option<fmt::TimestampPrecision>) -> &mut Self {
622
0
        self.format.format_timestamp = timestamp;
623
0
        self
624
0
    }
625
626
    /// Configures the timestamp to use second precision.
627
0
    pub fn format_timestamp_secs(&mut self) -> &mut Self {
628
0
        self.format_timestamp(Some(fmt::TimestampPrecision::Seconds))
629
0
    }
630
631
    /// Configures the timestamp to use millisecond precision.
632
0
    pub fn format_timestamp_millis(&mut self) -> &mut Self {
633
0
        self.format_timestamp(Some(fmt::TimestampPrecision::Millis))
634
0
    }
635
636
    /// Configures the timestamp to use microsecond precision.
637
0
    pub fn format_timestamp_micros(&mut self) -> &mut Self {
638
0
        self.format_timestamp(Some(fmt::TimestampPrecision::Micros))
639
0
    }
640
641
    /// Configures the timestamp to use nanosecond precision.
642
0
    pub fn format_timestamp_nanos(&mut self) -> &mut Self {
643
0
        self.format_timestamp(Some(fmt::TimestampPrecision::Nanos))
644
0
    }
645
646
    /// Configures the end of line suffix.
647
0
    pub fn format_suffix(&mut self, suffix: &'static str) -> &mut Self {
648
0
        self.format.format_suffix = suffix;
649
0
        self
650
0
    }
651
652
    /// Adds a directive to the filter for a specific module.
653
    ///
654
    /// # Examples
655
    ///
656
    /// Only include messages for info and above for logs in `path::to::module`:
657
    ///
658
    /// ```
659
    /// use env_logger::Builder;
660
    /// use log::LevelFilter;
661
    ///
662
    /// let mut builder = Builder::new();
663
    ///
664
    /// builder.filter_module("path::to::module", LevelFilter::Info);
665
    /// ```
666
0
    pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self {
667
0
        self.filter.filter_module(module, level);
668
0
        self
669
0
    }
670
671
    /// Adds a directive to the filter for all modules.
672
    ///
673
    /// # Examples
674
    ///
675
    /// Only include messages for info and above for logs globally:
676
    ///
677
    /// ```
678
    /// use env_logger::Builder;
679
    /// use log::LevelFilter;
680
    ///
681
    /// let mut builder = Builder::new();
682
    ///
683
    /// builder.filter_level(LevelFilter::Info);
684
    /// ```
685
0
    pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self {
686
0
        self.filter.filter_level(level);
687
0
        self
688
0
    }
689
690
    /// Adds filters to the logger.
691
    ///
692
    /// The given module (if any) will log at most the specified level provided.
693
    /// If no module is provided then the filter will apply to all log messages.
694
    ///
695
    /// # Examples
696
    ///
697
    /// Only include messages for info and above for logs in `path::to::module`:
698
    ///
699
    /// ```
700
    /// use env_logger::Builder;
701
    /// use log::LevelFilter;
702
    ///
703
    /// let mut builder = Builder::new();
704
    ///
705
    /// builder.filter(Some("path::to::module"), LevelFilter::Info);
706
    /// ```
707
0
    pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self {
708
0
        self.filter.filter(module, level);
709
0
        self
710
0
    }
711
712
    /// Parses the directives string in the same form as the `RUST_LOG`
713
    /// environment variable.
714
    ///
715
    /// See the module documentation for more details.
716
0
    pub fn parse_filters(&mut self, filters: &str) -> &mut Self {
717
0
        self.filter.parse(filters);
718
0
        self
719
0
    }
720
721
    /// Sets the target for the log output.
722
    ///
723
    /// Env logger can log to either stdout, stderr or a custom pipe. The default is stderr.
724
    ///
725
    /// The custom pipe can be used to send the log messages to a custom sink (for example a file).
726
    /// Do note that direct writes to a file can become a bottleneck due to IO operation times.
727
    ///
728
    /// # Examples
729
    ///
730
    /// Write log message to `stdout`:
731
    ///
732
    /// ```
733
    /// use env_logger::{Builder, Target};
734
    ///
735
    /// let mut builder = Builder::new();
736
    ///
737
    /// builder.target(Target::Stdout);
738
    /// ```
739
0
    pub fn target(&mut self, target: fmt::Target) -> &mut Self {
740
0
        self.writer.target(target);
741
0
        self
742
0
    }
743
744
    /// Sets whether or not styles will be written.
745
    ///
746
    /// This can be useful in environments that don't support control characters
747
    /// for setting colors.
748
    ///
749
    /// # Examples
750
    ///
751
    /// Never attempt to write styles:
752
    ///
753
    /// ```
754
    /// use env_logger::{Builder, WriteStyle};
755
    ///
756
    /// let mut builder = Builder::new();
757
    ///
758
    /// builder.write_style(WriteStyle::Never);
759
    /// ```
760
0
    pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self {
761
0
        self.writer.write_style(write_style);
762
0
        self
763
0
    }
764
765
    /// Parses whether or not to write styles in the same form as the `RUST_LOG_STYLE`
766
    /// environment variable.
767
    ///
768
    /// See the module documentation for more details.
769
0
    pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self {
770
0
        self.writer.parse_write_style(write_style);
771
0
        self
772
0
    }
773
774
    /// Sets whether or not the logger will be used in unit tests.
775
    ///
776
    /// If `is_test` is `true` then the logger will allow the testing framework to
777
    /// capture log records rather than printing them to the terminal directly.
778
0
    pub fn is_test(&mut self, is_test: bool) -> &mut Self {
779
0
        self.writer.is_test(is_test);
780
0
        self
781
0
    }
782
783
    /// Initializes the global logger with the built env logger.
784
    ///
785
    /// This should be called early in the execution of a Rust program. Any log
786
    /// events that occur before initialization will be ignored.
787
    ///
788
    /// # Errors
789
    ///
790
    /// This function will fail if it is called more than once, or if another
791
    /// library has already initialized a global logger.
792
111k
    pub fn try_init(&mut self) -> Result<(), SetLoggerError> {
793
111k
        let logger = self.build();
794
111k
795
111k
        let max_level = logger.filter();
796
111k
        let r = log::set_boxed_logger(Box::new(logger));
797
111k
798
111k
        if r.is_ok() {
799
8
            log::set_max_level(max_level);
800
111k
        }
801
802
111k
        r
803
111k
    }
804
805
    /// Initializes the global logger with the built env logger.
806
    ///
807
    /// This should be called early in the execution of a Rust program. Any log
808
    /// events that occur before initialization will be ignored.
809
    ///
810
    /// # Panics
811
    ///
812
    /// This function will panic if it is called more than once, or if another
813
    /// library has already initialized a global logger.
814
0
    pub fn init(&mut self) {
815
0
        self.try_init()
816
0
            .expect("Builder::init should not be called after logger initialized");
817
0
    }
818
819
    /// Build an env logger.
820
    ///
821
    /// The returned logger implements the `Log` trait and can be installed manually
822
    /// or nested within another logger.
823
111k
    pub fn build(&mut self) -> Logger {
824
111k
        assert!(!self.built, "attempt to re-use consumed builder");
825
111k
        self.built = true;
826
111k
827
111k
        Logger {
828
111k
            writer: self.writer.build(),
829
111k
            filter: self.filter.build(),
830
111k
            format: self.format.build(),
831
111k
        }
832
111k
    }
833
}
834
835
impl Logger {
836
    /// Creates the logger from the environment.
837
    ///
838
    /// The variables used to read configuration from can be tweaked before
839
    /// passing in.
840
    ///
841
    /// # Examples
842
    ///
843
    /// Create a logger reading the log filter from an environment variable
844
    /// called `MY_LOG`:
845
    ///
846
    /// ```
847
    /// use env_logger::Logger;
848
    ///
849
    /// let logger = Logger::from_env("MY_LOG");
850
    /// ```
851
    ///
852
    /// Create a logger using the `MY_LOG` variable for filtering and
853
    /// `MY_LOG_STYLE` for whether or not to write styles:
854
    ///
855
    /// ```
856
    /// use env_logger::{Logger, Env};
857
    ///
858
    /// let env = Env::new().filter_or("MY_LOG", "info").write_style_or("MY_LOG_STYLE", "always");
859
    ///
860
    /// let logger = Logger::from_env(env);
861
    /// ```
862
0
    pub fn from_env<'a, E>(env: E) -> Self
863
0
    where
864
0
        E: Into<Env<'a>>,
865
0
    {
866
0
        Builder::from_env(env).build()
867
0
    }
868
869
    /// Creates the logger from the environment using default variable names.
870
    ///
871
    /// This method is a convenient way to call `from_env(Env::default())` without
872
    /// having to use the `Env` type explicitly. The logger will use the
873
    /// [default environment variables].
874
    ///
875
    /// # Examples
876
    ///
877
    /// Creates a logger using the default environment variables:
878
    ///
879
    /// ```
880
    /// use env_logger::Logger;
881
    ///
882
    /// let logger = Logger::from_default_env();
883
    /// ```
884
    ///
885
    /// [default environment variables]: struct.Env.html#default-environment-variables
886
0
    pub fn from_default_env() -> Self {
887
0
        Builder::from_default_env().build()
888
0
    }
889
890
    /// Returns the maximum `LevelFilter` that this env logger instance is
891
    /// configured to output.
892
111k
    pub fn filter(&self) -> LevelFilter {
893
111k
        self.filter.filter()
894
111k
    }
895
896
    /// Checks if this record matches the configured filter.
897
0
    pub fn matches(&self, record: &Record) -> bool {
898
0
        self.filter.matches(record)
899
0
    }
900
}
901
902
impl Log for Logger {
903
0
    fn enabled(&self, metadata: &Metadata) -> bool {
904
0
        self.filter.enabled(metadata)
905
0
    }
906
907
0
    fn log(&self, record: &Record) {
908
0
        if self.matches(record) {
909
            // Log records are written to a thread-local buffer before being printed
910
            // to the terminal. We clear these buffers afterwards, but they aren't shrinked
911
            // so will always at least have capacity for the largest log record formatted
912
            // on that thread.
913
            //
914
            // If multiple `Logger`s are used by the same threads then the thread-local
915
            // formatter might have different color support. If this is the case the
916
            // formatter and its buffer are discarded and recreated.
917
918
            thread_local! {
919
                static FORMATTER: RefCell<Option<Formatter>> = RefCell::new(None);
920
            }
921
922
0
            let print = |formatter: &mut Formatter, record: &Record| {
923
0
                let _ =
924
0
                    (self.format)(formatter, record).and_then(|_| formatter.print(&self.writer));
925
0
926
0
                // Always clear the buffer afterwards
927
0
                formatter.clear();
928
0
            };
929
930
0
            let printed = FORMATTER
931
0
                .try_with(|tl_buf| {
932
0
                    match tl_buf.try_borrow_mut() {
933
                        // There are no active borrows of the buffer
934
0
                        Ok(mut tl_buf) => match *tl_buf {
935
                            // We have a previously set formatter
936
0
                            Some(ref mut formatter) => {
937
0
                                // Check the buffer style. If it's different from the logger's
938
0
                                // style then drop the buffer and recreate it.
939
0
                                if formatter.write_style() != self.writer.write_style() {
940
0
                                    *formatter = Formatter::new(&self.writer);
941
0
                                }
942
943
0
                                print(formatter, record);
944
                            }
945
                            // We don't have a previously set formatter
946
0
                            None => {
947
0
                                let mut formatter = Formatter::new(&self.writer);
948
0
                                print(&mut formatter, record);
949
0
950
0
                                *tl_buf = Some(formatter);
951
0
                            }
952
                        },
953
                        // There's already an active borrow of the buffer (due to re-entrancy)
954
0
                        Err(_) => {
955
0
                            print(&mut Formatter::new(&self.writer), record);
956
0
                        }
957
                    }
958
0
                })
959
0
                .is_ok();
960
0
961
0
            if !printed {
962
0
                // The thread-local storage was not available (because its
963
0
                // destructor has already run). Create a new single-use
964
0
                // Formatter on the stack for this call.
965
0
                print(&mut Formatter::new(&self.writer), record);
966
0
            }
967
0
        }
968
0
    }
969
970
0
    fn flush(&self) {}
971
}
972
973
impl<'a> Env<'a> {
974
    /// Get a default set of environment variables.
975
0
    pub fn new() -> Self {
976
0
        Self::default()
977
0
    }
978
979
    /// Specify an environment variable to read the filter from.
980
0
    pub fn filter<E>(mut self, filter_env: E) -> Self
981
0
    where
982
0
        E: Into<Cow<'a, str>>,
983
0
    {
984
0
        self.filter = Var::new(filter_env);
985
0
986
0
        self
987
0
    }
988
989
    /// Specify an environment variable to read the filter from.
990
    ///
991
    /// If the variable is not set, the default value will be used.
992
0
    pub fn filter_or<E, V>(mut self, filter_env: E, default: V) -> Self
993
0
    where
994
0
        E: Into<Cow<'a, str>>,
995
0
        V: Into<Cow<'a, str>>,
996
0
    {
997
0
        self.filter = Var::new_with_default(filter_env, default);
998
0
999
0
        self
1000
0
    }
1001
1002
    /// Use the default environment variable to read the filter from.
1003
    ///
1004
    /// If the variable is not set, the default value will be used.
1005
0
    pub fn default_filter_or<V>(mut self, default: V) -> Self
1006
0
    where
1007
0
        V: Into<Cow<'a, str>>,
1008
0
    {
1009
0
        self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default);
1010
0
1011
0
        self
1012
0
    }
1013
1014
111k
    fn get_filter(&self) -> Option<String> {
1015
111k
        self.filter.get()
1016
111k
    }
1017
1018
    /// Specify an environment variable to read the style from.
1019
0
    pub fn write_style<E>(mut self, write_style_env: E) -> Self
1020
0
    where
1021
0
        E: Into<Cow<'a, str>>,
1022
0
    {
1023
0
        self.write_style = Var::new(write_style_env);
1024
0
1025
0
        self
1026
0
    }
1027
1028
    /// Specify an environment variable to read the style from.
1029
    ///
1030
    /// If the variable is not set, the default value will be used.
1031
0
    pub fn write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self
1032
0
    where
1033
0
        E: Into<Cow<'a, str>>,
1034
0
        V: Into<Cow<'a, str>>,
1035
0
    {
1036
0
        self.write_style = Var::new_with_default(write_style_env, default);
1037
0
1038
0
        self
1039
0
    }
1040
1041
    /// Use the default environment variable to read the style from.
1042
    ///
1043
    /// If the variable is not set, the default value will be used.
1044
0
    pub fn default_write_style_or<V>(mut self, default: V) -> Self
1045
0
    where
1046
0
        V: Into<Cow<'a, str>>,
1047
0
    {
1048
0
        self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default);
1049
0
1050
0
        self
1051
0
    }
1052
1053
111k
    fn get_write_style(&self) -> Option<String> {
1054
111k
        self.write_style.get()
1055
111k
    }
1056
}
1057
1058
impl<'a> Var<'a> {
1059
222k
    fn new<E>(name: E) -> Self
1060
222k
    where
1061
222k
        E: Into<Cow<'a, str>>,
1062
222k
    {
1063
222k
        Var {
1064
222k
            name: name.into(),
1065
222k
            default: None,
1066
222k
        }
1067
222k
    }
1068
1069
0
    fn new_with_default<E, V>(name: E, default: V) -> Self
1070
0
    where
1071
0
        E: Into<Cow<'a, str>>,
1072
0
        V: Into<Cow<'a, str>>,
1073
0
    {
1074
0
        Var {
1075
0
            name: name.into(),
1076
0
            default: Some(default.into()),
1077
0
        }
1078
0
    }
1079
1080
222k
    fn get(&self) -> Option<String> {
1081
222k
        env::var(&*self.name)
1082
222k
            .ok()
1083
222k
            .or_else(|| self.default.to_owned().map(|v| v.into_owned()))
1084
222k
    }
1085
}
1086
1087
impl<'a, T> From<T> for Env<'a>
1088
where
1089
    T: Into<Cow<'a, str>>,
1090
{
1091
0
    fn from(filter_env: T) -> Self {
1092
0
        Env::default().filter(filter_env.into())
1093
0
    }
1094
}
1095
1096
impl<'a> Default for Env<'a> {
1097
111k
    fn default() -> Self {
1098
111k
        Env {
1099
111k
            filter: Var::new(DEFAULT_FILTER_ENV),
1100
111k
            write_style: Var::new(DEFAULT_WRITE_STYLE_ENV),
1101
111k
        }
1102
111k
    }
1103
}
1104
1105
mod std_fmt_impls {
1106
    use super::*;
1107
    use std::fmt;
1108
1109
    impl fmt::Debug for Logger {
1110
0
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1111
0
            f.debug_struct("Logger")
1112
0
                .field("filter", &self.filter)
1113
0
                .finish()
1114
0
        }
1115
    }
1116
1117
    impl fmt::Debug for Builder {
1118
0
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1119
0
            if self.built {
1120
0
                f.debug_struct("Logger").field("built", &true).finish()
1121
            } else {
1122
0
                f.debug_struct("Logger")
1123
0
                    .field("filter", &self.filter)
1124
0
                    .field("writer", &self.writer)
1125
0
                    .finish()
1126
            }
1127
0
        }
1128
    }
1129
}
1130
1131
/// Attempts to initialize the global logger with an env logger.
1132
///
1133
/// This should be called early in the execution of a Rust program. Any log
1134
/// events that occur before initialization will be ignored.
1135
///
1136
/// # Errors
1137
///
1138
/// This function will fail if it is called more than once, or if another
1139
/// library has already initialized a global logger.
1140
111k
pub fn try_init() -> Result<(), SetLoggerError> {
1141
111k
    try_init_from_env(Env::default())
1142
111k
}
1143
1144
/// Initializes the global logger with an env logger.
1145
///
1146
/// This should be called early in the execution of a Rust program. Any log
1147
/// events that occur before initialization will be ignored.
1148
///
1149
/// # Panics
1150
///
1151
/// This function will panic if it is called more than once, or if another
1152
/// library has already initialized a global logger.
1153
0
pub fn init() {
1154
0
    try_init().expect("env_logger::init should not be called after logger initialized");
1155
0
}
1156
1157
/// Attempts to initialize the global logger with an env logger from the given
1158
/// environment variables.
1159
///
1160
/// This should be called early in the execution of a Rust program. Any log
1161
/// events that occur before initialization will be ignored.
1162
///
1163
/// # Examples
1164
///
1165
/// Initialise a logger using the `MY_LOG` environment variable for filters
1166
/// and `MY_LOG_STYLE` for writing colors:
1167
///
1168
/// ```
1169
/// use env_logger::{Builder, Env};
1170
///
1171
/// # fn run() -> Result<(), Box<::std::error::Error>> {
1172
/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
1173
///
1174
/// env_logger::try_init_from_env(env)?;
1175
///
1176
/// Ok(())
1177
/// # }
1178
/// # run().unwrap();
1179
/// ```
1180
///
1181
/// # Errors
1182
///
1183
/// This function will fail if it is called more than once, or if another
1184
/// library has already initialized a global logger.
1185
111k
pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError>
1186
111k
where
1187
111k
    E: Into<Env<'a>>,
1188
111k
{
1189
111k
    let mut builder = Builder::from_env(env);
1190
111k
1191
111k
    builder.try_init()
1192
111k
}
1193
1194
/// Initializes the global logger with an env logger from the given environment
1195
/// variables.
1196
///
1197
/// This should be called early in the execution of a Rust program. Any log
1198
/// events that occur before initialization will be ignored.
1199
///
1200
/// # Examples
1201
///
1202
/// Initialise a logger using the `MY_LOG` environment variable for filters
1203
/// and `MY_LOG_STYLE` for writing colors:
1204
///
1205
/// ```
1206
/// use env_logger::{Builder, Env};
1207
///
1208
/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
1209
///
1210
/// env_logger::init_from_env(env);
1211
/// ```
1212
///
1213
/// # Panics
1214
///
1215
/// This function will panic if it is called more than once, or if another
1216
/// library has already initialized a global logger.
1217
0
pub fn init_from_env<'a, E>(env: E)
1218
0
where
1219
0
    E: Into<Env<'a>>,
1220
0
{
1221
0
    try_init_from_env(env)
1222
0
        .expect("env_logger::init_from_env should not be called after logger initialized");
1223
0
}
1224
1225
/// Create a new builder with the default environment variables.
1226
///
1227
/// The builder can be configured before being initialized.
1228
/// This is a convenient way of calling [`Builder::from_default_env`].
1229
///
1230
/// [`Builder::from_default_env`]: struct.Builder.html#method.from_default_env
1231
0
pub fn builder() -> Builder {
1232
0
    Builder::from_default_env()
1233
0
}
1234
1235
/// Create a builder from the given environment variables.
1236
///
1237
/// The builder can be configured before being initialized.
1238
#[deprecated(
1239
    since = "0.8.0",
1240
    note = "Prefer `env_logger::Builder::from_env()` instead."
1241
)]
1242
0
pub fn from_env<'a, E>(env: E) -> Builder
1243
0
where
1244
0
    E: Into<Env<'a>>,
1245
0
{
1246
0
    Builder::from_env(env)
1247
0
}
1248
1249
#[cfg(test)]
1250
mod tests {
1251
    use super::*;
1252
1253
    #[test]
1254
    fn env_get_filter_reads_from_var_if_set() {
1255
        env::set_var("env_get_filter_reads_from_var_if_set", "from var");
1256
1257
        let env = Env::new().filter_or("env_get_filter_reads_from_var_if_set", "from default");
1258
1259
        assert_eq!(Some("from var".to_owned()), env.get_filter());
1260
    }
1261
1262
    #[test]
1263
    fn env_get_filter_reads_from_default_if_var_not_set() {
1264
        env::remove_var("env_get_filter_reads_from_default_if_var_not_set");
1265
1266
        let env = Env::new().filter_or(
1267
            "env_get_filter_reads_from_default_if_var_not_set",
1268
            "from default",
1269
        );
1270
1271
        assert_eq!(Some("from default".to_owned()), env.get_filter());
1272
    }
1273
1274
    #[test]
1275
    fn env_get_write_style_reads_from_var_if_set() {
1276
        env::set_var("env_get_write_style_reads_from_var_if_set", "from var");
1277
1278
        let env =
1279
            Env::new().write_style_or("env_get_write_style_reads_from_var_if_set", "from default");
1280
1281
        assert_eq!(Some("from var".to_owned()), env.get_write_style());
1282
    }
1283
1284
    #[test]
1285
    fn env_get_write_style_reads_from_default_if_var_not_set() {
1286
        env::remove_var("env_get_write_style_reads_from_default_if_var_not_set");
1287
1288
        let env = Env::new().write_style_or(
1289
            "env_get_write_style_reads_from_default_if_var_not_set",
1290
            "from default",
1291
        );
1292
1293
        assert_eq!(Some("from default".to_owned()), env.get_write_style());
1294
    }
1295
1296
    #[test]
1297
    fn builder_parse_env_overrides_existing_filters() {
1298
        env::set_var(
1299
            "builder_parse_default_env_overrides_existing_filters",
1300
            "debug",
1301
        );
1302
        let env = Env::new().filter("builder_parse_default_env_overrides_existing_filters");
1303
1304
        let mut builder = Builder::new();
1305
        builder.filter_level(LevelFilter::Trace);
1306
        // Overrides global level to debug
1307
        builder.parse_env(env);
1308
1309
        assert_eq!(builder.filter.build().filter(), LevelFilter::Debug);
1310
    }
1311
}