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 overridden. |
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 | pub fn new() -> Builder { |
412 | Default::default() |
413 | } |
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 | pub fn from_env<'a, E>(env: E) -> Self |
444 | where |
445 | E: Into<Env<'a>>, |
446 | { |
447 | let mut builder = Builder::new(); |
448 | builder.parse_env(env); |
449 | builder |
450 | } |
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 | pub fn parse_env<'a, E>(&mut self, env: E) -> &mut Self |
489 | where |
490 | E: Into<Env<'a>>, |
491 | { |
492 | let env = env.into(); |
493 | |
494 | if let Some(s) = env.get_filter() { |
495 | self.parse_filters(&s); |
496 | } |
497 | |
498 | if let Some(s) = env.get_write_style() { |
499 | self.parse_write_style(&s); |
500 | } |
501 | |
502 | self |
503 | } |
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 | pub fn from_default_env() -> Self { |
524 | Self::from_env(Env::default()) |
525 | } |
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 | pub fn parse_default_env(&mut self) -> &mut Self { |
550 | self.parse_env(Env::default()) |
551 | } |
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 | pub fn format<F: 'static>(&mut self, format: F) -> &mut Self |
580 | where |
581 | F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send, |
582 | { |
583 | self.format.custom_format = Some(Box::new(format)); |
584 | self |
585 | } |
586 | |
587 | /// Use the default format. |
588 | /// |
589 | /// This method will clear any custom format set on the builder. |
590 | pub fn default_format(&mut self) -> &mut Self { |
591 | self.format = Default::default(); |
592 | self |
593 | } |
594 | |
595 | /// Whether or not to write the level in the default format. |
596 | pub fn format_level(&mut self, write: bool) -> &mut Self { |
597 | self.format.format_level = write; |
598 | self |
599 | } |
600 | |
601 | /// Whether or not to write the module path in the default format. |
602 | pub fn format_module_path(&mut self, write: bool) -> &mut Self { |
603 | self.format.format_module_path = write; |
604 | self |
605 | } |
606 | |
607 | /// Whether or not to write the target in the default format. |
608 | pub fn format_target(&mut self, write: bool) -> &mut Self { |
609 | self.format.format_target = write; |
610 | self |
611 | } |
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 | pub fn format_indent(&mut self, indent: Option<usize>) -> &mut Self { |
616 | self.format.format_indent = indent; |
617 | self |
618 | } |
619 | |
620 | /// Configures if timestamp should be included and in what precision. |
621 | pub fn format_timestamp(&mut self, timestamp: Option<fmt::TimestampPrecision>) -> &mut Self { |
622 | self.format.format_timestamp = timestamp; |
623 | self |
624 | } |
625 | |
626 | /// Configures the timestamp to use second precision. |
627 | pub fn format_timestamp_secs(&mut self) -> &mut Self { |
628 | self.format_timestamp(Some(fmt::TimestampPrecision::Seconds)) |
629 | } |
630 | |
631 | /// Configures the timestamp to use millisecond precision. |
632 | pub fn format_timestamp_millis(&mut self) -> &mut Self { |
633 | self.format_timestamp(Some(fmt::TimestampPrecision::Millis)) |
634 | } |
635 | |
636 | /// Configures the timestamp to use microsecond precision. |
637 | pub fn format_timestamp_micros(&mut self) -> &mut Self { |
638 | self.format_timestamp(Some(fmt::TimestampPrecision::Micros)) |
639 | } |
640 | |
641 | /// Configures the timestamp to use nanosecond precision. |
642 | pub fn format_timestamp_nanos(&mut self) -> &mut Self { |
643 | self.format_timestamp(Some(fmt::TimestampPrecision::Nanos)) |
644 | } |
645 | |
646 | /// Configures the end of line suffix. |
647 | pub fn format_suffix(&mut self, suffix: &'static str) -> &mut Self { |
648 | self.format.format_suffix = suffix; |
649 | self |
650 | } |
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 | pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self { |
667 | self.filter.filter_module(module, level); |
668 | self |
669 | } |
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 | pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self { |
686 | self.filter.filter_level(level); |
687 | self |
688 | } |
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 | pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self { |
708 | self.filter.filter(module, level); |
709 | self |
710 | } |
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 | pub fn parse_filters(&mut self, filters: &str) -> &mut Self { |
717 | self.filter.parse(filters); |
718 | self |
719 | } |
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 | pub fn target(&mut self, target: fmt::Target) -> &mut Self { |
740 | self.writer.target(target); |
741 | self |
742 | } |
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 | pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self { |
761 | self.writer.write_style(write_style); |
762 | self |
763 | } |
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 | pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self { |
770 | self.writer.parse_write_style(write_style); |
771 | self |
772 | } |
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 | pub fn is_test(&mut self, is_test: bool) -> &mut Self { |
779 | self.writer.is_test(is_test); |
780 | self |
781 | } |
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 | pub fn try_init(&mut self) -> Result<(), SetLoggerError> { |
793 | let logger = self.build(); |
794 | |
795 | let max_level = logger.filter(); |
796 | let r = log::set_boxed_logger(Box::new(logger)); |
797 | |
798 | if r.is_ok() { |
799 | log::set_max_level(max_level); |
800 | } |
801 | |
802 | r |
803 | } |
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 | pub fn init(&mut self) { |
815 | self.try_init() |
816 | .expect("Builder::init should not be called after logger initialized" ); |
817 | } |
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 | pub fn build(&mut self) -> Logger { |
824 | assert!(!self.built, "attempt to re-use consumed builder" ); |
825 | self.built = true; |
826 | |
827 | Logger { |
828 | writer: self.writer.build(), |
829 | filter: self.filter.build(), |
830 | format: self.format.build(), |
831 | } |
832 | } |
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 | pub fn from_env<'a, E>(env: E) -> Self |
863 | where |
864 | E: Into<Env<'a>>, |
865 | { |
866 | Builder::from_env(env).build() |
867 | } |
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 | pub fn from_default_env() -> Self { |
887 | Builder::from_default_env().build() |
888 | } |
889 | |
890 | /// Returns the maximum `LevelFilter` that this env logger instance is |
891 | /// configured to output. |
892 | pub fn filter(&self) -> LevelFilter { |
893 | self.filter.filter() |
894 | } |
895 | |
896 | /// Checks if this record matches the configured filter. |
897 | pub fn matches(&self, record: &Record) -> bool { |
898 | self.filter.matches(record) |
899 | } |
900 | } |
901 | |
902 | impl Log for Logger { |
903 | fn enabled(&self, metadata: &Metadata) -> bool { |
904 | self.filter.enabled(metadata) |
905 | } |
906 | |
907 | fn log(&self, record: &Record) { |
908 | 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 shrunk |
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 | let print = |formatter: &mut Formatter, record: &Record| { |
923 | let _ = |
924 | (self.format)(formatter, record).and_then(|_| formatter.print(&self.writer)); |
925 | |
926 | // Always clear the buffer afterwards |
927 | formatter.clear(); |
928 | }; |
929 | |
930 | let printed = FORMATTER |
931 | .try_with(|tl_buf| { |
932 | match tl_buf.try_borrow_mut() { |
933 | // There are no active borrows of the buffer |
934 | Ok(mut tl_buf) => match *tl_buf { |
935 | // We have a previously set formatter |
936 | Some(ref mut formatter) => { |
937 | // Check the buffer style. If it's different from the logger's |
938 | // style then drop the buffer and recreate it. |
939 | if formatter.write_style() != self.writer.write_style() { |
940 | *formatter = Formatter::new(&self.writer); |
941 | } |
942 | |
943 | print(formatter, record); |
944 | } |
945 | // We don't have a previously set formatter |
946 | None => { |
947 | let mut formatter = Formatter::new(&self.writer); |
948 | print(&mut formatter, record); |
949 | |
950 | *tl_buf = Some(formatter); |
951 | } |
952 | }, |
953 | // There's already an active borrow of the buffer (due to re-entrancy) |
954 | Err(_) => { |
955 | print(&mut Formatter::new(&self.writer), record); |
956 | } |
957 | } |
958 | }) |
959 | .is_ok(); |
960 | |
961 | if !printed { |
962 | // The thread-local storage was not available (because its |
963 | // destructor has already run). Create a new single-use |
964 | // Formatter on the stack for this call. |
965 | print(&mut Formatter::new(&self.writer), record); |
966 | } |
967 | } |
968 | } |
969 | |
970 | fn flush(&self) {} |
971 | } |
972 | |
973 | impl<'a> Env<'a> { |
974 | /// Get a default set of environment variables. |
975 | pub fn new() -> Self { |
976 | Self::default() |
977 | } |
978 | |
979 | /// Specify an environment variable to read the filter from. |
980 | pub fn filter<E>(mut self, filter_env: E) -> Self |
981 | where |
982 | E: Into<Cow<'a, str>>, |
983 | { |
984 | self.filter = Var::new(filter_env); |
985 | |
986 | self |
987 | } |
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 | pub fn filter_or<E, V>(mut self, filter_env: E, default: V) -> Self |
993 | where |
994 | E: Into<Cow<'a, str>>, |
995 | V: Into<Cow<'a, str>>, |
996 | { |
997 | self.filter = Var::new_with_default(filter_env, default); |
998 | |
999 | self |
1000 | } |
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 | pub fn default_filter_or<V>(mut self, default: V) -> Self |
1006 | where |
1007 | V: Into<Cow<'a, str>>, |
1008 | { |
1009 | self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default); |
1010 | |
1011 | self |
1012 | } |
1013 | |
1014 | fn get_filter(&self) -> Option<String> { |
1015 | self.filter.get() |
1016 | } |
1017 | |
1018 | /// Specify an environment variable to read the style from. |
1019 | pub fn write_style<E>(mut self, write_style_env: E) -> Self |
1020 | where |
1021 | E: Into<Cow<'a, str>>, |
1022 | { |
1023 | self.write_style = Var::new(write_style_env); |
1024 | |
1025 | self |
1026 | } |
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 | pub fn write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self |
1032 | where |
1033 | E: Into<Cow<'a, str>>, |
1034 | V: Into<Cow<'a, str>>, |
1035 | { |
1036 | self.write_style = Var::new_with_default(write_style_env, default); |
1037 | |
1038 | self |
1039 | } |
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 | pub fn default_write_style_or<V>(mut self, default: V) -> Self |
1045 | where |
1046 | V: Into<Cow<'a, str>>, |
1047 | { |
1048 | self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default); |
1049 | |
1050 | self |
1051 | } |
1052 | |
1053 | fn get_write_style(&self) -> Option<String> { |
1054 | self.write_style.get() |
1055 | } |
1056 | } |
1057 | |
1058 | impl<'a> Var<'a> { |
1059 | fn new<E>(name: E) -> Self |
1060 | where |
1061 | E: Into<Cow<'a, str>>, |
1062 | { |
1063 | Var { |
1064 | name: name.into(), |
1065 | default: None, |
1066 | } |
1067 | } |
1068 | |
1069 | fn new_with_default<E, V>(name: E, default: V) -> Self |
1070 | where |
1071 | E: Into<Cow<'a, str>>, |
1072 | V: Into<Cow<'a, str>>, |
1073 | { |
1074 | Var { |
1075 | name: name.into(), |
1076 | default: Some(default.into()), |
1077 | } |
1078 | } |
1079 | |
1080 | fn get(&self) -> Option<String> { |
1081 | env::var(&*self.name) |
1082 | .ok() |
1083 | .or_else(|| self.default.to_owned().map(|v| v.into_owned())) |
1084 | } |
1085 | } |
1086 | |
1087 | impl<'a, T> From<T> for Env<'a> |
1088 | where |
1089 | T: Into<Cow<'a, str>>, |
1090 | { |
1091 | fn from(filter_env: T) -> Self { |
1092 | Env::default().filter(filter_env:filter_env.into()) |
1093 | } |
1094 | } |
1095 | |
1096 | impl<'a> Default for Env<'a> { |
1097 | fn default() -> Self { |
1098 | Env { |
1099 | filter: Var::new(DEFAULT_FILTER_ENV), |
1100 | write_style: Var::new(DEFAULT_WRITE_STYLE_ENV), |
1101 | } |
1102 | } |
1103 | } |
1104 | |
1105 | mod std_fmt_impls { |
1106 | use super::*; |
1107 | use std::fmt; |
1108 | |
1109 | impl fmt::Debug for Logger { |
1110 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1111 | f.debug_struct("Logger" ) |
1112 | .field("filter" , &self.filter) |
1113 | .finish() |
1114 | } |
1115 | } |
1116 | |
1117 | impl fmt::Debug for Builder { |
1118 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1119 | if self.built { |
1120 | f.debug_struct("Logger" ).field("built" , &true).finish() |
1121 | } else { |
1122 | f.debug_struct("Logger" ) |
1123 | .field("filter" , &self.filter) |
1124 | .field("writer" , &self.writer) |
1125 | .finish() |
1126 | } |
1127 | } |
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 | pub fn try_init() -> Result<(), SetLoggerError> { |
1141 | try_init_from_env(Env::default()) |
1142 | } |
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 | pub fn init() { |
1154 | try_init().expect(msg:"env_logger::init should not be called after logger initialized" ); |
1155 | } |
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<dyn ::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 | pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError> |
1186 | where |
1187 | E: Into<Env<'a>>, |
1188 | { |
1189 | let mut builder: Builder = Builder::from_env(env); |
1190 | |
1191 | builder.try_init() |
1192 | } |
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 | pub fn init_from_env<'a, E>(env: E) |
1218 | where |
1219 | E: Into<Env<'a>>, |
1220 | { |
1221 | try_init_from_env(env) |
1222 | .expect(msg:"env_logger::init_from_env should not be called after logger initialized" ); |
1223 | } |
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 | pub fn builder() -> Builder { |
1232 | Builder::from_default_env() |
1233 | } |
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 | pub fn from_env<'a, E>(env: E) -> Builder |
1243 | where |
1244 | E: Into<Env<'a>>, |
1245 | { |
1246 | Builder::from_env(env) |
1247 | } |
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 | } |
1312 | |