Coverage Report

Created: 2025-07-23 06:18

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