]>
Commit | Line | Data |
---|---|---|
3c0e092e XL |
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 | |
923072b8 | 100 | //! example::log::target=level |
3c0e092e XL |
101 | //! ``` |
102 | //! | |
923072b8 FG |
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` | |
3c0e092e XL |
118 | //! |
119 | //! When providing the crate name or a module path, explicitly specifying the | |
923072b8 FG |
120 | //! log level is optional. If omitted, all logging for the item will be |
121 | //! enabled. | |
3c0e092e XL |
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 | //! | |
923072b8 FG |
127 | //! * `error` |
128 | //! * `warn` | |
129 | //! * `info` | |
130 | //! * `debug` | |
131 | //! * `trace` | |
3c0e092e XL |
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 | //! | |
923072b8 | 273 | //! [gh-repo-examples]: https://github.com/env-logger-rs/env_logger/tree/main/examples |
3c0e092e XL |
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 | pub fn new() -> Builder { | |
416 | Default::default() | |
417 | } | |
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 | pub fn from_env<'a, E>(env: E) -> Self | |
448 | where | |
449 | E: Into<Env<'a>>, | |
450 | { | |
451 | let mut builder = Builder::new(); | |
452 | builder.parse_env(env); | |
453 | builder | |
454 | } | |
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 | pub fn parse_env<'a, E>(&mut self, env: E) -> &mut Self | |
493 | where | |
494 | E: Into<Env<'a>>, | |
495 | { | |
496 | let env = env.into(); | |
497 | ||
498 | if let Some(s) = env.get_filter() { | |
499 | self.parse_filters(&s); | |
500 | } | |
501 | ||
502 | if let Some(s) = env.get_write_style() { | |
503 | self.parse_write_style(&s); | |
504 | } | |
505 | ||
506 | self | |
507 | } | |
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 | pub fn from_default_env() -> Self { | |
528 | Self::from_env(Env::default()) | |
529 | } | |
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 | pub fn parse_default_env(&mut self) -> &mut Self { | |
554 | self.parse_env(Env::default()) | |
555 | } | |
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 | pub fn format<F: 'static>(&mut self, format: F) -> &mut Self | |
584 | where | |
585 | F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send, | |
586 | { | |
587 | self.format.custom_format = Some(Box::new(format)); | |
588 | self | |
589 | } | |
590 | ||
591 | /// Use the default format. | |
592 | /// | |
593 | /// This method will clear any custom format set on the builder. | |
594 | pub fn default_format(&mut self) -> &mut Self { | |
595 | self.format = Default::default(); | |
596 | self | |
597 | } | |
598 | ||
599 | /// Whether or not to write the level in the default format. | |
600 | pub fn format_level(&mut self, write: bool) -> &mut Self { | |
601 | self.format.format_level = write; | |
602 | self | |
603 | } | |
604 | ||
605 | /// Whether or not to write the module path in the default format. | |
606 | pub fn format_module_path(&mut self, write: bool) -> &mut Self { | |
607 | self.format.format_module_path = write; | |
608 | self | |
609 | } | |
610 | ||
923072b8 FG |
611 | /// Whether or not to write the target in the default format. |
612 | pub fn format_target(&mut self, write: bool) -> &mut Self { | |
613 | self.format.format_target = write; | |
614 | self | |
615 | } | |
616 | ||
3c0e092e XL |
617 | /// Configures the amount of spaces to use to indent multiline log records. |
618 | /// A value of `None` disables any kind of indentation. | |
619 | pub fn format_indent(&mut self, indent: Option<usize>) -> &mut Self { | |
620 | self.format.format_indent = indent; | |
621 | self | |
622 | } | |
623 | ||
624 | /// Configures if timestamp should be included and in what precision. | |
625 | pub fn format_timestamp(&mut self, timestamp: Option<fmt::TimestampPrecision>) -> &mut Self { | |
626 | self.format.format_timestamp = timestamp; | |
627 | self | |
628 | } | |
629 | ||
630 | /// Configures the timestamp to use second precision. | |
631 | pub fn format_timestamp_secs(&mut self) -> &mut Self { | |
632 | self.format_timestamp(Some(fmt::TimestampPrecision::Seconds)) | |
633 | } | |
634 | ||
635 | /// Configures the timestamp to use millisecond precision. | |
636 | pub fn format_timestamp_millis(&mut self) -> &mut Self { | |
637 | self.format_timestamp(Some(fmt::TimestampPrecision::Millis)) | |
638 | } | |
639 | ||
640 | /// Configures the timestamp to use microsecond precision. | |
641 | pub fn format_timestamp_micros(&mut self) -> &mut Self { | |
642 | self.format_timestamp(Some(fmt::TimestampPrecision::Micros)) | |
643 | } | |
644 | ||
645 | /// Configures the timestamp to use nanosecond precision. | |
646 | pub fn format_timestamp_nanos(&mut self) -> &mut Self { | |
647 | self.format_timestamp(Some(fmt::TimestampPrecision::Nanos)) | |
648 | } | |
649 | ||
650 | /// Configures the end of line suffix. | |
651 | pub fn format_suffix(&mut self, suffix: &'static str) -> &mut Self { | |
652 | self.format.format_suffix = suffix; | |
653 | self | |
654 | } | |
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 | pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self { | |
671 | self.filter.filter_module(module, level); | |
672 | self | |
673 | } | |
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 | pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self { | |
690 | self.filter.filter_level(level); | |
691 | self | |
692 | } | |
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 | pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self { | |
712 | self.filter.filter(module, level); | |
713 | self | |
714 | } | |
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 | pub fn parse_filters(&mut self, filters: &str) -> &mut Self { | |
721 | self.filter.parse(filters); | |
722 | self | |
723 | } | |
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 | pub fn target(&mut self, target: fmt::Target) -> &mut Self { | |
744 | self.writer.target(target); | |
745 | self | |
746 | } | |
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 | pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self { | |
765 | self.writer.write_style(write_style); | |
766 | self | |
767 | } | |
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 | pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self { | |
774 | self.writer.parse_write_style(write_style); | |
775 | self | |
776 | } | |
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 | pub fn is_test(&mut self, is_test: bool) -> &mut Self { | |
783 | self.writer.is_test(is_test); | |
784 | self | |
785 | } | |
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 | pub fn try_init(&mut self) -> Result<(), SetLoggerError> { | |
797 | let logger = self.build(); | |
798 | ||
799 | let max_level = logger.filter(); | |
800 | let r = log::set_boxed_logger(Box::new(logger)); | |
801 | ||
802 | if r.is_ok() { | |
803 | log::set_max_level(max_level); | |
804 | } | |
805 | ||
806 | r | |
807 | } | |
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 | pub fn init(&mut self) { | |
819 | self.try_init() | |
820 | .expect("Builder::init should not be called after logger initialized"); | |
821 | } | |
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 | pub fn build(&mut self) -> Logger { | |
828 | assert!(!self.built, "attempt to re-use consumed builder"); | |
829 | self.built = true; | |
830 | ||
831 | Logger { | |
832 | writer: self.writer.build(), | |
833 | filter: self.filter.build(), | |
834 | format: self.format.build(), | |
835 | } | |
836 | } | |
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 | pub fn from_env<'a, E>(env: E) -> Self | |
867 | where | |
868 | E: Into<Env<'a>>, | |
869 | { | |
870 | Builder::from_env(env).build() | |
871 | } | |
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 | pub fn from_default_env() -> Self { | |
891 | Builder::from_default_env().build() | |
892 | } | |
893 | ||
894 | /// Returns the maximum `LevelFilter` that this env logger instance is | |
895 | /// configured to output. | |
896 | pub fn filter(&self) -> LevelFilter { | |
897 | self.filter.filter() | |
898 | } | |
899 | ||
900 | /// Checks if this record matches the configured filter. | |
901 | pub fn matches(&self, record: &Record) -> bool { | |
902 | self.filter.matches(record) | |
903 | } | |
904 | } | |
905 | ||
906 | impl Log for Logger { | |
907 | fn enabled(&self, metadata: &Metadata) -> bool { | |
908 | self.filter.enabled(metadata) | |
909 | } | |
910 | ||
911 | fn log(&self, record: &Record) { | |
912 | 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 | let print = |formatter: &mut Formatter, record: &Record| { | |
927 | let _ = | |
928 | (self.format)(formatter, record).and_then(|_| formatter.print(&self.writer)); | |
929 | ||
930 | // Always clear the buffer afterwards | |
931 | formatter.clear(); | |
932 | }; | |
933 | ||
934 | let printed = FORMATTER | |
935 | .try_with(|tl_buf| { | |
936 | match tl_buf.try_borrow_mut() { | |
937 | // There are no active borrows of the buffer | |
938 | Ok(mut tl_buf) => match *tl_buf { | |
939 | // We have a previously set formatter | |
940 | Some(ref mut formatter) => { | |
941 | // Check the buffer style. If it's different from the logger's | |
942 | // style then drop the buffer and recreate it. | |
943 | if formatter.write_style() != self.writer.write_style() { | |
944 | *formatter = Formatter::new(&self.writer); | |
945 | } | |
946 | ||
947 | print(formatter, record); | |
948 | } | |
949 | // We don't have a previously set formatter | |
950 | None => { | |
951 | let mut formatter = Formatter::new(&self.writer); | |
952 | print(&mut formatter, record); | |
953 | ||
954 | *tl_buf = Some(formatter); | |
955 | } | |
956 | }, | |
957 | // There's already an active borrow of the buffer (due to re-entrancy) | |
958 | Err(_) => { | |
959 | print(&mut Formatter::new(&self.writer), record); | |
960 | } | |
961 | } | |
962 | }) | |
963 | .is_ok(); | |
964 | ||
965 | if !printed { | |
966 | // The thread-local storage was not available (because its | |
967 | // destructor has already run). Create a new single-use | |
968 | // Formatter on the stack for this call. | |
969 | print(&mut Formatter::new(&self.writer), record); | |
970 | } | |
971 | } | |
972 | } | |
973 | ||
974 | fn flush(&self) {} | |
975 | } | |
976 | ||
977 | impl<'a> Env<'a> { | |
978 | /// Get a default set of environment variables. | |
979 | pub fn new() -> Self { | |
980 | Self::default() | |
981 | } | |
982 | ||
983 | /// Specify an environment variable to read the filter from. | |
984 | pub fn filter<E>(mut self, filter_env: E) -> Self | |
985 | where | |
986 | E: Into<Cow<'a, str>>, | |
987 | { | |
988 | self.filter = Var::new(filter_env); | |
989 | ||
990 | self | |
991 | } | |
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 | pub fn filter_or<E, V>(mut self, filter_env: E, default: V) -> Self | |
997 | where | |
998 | E: Into<Cow<'a, str>>, | |
999 | V: Into<Cow<'a, str>>, | |
1000 | { | |
1001 | self.filter = Var::new_with_default(filter_env, default); | |
1002 | ||
1003 | self | |
1004 | } | |
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 | pub fn default_filter_or<V>(mut self, default: V) -> Self | |
1010 | where | |
1011 | V: Into<Cow<'a, str>>, | |
1012 | { | |
1013 | self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default); | |
1014 | ||
1015 | self | |
1016 | } | |
1017 | ||
1018 | fn get_filter(&self) -> Option<String> { | |
1019 | self.filter.get() | |
1020 | } | |
1021 | ||
1022 | /// Specify an environment variable to read the style from. | |
1023 | pub fn write_style<E>(mut self, write_style_env: E) -> Self | |
1024 | where | |
1025 | E: Into<Cow<'a, str>>, | |
1026 | { | |
1027 | self.write_style = Var::new(write_style_env); | |
1028 | ||
1029 | self | |
1030 | } | |
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 | pub fn write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self | |
1036 | where | |
1037 | E: Into<Cow<'a, str>>, | |
1038 | V: Into<Cow<'a, str>>, | |
1039 | { | |
1040 | self.write_style = Var::new_with_default(write_style_env, default); | |
1041 | ||
1042 | self | |
1043 | } | |
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 | pub fn default_write_style_or<V>(mut self, default: V) -> Self | |
1049 | where | |
1050 | V: Into<Cow<'a, str>>, | |
1051 | { | |
1052 | self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default); | |
1053 | ||
1054 | self | |
1055 | } | |
1056 | ||
1057 | fn get_write_style(&self) -> Option<String> { | |
1058 | self.write_style.get() | |
1059 | } | |
1060 | } | |
1061 | ||
1062 | impl<'a> Var<'a> { | |
1063 | fn new<E>(name: E) -> Self | |
1064 | where | |
1065 | E: Into<Cow<'a, str>>, | |
1066 | { | |
1067 | Var { | |
1068 | name: name.into(), | |
1069 | default: None, | |
1070 | } | |
1071 | } | |
1072 | ||
1073 | fn new_with_default<E, V>(name: E, default: V) -> Self | |
1074 | where | |
1075 | E: Into<Cow<'a, str>>, | |
1076 | V: Into<Cow<'a, str>>, | |
1077 | { | |
1078 | Var { | |
1079 | name: name.into(), | |
1080 | default: Some(default.into()), | |
1081 | } | |
1082 | } | |
1083 | ||
1084 | fn get(&self) -> Option<String> { | |
1085 | env::var(&*self.name) | |
1086 | .ok() | |
1087 | .or_else(|| self.default.to_owned().map(|v| v.into_owned())) | |
1088 | } | |
1089 | } | |
1090 | ||
1091 | impl<'a, T> From<T> for Env<'a> | |
1092 | where | |
1093 | T: Into<Cow<'a, str>>, | |
1094 | { | |
1095 | fn from(filter_env: T) -> Self { | |
1096 | Env::default().filter(filter_env.into()) | |
1097 | } | |
1098 | } | |
1099 | ||
1100 | impl<'a> Default for Env<'a> { | |
1101 | fn default() -> Self { | |
1102 | Env { | |
1103 | filter: Var::new(DEFAULT_FILTER_ENV), | |
1104 | write_style: Var::new(DEFAULT_WRITE_STYLE_ENV), | |
1105 | } | |
1106 | } | |
1107 | } | |
1108 | ||
1109 | mod std_fmt_impls { | |
1110 | use super::*; | |
1111 | use std::fmt; | |
1112 | ||
1113 | impl fmt::Debug for Logger { | |
1114 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
1115 | f.debug_struct("Logger") | |
1116 | .field("filter", &self.filter) | |
1117 | .finish() | |
1118 | } | |
1119 | } | |
1120 | ||
1121 | impl fmt::Debug for Builder { | |
1122 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
1123 | if self.built { | |
1124 | f.debug_struct("Logger").field("built", &true).finish() | |
1125 | } else { | |
1126 | f.debug_struct("Logger") | |
1127 | .field("filter", &self.filter) | |
1128 | .field("writer", &self.writer) | |
1129 | .finish() | |
1130 | } | |
1131 | } | |
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 | pub fn try_init() -> Result<(), SetLoggerError> { | |
1145 | try_init_from_env(Env::default()) | |
1146 | } | |
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 | pub fn init() { | |
1158 | try_init().expect("env_logger::init should not be called after logger initialized"); | |
1159 | } | |
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 | pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError> | |
1190 | where | |
1191 | E: Into<Env<'a>>, | |
1192 | { | |
1193 | let mut builder = Builder::from_env(env); | |
1194 | ||
1195 | builder.try_init() | |
1196 | } | |
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 | pub fn init_from_env<'a, E>(env: E) | |
1222 | where | |
1223 | E: Into<Env<'a>>, | |
1224 | { | |
1225 | try_init_from_env(env) | |
1226 | .expect("env_logger::init_from_env should not be called after logger initialized"); | |
1227 | } | |
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 | pub fn builder() -> Builder { | |
1236 | Builder::from_default_env() | |
1237 | } | |
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 | pub fn from_env<'a, E>(env: E) -> Builder | |
1247 | where | |
1248 | E: Into<Env<'a>>, | |
1249 | { | |
1250 | Builder::from_env(env) | |
1251 | } | |
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 | } |