1336d762aSopenharmony_ci// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2336d762aSopenharmony_ci// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3336d762aSopenharmony_ci// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
4336d762aSopenharmony_ci// option. This file may not be copied, modified, or distributed
5336d762aSopenharmony_ci// except according to those terms.
6336d762aSopenharmony_ci
7336d762aSopenharmony_ci//! A simple logger that can be configured via environment variables, for use
8336d762aSopenharmony_ci//! with the logging facade exposed by the [`log` crate][log-crate-url].
9336d762aSopenharmony_ci//!
10336d762aSopenharmony_ci//! Despite having "env" in its name, **`env_logger`** can also be configured by
11336d762aSopenharmony_ci//! other means besides environment variables. See [the examples][gh-repo-examples]
12336d762aSopenharmony_ci//! in the source repository for more approaches.
13336d762aSopenharmony_ci//!
14336d762aSopenharmony_ci//! By default, `env_logger` writes logs to `stderr`, but can be configured to
15336d762aSopenharmony_ci//! instead write them to `stdout`.
16336d762aSopenharmony_ci//!
17336d762aSopenharmony_ci//! ## Example
18336d762aSopenharmony_ci//!
19336d762aSopenharmony_ci//! ```
20336d762aSopenharmony_ci//! use log::{debug, error, log_enabled, info, Level};
21336d762aSopenharmony_ci//!
22336d762aSopenharmony_ci//! env_logger::init();
23336d762aSopenharmony_ci//!
24336d762aSopenharmony_ci//! debug!("this is a debug {}", "message");
25336d762aSopenharmony_ci//! error!("this is printed by default");
26336d762aSopenharmony_ci//!
27336d762aSopenharmony_ci//! if log_enabled!(Level::Info) {
28336d762aSopenharmony_ci//!     let x = 3 * 4; // expensive computation
29336d762aSopenharmony_ci//!     info!("the answer was: {}", x);
30336d762aSopenharmony_ci//! }
31336d762aSopenharmony_ci//! ```
32336d762aSopenharmony_ci//!
33336d762aSopenharmony_ci//! Assumes the binary is `main`:
34336d762aSopenharmony_ci//!
35336d762aSopenharmony_ci//! ```{.bash}
36336d762aSopenharmony_ci//! $ RUST_LOG=error ./main
37336d762aSopenharmony_ci//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
38336d762aSopenharmony_ci//! ```
39336d762aSopenharmony_ci//!
40336d762aSopenharmony_ci//! ```{.bash}
41336d762aSopenharmony_ci//! $ RUST_LOG=info ./main
42336d762aSopenharmony_ci//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
43336d762aSopenharmony_ci//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
44336d762aSopenharmony_ci//! ```
45336d762aSopenharmony_ci//!
46336d762aSopenharmony_ci//! ```{.bash}
47336d762aSopenharmony_ci//! $ RUST_LOG=debug ./main
48336d762aSopenharmony_ci//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message
49336d762aSopenharmony_ci//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
50336d762aSopenharmony_ci//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
51336d762aSopenharmony_ci//! ```
52336d762aSopenharmony_ci//!
53336d762aSopenharmony_ci//! You can also set the log level on a per module basis:
54336d762aSopenharmony_ci//!
55336d762aSopenharmony_ci//! ```{.bash}
56336d762aSopenharmony_ci//! $ RUST_LOG=main=info ./main
57336d762aSopenharmony_ci//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
58336d762aSopenharmony_ci//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
59336d762aSopenharmony_ci//! ```
60336d762aSopenharmony_ci//!
61336d762aSopenharmony_ci//! And enable all logging:
62336d762aSopenharmony_ci//!
63336d762aSopenharmony_ci//! ```{.bash}
64336d762aSopenharmony_ci//! $ RUST_LOG=main ./main
65336d762aSopenharmony_ci//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message
66336d762aSopenharmony_ci//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
67336d762aSopenharmony_ci//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
68336d762aSopenharmony_ci//! ```
69336d762aSopenharmony_ci//!
70336d762aSopenharmony_ci//! If the binary name contains hyphens, you will need to replace
71336d762aSopenharmony_ci//! them with underscores:
72336d762aSopenharmony_ci//!
73336d762aSopenharmony_ci//! ```{.bash}
74336d762aSopenharmony_ci//! $ RUST_LOG=my_app ./my-app
75336d762aSopenharmony_ci//! [2017-11-09T02:12:24Z DEBUG my_app] this is a debug message
76336d762aSopenharmony_ci//! [2017-11-09T02:12:24Z ERROR my_app] this is printed by default
77336d762aSopenharmony_ci//! [2017-11-09T02:12:24Z INFO my_app] the answer was: 12
78336d762aSopenharmony_ci//! ```
79336d762aSopenharmony_ci//!
80336d762aSopenharmony_ci//! This is because Rust modules and crates cannot contain hyphens
81336d762aSopenharmony_ci//! in their name, although `cargo` continues to accept them.
82336d762aSopenharmony_ci//!
83336d762aSopenharmony_ci//! See the documentation for the [`log` crate][log-crate-url] for more
84336d762aSopenharmony_ci//! information about its API.
85336d762aSopenharmony_ci//!
86336d762aSopenharmony_ci//! ## Enabling logging
87336d762aSopenharmony_ci//!
88336d762aSopenharmony_ci//! Log levels are controlled on a per-module basis, and **by default all
89336d762aSopenharmony_ci//! logging is disabled except for the `error` level**.
90336d762aSopenharmony_ci//!
91336d762aSopenharmony_ci//! Logging is controlled via the **`RUST_LOG`** environment variable. The
92336d762aSopenharmony_ci//! value of this environment variable is a comma-separated list of *logging
93336d762aSopenharmony_ci//! directives*. A logging directive is of the form:
94336d762aSopenharmony_ci//!
95336d762aSopenharmony_ci//! ```text
96336d762aSopenharmony_ci//! example::log::target=level
97336d762aSopenharmony_ci//! ```
98336d762aSopenharmony_ci//!
99336d762aSopenharmony_ci//! The log target is typically equal to the path of the module the message
100336d762aSopenharmony_ci//! in question originated from, though it can be overriden.
101336d762aSopenharmony_ci//!
102336d762aSopenharmony_ci//! The path is rooted in the name of the crate it was compiled for, so if
103336d762aSopenharmony_ci//! your program is in a file called, for example, `hello.rs`, the path would
104336d762aSopenharmony_ci//! simply be be `hello`.
105336d762aSopenharmony_ci//!
106336d762aSopenharmony_ci//! Furthermore, the log can be filtered using prefix-search based on the
107336d762aSopenharmony_ci//! specified log target. A value of, for example, `RUST_LOG=example`, would
108336d762aSopenharmony_ci//! match all of the messages with targets:
109336d762aSopenharmony_ci//!
110336d762aSopenharmony_ci//! * `example`
111336d762aSopenharmony_ci//! * `example::test`
112336d762aSopenharmony_ci//! * `example::test::module::submodule`
113336d762aSopenharmony_ci//! * `examples::and_more_examples`
114336d762aSopenharmony_ci//!
115336d762aSopenharmony_ci//! When providing the crate name or a module path, explicitly specifying the
116336d762aSopenharmony_ci//! log level is optional. If omitted, all logging for the item will be
117336d762aSopenharmony_ci//! enabled.
118336d762aSopenharmony_ci//!
119336d762aSopenharmony_ci//! The names of the log levels that may be specified correspond to the
120336d762aSopenharmony_ci//! variations of the [`log::Level`][level-enum] enum from the `log`
121336d762aSopenharmony_ci//! crate. They are:
122336d762aSopenharmony_ci//!
123336d762aSopenharmony_ci//! * `error`
124336d762aSopenharmony_ci//! * `warn`
125336d762aSopenharmony_ci//! * `info`
126336d762aSopenharmony_ci//! * `debug`
127336d762aSopenharmony_ci//! * `trace`
128336d762aSopenharmony_ci//!
129336d762aSopenharmony_ci//! There is also a pseudo logging level, `off`, which may be specified to
130336d762aSopenharmony_ci//! disable all logging for a given module or for the entire application. As
131336d762aSopenharmony_ci//! with the logging levels, the letter case is not significant[^fn-off].
132336d762aSopenharmony_ci//!
133336d762aSopenharmony_ci//! [^fn-off]: Similar to the universe of log level names, the `off` pseudo
134336d762aSopenharmony_ci//!    log level feature is also provided by the underlying `log` crate.
135336d762aSopenharmony_ci//!
136336d762aSopenharmony_ci//! The letter case is not significant for the logging level names; e.g.,
137336d762aSopenharmony_ci//! `debug`, `DEBUG`, and `dEbuG` all represent the same logging level. For
138336d762aSopenharmony_ci//! consistency, our convention is to use the lower case names. Where our docs
139336d762aSopenharmony_ci//! do use other forms, they do so in the context of specific examples, so you
140336d762aSopenharmony_ci//! won't be surprised if you see similar usage in the wild.
141336d762aSopenharmony_ci//!
142336d762aSopenharmony_ci//! As the log level for a module is optional, the module to enable logging for
143336d762aSopenharmony_ci//! is also optional. **If only a level is provided, then the global log
144336d762aSopenharmony_ci//! level for all modules is set to this value.**
145336d762aSopenharmony_ci//!
146336d762aSopenharmony_ci//! Some examples of valid values of `RUST_LOG` are:
147336d762aSopenharmony_ci//!
148336d762aSopenharmony_ci//! * `hello` turns on all logging for the 'hello' module
149336d762aSopenharmony_ci//! * `trace` turns on all logging for the application, regardless of its name
150336d762aSopenharmony_ci//! * `TRACE` turns on all logging for the application, regardless of its name (same as previous)
151336d762aSopenharmony_ci//! * `info` turns on all info logging
152336d762aSopenharmony_ci//! * `INFO` turns on all info logging (same as previous)
153336d762aSopenharmony_ci//! * `hello=debug` turns on debug logging for 'hello'
154336d762aSopenharmony_ci//! * `hello=DEBUG` turns on debug logging for 'hello' (same as previous)
155336d762aSopenharmony_ci//! * `hello,std::option` turns on hello, and std's option logging
156336d762aSopenharmony_ci//! * `error,hello=warn` turn on global error logging and also warn for hello
157336d762aSopenharmony_ci//! * `error,hello=off`  turn on global error logging, but turn off logging for hello
158336d762aSopenharmony_ci//! * `off` turns off all logging for the application
159336d762aSopenharmony_ci//! * `OFF` turns off all logging for the application (same as previous)
160336d762aSopenharmony_ci//!
161336d762aSopenharmony_ci//! ## Filtering results
162336d762aSopenharmony_ci//!
163336d762aSopenharmony_ci//! A `RUST_LOG` directive may include a regex filter. The syntax is to append `/`
164336d762aSopenharmony_ci//! followed by a regex. Each message is checked against the regex, and is only
165336d762aSopenharmony_ci//! logged if it matches. Note that the matching is done after formatting the
166336d762aSopenharmony_ci//! log string but before adding any logging meta-data. There is a single filter
167336d762aSopenharmony_ci//! for all modules.
168336d762aSopenharmony_ci//!
169336d762aSopenharmony_ci//! Some examples:
170336d762aSopenharmony_ci//!
171336d762aSopenharmony_ci//! * `hello/foo` turns on all logging for the 'hello' module where the log
172336d762aSopenharmony_ci//!   message includes 'foo'.
173336d762aSopenharmony_ci//! * `info/f.o` turns on all info logging where the log message includes 'foo',
174336d762aSopenharmony_ci//!   'f1o', 'fao', etc.
175336d762aSopenharmony_ci//! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the log
176336d762aSopenharmony_ci//!   message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc.
177336d762aSopenharmony_ci//! * `error,hello=warn/[0-9]scopes` turn on global error logging and also
178336d762aSopenharmony_ci//!   warn for hello. In both cases the log message must include a single digit
179336d762aSopenharmony_ci//!   number followed by 'scopes'.
180336d762aSopenharmony_ci//!
181336d762aSopenharmony_ci//! ## Capturing logs in tests
182336d762aSopenharmony_ci//!
183336d762aSopenharmony_ci//! Records logged during `cargo test` will not be captured by the test harness by default.
184336d762aSopenharmony_ci//! The [`Builder::is_test`] method can be used in unit tests to ensure logs will be captured:
185336d762aSopenharmony_ci//!
186336d762aSopenharmony_ci//! ```
187336d762aSopenharmony_ci//! # #[macro_use] extern crate log;
188336d762aSopenharmony_ci//! #[cfg(test)]
189336d762aSopenharmony_ci//! mod tests {
190336d762aSopenharmony_ci//!     fn init() {
191336d762aSopenharmony_ci//!         let _ = env_logger::builder().is_test(true).try_init();
192336d762aSopenharmony_ci//!     }
193336d762aSopenharmony_ci//!
194336d762aSopenharmony_ci//!     #[test]
195336d762aSopenharmony_ci//!     fn it_works() {
196336d762aSopenharmony_ci//!         init();
197336d762aSopenharmony_ci//!
198336d762aSopenharmony_ci//!         info!("This record will be captured by `cargo test`");
199336d762aSopenharmony_ci//!
200336d762aSopenharmony_ci//!         assert_eq!(2, 1 + 1);
201336d762aSopenharmony_ci//!     }
202336d762aSopenharmony_ci//! }
203336d762aSopenharmony_ci//! ```
204336d762aSopenharmony_ci//!
205336d762aSopenharmony_ci//! Enabling test capturing comes at the expense of color and other style support
206336d762aSopenharmony_ci//! and may have performance implications.
207336d762aSopenharmony_ci//!
208336d762aSopenharmony_ci//! ## Disabling colors
209336d762aSopenharmony_ci//!
210336d762aSopenharmony_ci//! Colors and other styles can be configured with the `RUST_LOG_STYLE`
211336d762aSopenharmony_ci//! environment variable. It accepts the following values:
212336d762aSopenharmony_ci//!
213336d762aSopenharmony_ci//! * `auto` (default) will attempt to print style characters, but don't force the issue.
214336d762aSopenharmony_ci//! If the console isn't available on Windows, or if TERM=dumb, for example, then don't print colors.
215336d762aSopenharmony_ci//! * `always` will always print style characters even if they aren't supported by the terminal.
216336d762aSopenharmony_ci//! This includes emitting ANSI colors on Windows if the console API is unavailable.
217336d762aSopenharmony_ci//! * `never` will never print style characters.
218336d762aSopenharmony_ci//!
219336d762aSopenharmony_ci//! ## Tweaking the default format
220336d762aSopenharmony_ci//!
221336d762aSopenharmony_ci//! Parts of the default format can be excluded from the log output using the [`Builder`].
222336d762aSopenharmony_ci//! The following example excludes the timestamp from the log output:
223336d762aSopenharmony_ci//!
224336d762aSopenharmony_ci//! ```
225336d762aSopenharmony_ci//! env_logger::builder()
226336d762aSopenharmony_ci//!     .format_timestamp(None)
227336d762aSopenharmony_ci//!     .init();
228336d762aSopenharmony_ci//! ```
229336d762aSopenharmony_ci//!
230336d762aSopenharmony_ci//! ### Stability of the default format
231336d762aSopenharmony_ci//!
232336d762aSopenharmony_ci//! The default format won't optimise for long-term stability, and explicitly makes no
233336d762aSopenharmony_ci//! guarantees about the stability of its output across major, minor or patch version
234336d762aSopenharmony_ci//! bumps during `0.x`.
235336d762aSopenharmony_ci//!
236336d762aSopenharmony_ci//! If you want to capture or interpret the output of `env_logger` programmatically
237336d762aSopenharmony_ci//! then you should use a custom format.
238336d762aSopenharmony_ci//!
239336d762aSopenharmony_ci//! ### Using a custom format
240336d762aSopenharmony_ci//!
241336d762aSopenharmony_ci//! Custom formats can be provided as closures to the [`Builder`].
242336d762aSopenharmony_ci//! These closures take a [`Formatter`] and `log::Record` as arguments:
243336d762aSopenharmony_ci//!
244336d762aSopenharmony_ci//! ```
245336d762aSopenharmony_ci//! use std::io::Write;
246336d762aSopenharmony_ci//!
247336d762aSopenharmony_ci//! env_logger::builder()
248336d762aSopenharmony_ci//!     .format(|buf, record| {
249336d762aSopenharmony_ci//!         writeln!(buf, "{}: {}", record.level(), record.args())
250336d762aSopenharmony_ci//!     })
251336d762aSopenharmony_ci//!     .init();
252336d762aSopenharmony_ci//! ```
253336d762aSopenharmony_ci//!
254336d762aSopenharmony_ci//! See the [`fmt`] module for more details about custom formats.
255336d762aSopenharmony_ci//!
256336d762aSopenharmony_ci//! ## Specifying defaults for environment variables
257336d762aSopenharmony_ci//!
258336d762aSopenharmony_ci//! `env_logger` can read configuration from environment variables.
259336d762aSopenharmony_ci//! If these variables aren't present, the default value to use can be tweaked with the [`Env`] type.
260336d762aSopenharmony_ci//! The following example defaults to log `warn` and above if the `RUST_LOG` environment variable
261336d762aSopenharmony_ci//! isn't set:
262336d762aSopenharmony_ci//!
263336d762aSopenharmony_ci//! ```
264336d762aSopenharmony_ci//! use env_logger::Env;
265336d762aSopenharmony_ci//!
266336d762aSopenharmony_ci//! env_logger::Builder::from_env(Env::default().default_filter_or("warn")).init();
267336d762aSopenharmony_ci//! ```
268336d762aSopenharmony_ci//!
269336d762aSopenharmony_ci//! [gh-repo-examples]: https://github.com/env-logger-rs/env_logger/tree/main/examples
270336d762aSopenharmony_ci//! [level-enum]: https://docs.rs/log/latest/log/enum.Level.html
271336d762aSopenharmony_ci//! [log-crate-url]: https://docs.rs/log/
272336d762aSopenharmony_ci//! [`Builder`]: struct.Builder.html
273336d762aSopenharmony_ci//! [`Builder::is_test`]: struct.Builder.html#method.is_test
274336d762aSopenharmony_ci//! [`Env`]: struct.Env.html
275336d762aSopenharmony_ci//! [`fmt`]: fmt/index.html
276336d762aSopenharmony_ci
277336d762aSopenharmony_ci#![doc(
278336d762aSopenharmony_ci    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
279336d762aSopenharmony_ci    html_favicon_url = "https://www.rust-lang.org/static/images/favicon.ico"
280336d762aSopenharmony_ci)]
281336d762aSopenharmony_ci// When compiled for the rustc compiler itself we want to make sure that this is
282336d762aSopenharmony_ci// an unstable crate
283336d762aSopenharmony_ci#![cfg_attr(rustbuild, feature(staged_api, rustc_private))]
284336d762aSopenharmony_ci#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))]
285336d762aSopenharmony_ci#![deny(missing_debug_implementations, missing_docs)]
286336d762aSopenharmony_ci
287336d762aSopenharmony_ciuse std::{borrow::Cow, cell::RefCell, env, io};
288336d762aSopenharmony_ci
289336d762aSopenharmony_ciuse log::{LevelFilter, Log, Metadata, Record, SetLoggerError};
290336d762aSopenharmony_ci
291336d762aSopenharmony_cipub mod filter;
292336d762aSopenharmony_cipub mod fmt;
293336d762aSopenharmony_ci
294336d762aSopenharmony_cipub use self::fmt::glob::*;
295336d762aSopenharmony_ci
296336d762aSopenharmony_ciuse self::filter::Filter;
297336d762aSopenharmony_ciuse self::fmt::writer::{self, Writer};
298336d762aSopenharmony_ciuse self::fmt::{FormatFn, Formatter};
299336d762aSopenharmony_ci
300336d762aSopenharmony_ci/// The default name for the environment variable to read filters from.
301336d762aSopenharmony_cipub const DEFAULT_FILTER_ENV: &str = "RUST_LOG";
302336d762aSopenharmony_ci
303336d762aSopenharmony_ci/// The default name for the environment variable to read style preferences from.
304336d762aSopenharmony_cipub const DEFAULT_WRITE_STYLE_ENV: &str = "RUST_LOG_STYLE";
305336d762aSopenharmony_ci
306336d762aSopenharmony_ci/// Set of environment variables to configure from.
307336d762aSopenharmony_ci///
308336d762aSopenharmony_ci/// # Default environment variables
309336d762aSopenharmony_ci///
310336d762aSopenharmony_ci/// By default, the `Env` will read the following environment variables:
311336d762aSopenharmony_ci///
312336d762aSopenharmony_ci/// - `RUST_LOG`: the level filter
313336d762aSopenharmony_ci/// - `RUST_LOG_STYLE`: whether or not to print styles with records.
314336d762aSopenharmony_ci///
315336d762aSopenharmony_ci/// These sources can be configured using the builder methods on `Env`.
316336d762aSopenharmony_ci#[derive(Debug)]
317336d762aSopenharmony_cipub struct Env<'a> {
318336d762aSopenharmony_ci    filter: Var<'a>,
319336d762aSopenharmony_ci    write_style: Var<'a>,
320336d762aSopenharmony_ci}
321336d762aSopenharmony_ci
322336d762aSopenharmony_ci#[derive(Debug)]
323336d762aSopenharmony_cistruct Var<'a> {
324336d762aSopenharmony_ci    name: Cow<'a, str>,
325336d762aSopenharmony_ci    default: Option<Cow<'a, str>>,
326336d762aSopenharmony_ci}
327336d762aSopenharmony_ci
328336d762aSopenharmony_ci/// The env logger.
329336d762aSopenharmony_ci///
330336d762aSopenharmony_ci/// This struct implements the `Log` trait from the [`log` crate][log-crate-url],
331336d762aSopenharmony_ci/// which allows it to act as a logger.
332336d762aSopenharmony_ci///
333336d762aSopenharmony_ci/// The [`init()`], [`try_init()`], [`Builder::init()`] and [`Builder::try_init()`]
334336d762aSopenharmony_ci/// methods will each construct a `Logger` and immediately initialize it as the
335336d762aSopenharmony_ci/// default global logger.
336336d762aSopenharmony_ci///
337336d762aSopenharmony_ci/// If you'd instead need access to the constructed `Logger`, you can use
338336d762aSopenharmony_ci/// the associated [`Builder`] and install it with the
339336d762aSopenharmony_ci/// [`log` crate][log-crate-url] directly.
340336d762aSopenharmony_ci///
341336d762aSopenharmony_ci/// [log-crate-url]: https://docs.rs/log/
342336d762aSopenharmony_ci/// [`init()`]: fn.init.html
343336d762aSopenharmony_ci/// [`try_init()`]: fn.try_init.html
344336d762aSopenharmony_ci/// [`Builder::init()`]: struct.Builder.html#method.init
345336d762aSopenharmony_ci/// [`Builder::try_init()`]: struct.Builder.html#method.try_init
346336d762aSopenharmony_ci/// [`Builder`]: struct.Builder.html
347336d762aSopenharmony_cipub struct Logger {
348336d762aSopenharmony_ci    writer: Writer,
349336d762aSopenharmony_ci    filter: Filter,
350336d762aSopenharmony_ci    format: FormatFn,
351336d762aSopenharmony_ci}
352336d762aSopenharmony_ci
353336d762aSopenharmony_ci/// `Builder` acts as builder for initializing a `Logger`.
354336d762aSopenharmony_ci///
355336d762aSopenharmony_ci/// It can be used to customize the log format, change the environment variable used
356336d762aSopenharmony_ci/// to provide the logging directives and also set the default log level filter.
357336d762aSopenharmony_ci///
358336d762aSopenharmony_ci/// # Examples
359336d762aSopenharmony_ci///
360336d762aSopenharmony_ci/// ```
361336d762aSopenharmony_ci/// # #[macro_use] extern crate log;
362336d762aSopenharmony_ci/// # use std::io::Write;
363336d762aSopenharmony_ci/// use env_logger::Builder;
364336d762aSopenharmony_ci/// use log::LevelFilter;
365336d762aSopenharmony_ci///
366336d762aSopenharmony_ci/// let mut builder = Builder::from_default_env();
367336d762aSopenharmony_ci///
368336d762aSopenharmony_ci/// builder
369336d762aSopenharmony_ci///     .format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args()))
370336d762aSopenharmony_ci///     .filter(None, LevelFilter::Info)
371336d762aSopenharmony_ci///     .init();
372336d762aSopenharmony_ci///
373336d762aSopenharmony_ci/// error!("error message");
374336d762aSopenharmony_ci/// info!("info message");
375336d762aSopenharmony_ci/// ```
376336d762aSopenharmony_ci#[derive(Default)]
377336d762aSopenharmony_cipub struct Builder {
378336d762aSopenharmony_ci    filter: filter::Builder,
379336d762aSopenharmony_ci    writer: writer::Builder,
380336d762aSopenharmony_ci    format: fmt::Builder,
381336d762aSopenharmony_ci    built: bool,
382336d762aSopenharmony_ci}
383336d762aSopenharmony_ci
384336d762aSopenharmony_ciimpl Builder {
385336d762aSopenharmony_ci    /// Initializes the log builder with defaults.
386336d762aSopenharmony_ci    ///
387336d762aSopenharmony_ci    /// **NOTE:** This method won't read from any environment variables.
388336d762aSopenharmony_ci    /// Use the [`filter`] and [`write_style`] methods to configure the builder
389336d762aSopenharmony_ci    /// or use [`from_env`] or [`from_default_env`] instead.
390336d762aSopenharmony_ci    ///
391336d762aSopenharmony_ci    /// # Examples
392336d762aSopenharmony_ci    ///
393336d762aSopenharmony_ci    /// Create a new builder and configure filters and style:
394336d762aSopenharmony_ci    ///
395336d762aSopenharmony_ci    /// ```
396336d762aSopenharmony_ci    /// use log::LevelFilter;
397336d762aSopenharmony_ci    /// use env_logger::{Builder, WriteStyle};
398336d762aSopenharmony_ci    ///
399336d762aSopenharmony_ci    /// let mut builder = Builder::new();
400336d762aSopenharmony_ci    ///
401336d762aSopenharmony_ci    /// builder
402336d762aSopenharmony_ci    ///     .filter(None, LevelFilter::Info)
403336d762aSopenharmony_ci    ///     .write_style(WriteStyle::Always)
404336d762aSopenharmony_ci    ///     .init();
405336d762aSopenharmony_ci    /// ```
406336d762aSopenharmony_ci    ///
407336d762aSopenharmony_ci    /// [`filter`]: #method.filter
408336d762aSopenharmony_ci    /// [`write_style`]: #method.write_style
409336d762aSopenharmony_ci    /// [`from_env`]: #method.from_env
410336d762aSopenharmony_ci    /// [`from_default_env`]: #method.from_default_env
411336d762aSopenharmony_ci    pub fn new() -> Builder {
412336d762aSopenharmony_ci        Default::default()
413336d762aSopenharmony_ci    }
414336d762aSopenharmony_ci
415336d762aSopenharmony_ci    /// Initializes the log builder from the environment.
416336d762aSopenharmony_ci    ///
417336d762aSopenharmony_ci    /// The variables used to read configuration from can be tweaked before
418336d762aSopenharmony_ci    /// passing in.
419336d762aSopenharmony_ci    ///
420336d762aSopenharmony_ci    /// # Examples
421336d762aSopenharmony_ci    ///
422336d762aSopenharmony_ci    /// Initialise a logger reading the log filter from an environment variable
423336d762aSopenharmony_ci    /// called `MY_LOG`:
424336d762aSopenharmony_ci    ///
425336d762aSopenharmony_ci    /// ```
426336d762aSopenharmony_ci    /// use env_logger::Builder;
427336d762aSopenharmony_ci    ///
428336d762aSopenharmony_ci    /// let mut builder = Builder::from_env("MY_LOG");
429336d762aSopenharmony_ci    /// builder.init();
430336d762aSopenharmony_ci    /// ```
431336d762aSopenharmony_ci    ///
432336d762aSopenharmony_ci    /// Initialise a logger using the `MY_LOG` variable for filtering and
433336d762aSopenharmony_ci    /// `MY_LOG_STYLE` for whether or not to write styles:
434336d762aSopenharmony_ci    ///
435336d762aSopenharmony_ci    /// ```
436336d762aSopenharmony_ci    /// use env_logger::{Builder, Env};
437336d762aSopenharmony_ci    ///
438336d762aSopenharmony_ci    /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
439336d762aSopenharmony_ci    ///
440336d762aSopenharmony_ci    /// let mut builder = Builder::from_env(env);
441336d762aSopenharmony_ci    /// builder.init();
442336d762aSopenharmony_ci    /// ```
443336d762aSopenharmony_ci    pub fn from_env<'a, E>(env: E) -> Self
444336d762aSopenharmony_ci    where
445336d762aSopenharmony_ci        E: Into<Env<'a>>,
446336d762aSopenharmony_ci    {
447336d762aSopenharmony_ci        let mut builder = Builder::new();
448336d762aSopenharmony_ci        builder.parse_env(env);
449336d762aSopenharmony_ci        builder
450336d762aSopenharmony_ci    }
451336d762aSopenharmony_ci
452336d762aSopenharmony_ci    /// Applies the configuration from the environment.
453336d762aSopenharmony_ci    ///
454336d762aSopenharmony_ci    /// This function allows a builder to be configured with default parameters,
455336d762aSopenharmony_ci    /// to be then overridden by the environment.
456336d762aSopenharmony_ci    ///
457336d762aSopenharmony_ci    /// # Examples
458336d762aSopenharmony_ci    ///
459336d762aSopenharmony_ci    /// Initialise a logger with filter level `Off`, then override the log
460336d762aSopenharmony_ci    /// filter from an environment variable called `MY_LOG`:
461336d762aSopenharmony_ci    ///
462336d762aSopenharmony_ci    /// ```
463336d762aSopenharmony_ci    /// use log::LevelFilter;
464336d762aSopenharmony_ci    /// use env_logger::Builder;
465336d762aSopenharmony_ci    ///
466336d762aSopenharmony_ci    /// let mut builder = Builder::new();
467336d762aSopenharmony_ci    ///
468336d762aSopenharmony_ci    /// builder.filter_level(LevelFilter::Off);
469336d762aSopenharmony_ci    /// builder.parse_env("MY_LOG");
470336d762aSopenharmony_ci    /// builder.init();
471336d762aSopenharmony_ci    /// ```
472336d762aSopenharmony_ci    ///
473336d762aSopenharmony_ci    /// Initialise a logger with filter level `Off`, then use the `MY_LOG`
474336d762aSopenharmony_ci    /// variable to override filtering and `MY_LOG_STYLE` to override  whether
475336d762aSopenharmony_ci    /// or not to write styles:
476336d762aSopenharmony_ci    ///
477336d762aSopenharmony_ci    /// ```
478336d762aSopenharmony_ci    /// use log::LevelFilter;
479336d762aSopenharmony_ci    /// use env_logger::{Builder, Env};
480336d762aSopenharmony_ci    ///
481336d762aSopenharmony_ci    /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
482336d762aSopenharmony_ci    ///
483336d762aSopenharmony_ci    /// let mut builder = Builder::new();
484336d762aSopenharmony_ci    /// builder.filter_level(LevelFilter::Off);
485336d762aSopenharmony_ci    /// builder.parse_env(env);
486336d762aSopenharmony_ci    /// builder.init();
487336d762aSopenharmony_ci    /// ```
488336d762aSopenharmony_ci    pub fn parse_env<'a, E>(&mut self, env: E) -> &mut Self
489336d762aSopenharmony_ci    where
490336d762aSopenharmony_ci        E: Into<Env<'a>>,
491336d762aSopenharmony_ci    {
492336d762aSopenharmony_ci        let env = env.into();
493336d762aSopenharmony_ci
494336d762aSopenharmony_ci        if let Some(s) = env.get_filter() {
495336d762aSopenharmony_ci            self.parse_filters(&s);
496336d762aSopenharmony_ci        }
497336d762aSopenharmony_ci
498336d762aSopenharmony_ci        if let Some(s) = env.get_write_style() {
499336d762aSopenharmony_ci            self.parse_write_style(&s);
500336d762aSopenharmony_ci        }
501336d762aSopenharmony_ci
502336d762aSopenharmony_ci        self
503336d762aSopenharmony_ci    }
504336d762aSopenharmony_ci
505336d762aSopenharmony_ci    /// Initializes the log builder from the environment using default variable names.
506336d762aSopenharmony_ci    ///
507336d762aSopenharmony_ci    /// This method is a convenient way to call `from_env(Env::default())` without
508336d762aSopenharmony_ci    /// having to use the `Env` type explicitly. The builder will use the
509336d762aSopenharmony_ci    /// [default environment variables].
510336d762aSopenharmony_ci    ///
511336d762aSopenharmony_ci    /// # Examples
512336d762aSopenharmony_ci    ///
513336d762aSopenharmony_ci    /// Initialise a logger using the default environment variables:
514336d762aSopenharmony_ci    ///
515336d762aSopenharmony_ci    /// ```
516336d762aSopenharmony_ci    /// use env_logger::Builder;
517336d762aSopenharmony_ci    ///
518336d762aSopenharmony_ci    /// let mut builder = Builder::from_default_env();
519336d762aSopenharmony_ci    /// builder.init();
520336d762aSopenharmony_ci    /// ```
521336d762aSopenharmony_ci    ///
522336d762aSopenharmony_ci    /// [default environment variables]: struct.Env.html#default-environment-variables
523336d762aSopenharmony_ci    pub fn from_default_env() -> Self {
524336d762aSopenharmony_ci        Self::from_env(Env::default())
525336d762aSopenharmony_ci    }
526336d762aSopenharmony_ci
527336d762aSopenharmony_ci    /// Applies the configuration from the environment using default variable names.
528336d762aSopenharmony_ci    ///
529336d762aSopenharmony_ci    /// This method is a convenient way to call `parse_env(Env::default())` without
530336d762aSopenharmony_ci    /// having to use the `Env` type explicitly. The builder will use the
531336d762aSopenharmony_ci    /// [default environment variables].
532336d762aSopenharmony_ci    ///
533336d762aSopenharmony_ci    /// # Examples
534336d762aSopenharmony_ci    ///
535336d762aSopenharmony_ci    /// Initialise a logger with filter level `Off`, then configure it using the
536336d762aSopenharmony_ci    /// default environment variables:
537336d762aSopenharmony_ci    ///
538336d762aSopenharmony_ci    /// ```
539336d762aSopenharmony_ci    /// use log::LevelFilter;
540336d762aSopenharmony_ci    /// use env_logger::Builder;
541336d762aSopenharmony_ci    ///
542336d762aSopenharmony_ci    /// let mut builder = Builder::new();
543336d762aSopenharmony_ci    /// builder.filter_level(LevelFilter::Off);
544336d762aSopenharmony_ci    /// builder.parse_default_env();
545336d762aSopenharmony_ci    /// builder.init();
546336d762aSopenharmony_ci    /// ```
547336d762aSopenharmony_ci    ///
548336d762aSopenharmony_ci    /// [default environment variables]: struct.Env.html#default-environment-variables
549336d762aSopenharmony_ci    pub fn parse_default_env(&mut self) -> &mut Self {
550336d762aSopenharmony_ci        self.parse_env(Env::default())
551336d762aSopenharmony_ci    }
552336d762aSopenharmony_ci
553336d762aSopenharmony_ci    /// Sets the format function for formatting the log output.
554336d762aSopenharmony_ci    ///
555336d762aSopenharmony_ci    /// This function is called on each record logged and should format the
556336d762aSopenharmony_ci    /// log record and output it to the given [`Formatter`].
557336d762aSopenharmony_ci    ///
558336d762aSopenharmony_ci    /// The format function is expected to output the string directly to the
559336d762aSopenharmony_ci    /// `Formatter` so that implementations can use the [`std::fmt`] macros
560336d762aSopenharmony_ci    /// to format and output without intermediate heap allocations. The default
561336d762aSopenharmony_ci    /// `env_logger` formatter takes advantage of this.
562336d762aSopenharmony_ci    ///
563336d762aSopenharmony_ci    /// # Examples
564336d762aSopenharmony_ci    ///
565336d762aSopenharmony_ci    /// Use a custom format to write only the log message:
566336d762aSopenharmony_ci    ///
567336d762aSopenharmony_ci    /// ```
568336d762aSopenharmony_ci    /// use std::io::Write;
569336d762aSopenharmony_ci    /// use env_logger::Builder;
570336d762aSopenharmony_ci    ///
571336d762aSopenharmony_ci    /// let mut builder = Builder::new();
572336d762aSopenharmony_ci    ///
573336d762aSopenharmony_ci    /// builder.format(|buf, record| writeln!(buf, "{}", record.args()));
574336d762aSopenharmony_ci    /// ```
575336d762aSopenharmony_ci    ///
576336d762aSopenharmony_ci    /// [`Formatter`]: fmt/struct.Formatter.html
577336d762aSopenharmony_ci    /// [`String`]: https://doc.rust-lang.org/stable/std/string/struct.String.html
578336d762aSopenharmony_ci    /// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html
579336d762aSopenharmony_ci    pub fn format<F: 'static>(&mut self, format: F) -> &mut Self
580336d762aSopenharmony_ci    where
581336d762aSopenharmony_ci        F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send,
582336d762aSopenharmony_ci    {
583336d762aSopenharmony_ci        self.format.custom_format = Some(Box::new(format));
584336d762aSopenharmony_ci        self
585336d762aSopenharmony_ci    }
586336d762aSopenharmony_ci
587336d762aSopenharmony_ci    /// Use the default format.
588336d762aSopenharmony_ci    ///
589336d762aSopenharmony_ci    /// This method will clear any custom format set on the builder.
590336d762aSopenharmony_ci    pub fn default_format(&mut self) -> &mut Self {
591336d762aSopenharmony_ci        self.format = Default::default();
592336d762aSopenharmony_ci        self
593336d762aSopenharmony_ci    }
594336d762aSopenharmony_ci
595336d762aSopenharmony_ci    /// Whether or not to write the level in the default format.
596336d762aSopenharmony_ci    pub fn format_level(&mut self, write: bool) -> &mut Self {
597336d762aSopenharmony_ci        self.format.format_level = write;
598336d762aSopenharmony_ci        self
599336d762aSopenharmony_ci    }
600336d762aSopenharmony_ci
601336d762aSopenharmony_ci    /// Whether or not to write the module path in the default format.
602336d762aSopenharmony_ci    pub fn format_module_path(&mut self, write: bool) -> &mut Self {
603336d762aSopenharmony_ci        self.format.format_module_path = write;
604336d762aSopenharmony_ci        self
605336d762aSopenharmony_ci    }
606336d762aSopenharmony_ci
607336d762aSopenharmony_ci    /// Whether or not to write the target in the default format.
608336d762aSopenharmony_ci    pub fn format_target(&mut self, write: bool) -> &mut Self {
609336d762aSopenharmony_ci        self.format.format_target = write;
610336d762aSopenharmony_ci        self
611336d762aSopenharmony_ci    }
612336d762aSopenharmony_ci
613336d762aSopenharmony_ci    /// Configures the amount of spaces to use to indent multiline log records.
614336d762aSopenharmony_ci    /// A value of `None` disables any kind of indentation.
615336d762aSopenharmony_ci    pub fn format_indent(&mut self, indent: Option<usize>) -> &mut Self {
616336d762aSopenharmony_ci        self.format.format_indent = indent;
617336d762aSopenharmony_ci        self
618336d762aSopenharmony_ci    }
619336d762aSopenharmony_ci
620336d762aSopenharmony_ci    /// Configures if timestamp should be included and in what precision.
621336d762aSopenharmony_ci    pub fn format_timestamp(&mut self, timestamp: Option<fmt::TimestampPrecision>) -> &mut Self {
622336d762aSopenharmony_ci        self.format.format_timestamp = timestamp;
623336d762aSopenharmony_ci        self
624336d762aSopenharmony_ci    }
625336d762aSopenharmony_ci
626336d762aSopenharmony_ci    /// Configures the timestamp to use second precision.
627336d762aSopenharmony_ci    pub fn format_timestamp_secs(&mut self) -> &mut Self {
628336d762aSopenharmony_ci        self.format_timestamp(Some(fmt::TimestampPrecision::Seconds))
629336d762aSopenharmony_ci    }
630336d762aSopenharmony_ci
631336d762aSopenharmony_ci    /// Configures the timestamp to use millisecond precision.
632336d762aSopenharmony_ci    pub fn format_timestamp_millis(&mut self) -> &mut Self {
633336d762aSopenharmony_ci        self.format_timestamp(Some(fmt::TimestampPrecision::Millis))
634336d762aSopenharmony_ci    }
635336d762aSopenharmony_ci
636336d762aSopenharmony_ci    /// Configures the timestamp to use microsecond precision.
637336d762aSopenharmony_ci    pub fn format_timestamp_micros(&mut self) -> &mut Self {
638336d762aSopenharmony_ci        self.format_timestamp(Some(fmt::TimestampPrecision::Micros))
639336d762aSopenharmony_ci    }
640336d762aSopenharmony_ci
641336d762aSopenharmony_ci    /// Configures the timestamp to use nanosecond precision.
642336d762aSopenharmony_ci    pub fn format_timestamp_nanos(&mut self) -> &mut Self {
643336d762aSopenharmony_ci        self.format_timestamp(Some(fmt::TimestampPrecision::Nanos))
644336d762aSopenharmony_ci    }
645336d762aSopenharmony_ci
646336d762aSopenharmony_ci    /// Configures the end of line suffix.
647336d762aSopenharmony_ci    pub fn format_suffix(&mut self, suffix: &'static str) -> &mut Self {
648336d762aSopenharmony_ci        self.format.format_suffix = suffix;
649336d762aSopenharmony_ci        self
650336d762aSopenharmony_ci    }
651336d762aSopenharmony_ci
652336d762aSopenharmony_ci    /// Adds a directive to the filter for a specific module.
653336d762aSopenharmony_ci    ///
654336d762aSopenharmony_ci    /// # Examples
655336d762aSopenharmony_ci    ///
656336d762aSopenharmony_ci    /// Only include messages for info and above for logs in `path::to::module`:
657336d762aSopenharmony_ci    ///
658336d762aSopenharmony_ci    /// ```
659336d762aSopenharmony_ci    /// use env_logger::Builder;
660336d762aSopenharmony_ci    /// use log::LevelFilter;
661336d762aSopenharmony_ci    ///
662336d762aSopenharmony_ci    /// let mut builder = Builder::new();
663336d762aSopenharmony_ci    ///
664336d762aSopenharmony_ci    /// builder.filter_module("path::to::module", LevelFilter::Info);
665336d762aSopenharmony_ci    /// ```
666336d762aSopenharmony_ci    pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self {
667336d762aSopenharmony_ci        self.filter.filter_module(module, level);
668336d762aSopenharmony_ci        self
669336d762aSopenharmony_ci    }
670336d762aSopenharmony_ci
671336d762aSopenharmony_ci    /// Adds a directive to the filter for all modules.
672336d762aSopenharmony_ci    ///
673336d762aSopenharmony_ci    /// # Examples
674336d762aSopenharmony_ci    ///
675336d762aSopenharmony_ci    /// Only include messages for info and above for logs globally:
676336d762aSopenharmony_ci    ///
677336d762aSopenharmony_ci    /// ```
678336d762aSopenharmony_ci    /// use env_logger::Builder;
679336d762aSopenharmony_ci    /// use log::LevelFilter;
680336d762aSopenharmony_ci    ///
681336d762aSopenharmony_ci    /// let mut builder = Builder::new();
682336d762aSopenharmony_ci    ///
683336d762aSopenharmony_ci    /// builder.filter_level(LevelFilter::Info);
684336d762aSopenharmony_ci    /// ```
685336d762aSopenharmony_ci    pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self {
686336d762aSopenharmony_ci        self.filter.filter_level(level);
687336d762aSopenharmony_ci        self
688336d762aSopenharmony_ci    }
689336d762aSopenharmony_ci
690336d762aSopenharmony_ci    /// Adds filters to the logger.
691336d762aSopenharmony_ci    ///
692336d762aSopenharmony_ci    /// The given module (if any) will log at most the specified level provided.
693336d762aSopenharmony_ci    /// If no module is provided then the filter will apply to all log messages.
694336d762aSopenharmony_ci    ///
695336d762aSopenharmony_ci    /// # Examples
696336d762aSopenharmony_ci    ///
697336d762aSopenharmony_ci    /// Only include messages for info and above for logs in `path::to::module`:
698336d762aSopenharmony_ci    ///
699336d762aSopenharmony_ci    /// ```
700336d762aSopenharmony_ci    /// use env_logger::Builder;
701336d762aSopenharmony_ci    /// use log::LevelFilter;
702336d762aSopenharmony_ci    ///
703336d762aSopenharmony_ci    /// let mut builder = Builder::new();
704336d762aSopenharmony_ci    ///
705336d762aSopenharmony_ci    /// builder.filter(Some("path::to::module"), LevelFilter::Info);
706336d762aSopenharmony_ci    /// ```
707336d762aSopenharmony_ci    pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self {
708336d762aSopenharmony_ci        self.filter.filter(module, level);
709336d762aSopenharmony_ci        self
710336d762aSopenharmony_ci    }
711336d762aSopenharmony_ci
712336d762aSopenharmony_ci    /// Parses the directives string in the same form as the `RUST_LOG`
713336d762aSopenharmony_ci    /// environment variable.
714336d762aSopenharmony_ci    ///
715336d762aSopenharmony_ci    /// See the module documentation for more details.
716336d762aSopenharmony_ci    pub fn parse_filters(&mut self, filters: &str) -> &mut Self {
717336d762aSopenharmony_ci        self.filter.parse(filters);
718336d762aSopenharmony_ci        self
719336d762aSopenharmony_ci    }
720336d762aSopenharmony_ci
721336d762aSopenharmony_ci    /// Sets the target for the log output.
722336d762aSopenharmony_ci    ///
723336d762aSopenharmony_ci    /// Env logger can log to either stdout, stderr or a custom pipe. The default is stderr.
724336d762aSopenharmony_ci    ///
725336d762aSopenharmony_ci    /// The custom pipe can be used to send the log messages to a custom sink (for example a file).
726336d762aSopenharmony_ci    /// Do note that direct writes to a file can become a bottleneck due to IO operation times.
727336d762aSopenharmony_ci    ///
728336d762aSopenharmony_ci    /// # Examples
729336d762aSopenharmony_ci    ///
730336d762aSopenharmony_ci    /// Write log message to `stdout`:
731336d762aSopenharmony_ci    ///
732336d762aSopenharmony_ci    /// ```
733336d762aSopenharmony_ci    /// use env_logger::{Builder, Target};
734336d762aSopenharmony_ci    ///
735336d762aSopenharmony_ci    /// let mut builder = Builder::new();
736336d762aSopenharmony_ci    ///
737336d762aSopenharmony_ci    /// builder.target(Target::Stdout);
738336d762aSopenharmony_ci    /// ```
739336d762aSopenharmony_ci    pub fn target(&mut self, target: fmt::Target) -> &mut Self {
740336d762aSopenharmony_ci        self.writer.target(target);
741336d762aSopenharmony_ci        self
742336d762aSopenharmony_ci    }
743336d762aSopenharmony_ci
744336d762aSopenharmony_ci    /// Sets whether or not styles will be written.
745336d762aSopenharmony_ci    ///
746336d762aSopenharmony_ci    /// This can be useful in environments that don't support control characters
747336d762aSopenharmony_ci    /// for setting colors.
748336d762aSopenharmony_ci    ///
749336d762aSopenharmony_ci    /// # Examples
750336d762aSopenharmony_ci    ///
751336d762aSopenharmony_ci    /// Never attempt to write styles:
752336d762aSopenharmony_ci    ///
753336d762aSopenharmony_ci    /// ```
754336d762aSopenharmony_ci    /// use env_logger::{Builder, WriteStyle};
755336d762aSopenharmony_ci    ///
756336d762aSopenharmony_ci    /// let mut builder = Builder::new();
757336d762aSopenharmony_ci    ///
758336d762aSopenharmony_ci    /// builder.write_style(WriteStyle::Never);
759336d762aSopenharmony_ci    /// ```
760336d762aSopenharmony_ci    pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self {
761336d762aSopenharmony_ci        self.writer.write_style(write_style);
762336d762aSopenharmony_ci        self
763336d762aSopenharmony_ci    }
764336d762aSopenharmony_ci
765336d762aSopenharmony_ci    /// Parses whether or not to write styles in the same form as the `RUST_LOG_STYLE`
766336d762aSopenharmony_ci    /// environment variable.
767336d762aSopenharmony_ci    ///
768336d762aSopenharmony_ci    /// See the module documentation for more details.
769336d762aSopenharmony_ci    pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self {
770336d762aSopenharmony_ci        self.writer.parse_write_style(write_style);
771336d762aSopenharmony_ci        self
772336d762aSopenharmony_ci    }
773336d762aSopenharmony_ci
774336d762aSopenharmony_ci    /// Sets whether or not the logger will be used in unit tests.
775336d762aSopenharmony_ci    ///
776336d762aSopenharmony_ci    /// If `is_test` is `true` then the logger will allow the testing framework to
777336d762aSopenharmony_ci    /// capture log records rather than printing them to the terminal directly.
778336d762aSopenharmony_ci    pub fn is_test(&mut self, is_test: bool) -> &mut Self {
779336d762aSopenharmony_ci        self.writer.is_test(is_test);
780336d762aSopenharmony_ci        self
781336d762aSopenharmony_ci    }
782336d762aSopenharmony_ci
783336d762aSopenharmony_ci    /// Initializes the global logger with the built env logger.
784336d762aSopenharmony_ci    ///
785336d762aSopenharmony_ci    /// This should be called early in the execution of a Rust program. Any log
786336d762aSopenharmony_ci    /// events that occur before initialization will be ignored.
787336d762aSopenharmony_ci    ///
788336d762aSopenharmony_ci    /// # Errors
789336d762aSopenharmony_ci    ///
790336d762aSopenharmony_ci    /// This function will fail if it is called more than once, or if another
791336d762aSopenharmony_ci    /// library has already initialized a global logger.
792336d762aSopenharmony_ci    pub fn try_init(&mut self) -> Result<(), SetLoggerError> {
793336d762aSopenharmony_ci        let logger = self.build();
794336d762aSopenharmony_ci
795336d762aSopenharmony_ci        let max_level = logger.filter();
796336d762aSopenharmony_ci        let r = log::set_boxed_logger(Box::new(logger));
797336d762aSopenharmony_ci
798336d762aSopenharmony_ci        if r.is_ok() {
799336d762aSopenharmony_ci            log::set_max_level(max_level);
800336d762aSopenharmony_ci        }
801336d762aSopenharmony_ci
802336d762aSopenharmony_ci        r
803336d762aSopenharmony_ci    }
804336d762aSopenharmony_ci
805336d762aSopenharmony_ci    /// Initializes the global logger with the built env logger.
806336d762aSopenharmony_ci    ///
807336d762aSopenharmony_ci    /// This should be called early in the execution of a Rust program. Any log
808336d762aSopenharmony_ci    /// events that occur before initialization will be ignored.
809336d762aSopenharmony_ci    ///
810336d762aSopenharmony_ci    /// # Panics
811336d762aSopenharmony_ci    ///
812336d762aSopenharmony_ci    /// This function will panic if it is called more than once, or if another
813336d762aSopenharmony_ci    /// library has already initialized a global logger.
814336d762aSopenharmony_ci    pub fn init(&mut self) {
815336d762aSopenharmony_ci        self.try_init()
816336d762aSopenharmony_ci            .expect("Builder::init should not be called after logger initialized");
817336d762aSopenharmony_ci    }
818336d762aSopenharmony_ci
819336d762aSopenharmony_ci    /// Build an env logger.
820336d762aSopenharmony_ci    ///
821336d762aSopenharmony_ci    /// The returned logger implements the `Log` trait and can be installed manually
822336d762aSopenharmony_ci    /// or nested within another logger.
823336d762aSopenharmony_ci    pub fn build(&mut self) -> Logger {
824336d762aSopenharmony_ci        assert!(!self.built, "attempt to re-use consumed builder");
825336d762aSopenharmony_ci        self.built = true;
826336d762aSopenharmony_ci
827336d762aSopenharmony_ci        Logger {
828336d762aSopenharmony_ci            writer: self.writer.build(),
829336d762aSopenharmony_ci            filter: self.filter.build(),
830336d762aSopenharmony_ci            format: self.format.build(),
831336d762aSopenharmony_ci        }
832336d762aSopenharmony_ci    }
833336d762aSopenharmony_ci}
834336d762aSopenharmony_ci
835336d762aSopenharmony_ciimpl Logger {
836336d762aSopenharmony_ci    /// Creates the logger from the environment.
837336d762aSopenharmony_ci    ///
838336d762aSopenharmony_ci    /// The variables used to read configuration from can be tweaked before
839336d762aSopenharmony_ci    /// passing in.
840336d762aSopenharmony_ci    ///
841336d762aSopenharmony_ci    /// # Examples
842336d762aSopenharmony_ci    ///
843336d762aSopenharmony_ci    /// Create a logger reading the log filter from an environment variable
844336d762aSopenharmony_ci    /// called `MY_LOG`:
845336d762aSopenharmony_ci    ///
846336d762aSopenharmony_ci    /// ```
847336d762aSopenharmony_ci    /// use env_logger::Logger;
848336d762aSopenharmony_ci    ///
849336d762aSopenharmony_ci    /// let logger = Logger::from_env("MY_LOG");
850336d762aSopenharmony_ci    /// ```
851336d762aSopenharmony_ci    ///
852336d762aSopenharmony_ci    /// Create a logger using the `MY_LOG` variable for filtering and
853336d762aSopenharmony_ci    /// `MY_LOG_STYLE` for whether or not to write styles:
854336d762aSopenharmony_ci    ///
855336d762aSopenharmony_ci    /// ```
856336d762aSopenharmony_ci    /// use env_logger::{Logger, Env};
857336d762aSopenharmony_ci    ///
858336d762aSopenharmony_ci    /// let env = Env::new().filter_or("MY_LOG", "info").write_style_or("MY_LOG_STYLE", "always");
859336d762aSopenharmony_ci    ///
860336d762aSopenharmony_ci    /// let logger = Logger::from_env(env);
861336d762aSopenharmony_ci    /// ```
862336d762aSopenharmony_ci    pub fn from_env<'a, E>(env: E) -> Self
863336d762aSopenharmony_ci    where
864336d762aSopenharmony_ci        E: Into<Env<'a>>,
865336d762aSopenharmony_ci    {
866336d762aSopenharmony_ci        Builder::from_env(env).build()
867336d762aSopenharmony_ci    }
868336d762aSopenharmony_ci
869336d762aSopenharmony_ci    /// Creates the logger from the environment using default variable names.
870336d762aSopenharmony_ci    ///
871336d762aSopenharmony_ci    /// This method is a convenient way to call `from_env(Env::default())` without
872336d762aSopenharmony_ci    /// having to use the `Env` type explicitly. The logger will use the
873336d762aSopenharmony_ci    /// [default environment variables].
874336d762aSopenharmony_ci    ///
875336d762aSopenharmony_ci    /// # Examples
876336d762aSopenharmony_ci    ///
877336d762aSopenharmony_ci    /// Creates a logger using the default environment variables:
878336d762aSopenharmony_ci    ///
879336d762aSopenharmony_ci    /// ```
880336d762aSopenharmony_ci    /// use env_logger::Logger;
881336d762aSopenharmony_ci    ///
882336d762aSopenharmony_ci    /// let logger = Logger::from_default_env();
883336d762aSopenharmony_ci    /// ```
884336d762aSopenharmony_ci    ///
885336d762aSopenharmony_ci    /// [default environment variables]: struct.Env.html#default-environment-variables
886336d762aSopenharmony_ci    pub fn from_default_env() -> Self {
887336d762aSopenharmony_ci        Builder::from_default_env().build()
888336d762aSopenharmony_ci    }
889336d762aSopenharmony_ci
890336d762aSopenharmony_ci    /// Returns the maximum `LevelFilter` that this env logger instance is
891336d762aSopenharmony_ci    /// configured to output.
892336d762aSopenharmony_ci    pub fn filter(&self) -> LevelFilter {
893336d762aSopenharmony_ci        self.filter.filter()
894336d762aSopenharmony_ci    }
895336d762aSopenharmony_ci
896336d762aSopenharmony_ci    /// Checks if this record matches the configured filter.
897336d762aSopenharmony_ci    pub fn matches(&self, record: &Record) -> bool {
898336d762aSopenharmony_ci        self.filter.matches(record)
899336d762aSopenharmony_ci    }
900336d762aSopenharmony_ci}
901336d762aSopenharmony_ci
902336d762aSopenharmony_ciimpl Log for Logger {
903336d762aSopenharmony_ci    fn enabled(&self, metadata: &Metadata) -> bool {
904336d762aSopenharmony_ci        self.filter.enabled(metadata)
905336d762aSopenharmony_ci    }
906336d762aSopenharmony_ci
907336d762aSopenharmony_ci    fn log(&self, record: &Record) {
908336d762aSopenharmony_ci        if self.matches(record) {
909336d762aSopenharmony_ci            // Log records are written to a thread-local buffer before being printed
910336d762aSopenharmony_ci            // to the terminal. We clear these buffers afterwards, but they aren't shrinked
911336d762aSopenharmony_ci            // so will always at least have capacity for the largest log record formatted
912336d762aSopenharmony_ci            // on that thread.
913336d762aSopenharmony_ci            //
914336d762aSopenharmony_ci            // If multiple `Logger`s are used by the same threads then the thread-local
915336d762aSopenharmony_ci            // formatter might have different color support. If this is the case the
916336d762aSopenharmony_ci            // formatter and its buffer are discarded and recreated.
917336d762aSopenharmony_ci
918336d762aSopenharmony_ci            thread_local! {
919336d762aSopenharmony_ci                static FORMATTER: RefCell<Option<Formatter>> = RefCell::new(None);
920336d762aSopenharmony_ci            }
921336d762aSopenharmony_ci
922336d762aSopenharmony_ci            let print = |formatter: &mut Formatter, record: &Record| {
923336d762aSopenharmony_ci                let _ =
924336d762aSopenharmony_ci                    (self.format)(formatter, record).and_then(|_| formatter.print(&self.writer));
925336d762aSopenharmony_ci
926336d762aSopenharmony_ci                // Always clear the buffer afterwards
927336d762aSopenharmony_ci                formatter.clear();
928336d762aSopenharmony_ci            };
929336d762aSopenharmony_ci
930336d762aSopenharmony_ci            let printed = FORMATTER
931336d762aSopenharmony_ci                .try_with(|tl_buf| {
932336d762aSopenharmony_ci                    match tl_buf.try_borrow_mut() {
933336d762aSopenharmony_ci                        // There are no active borrows of the buffer
934336d762aSopenharmony_ci                        Ok(mut tl_buf) => match *tl_buf {
935336d762aSopenharmony_ci                            // We have a previously set formatter
936336d762aSopenharmony_ci                            Some(ref mut formatter) => {
937336d762aSopenharmony_ci                                // Check the buffer style. If it's different from the logger's
938336d762aSopenharmony_ci                                // style then drop the buffer and recreate it.
939336d762aSopenharmony_ci                                if formatter.write_style() != self.writer.write_style() {
940336d762aSopenharmony_ci                                    *formatter = Formatter::new(&self.writer);
941336d762aSopenharmony_ci                                }
942336d762aSopenharmony_ci
943336d762aSopenharmony_ci                                print(formatter, record);
944336d762aSopenharmony_ci                            }
945336d762aSopenharmony_ci                            // We don't have a previously set formatter
946336d762aSopenharmony_ci                            None => {
947336d762aSopenharmony_ci                                let mut formatter = Formatter::new(&self.writer);
948336d762aSopenharmony_ci                                print(&mut formatter, record);
949336d762aSopenharmony_ci
950336d762aSopenharmony_ci                                *tl_buf = Some(formatter);
951336d762aSopenharmony_ci                            }
952336d762aSopenharmony_ci                        },
953336d762aSopenharmony_ci                        // There's already an active borrow of the buffer (due to re-entrancy)
954336d762aSopenharmony_ci                        Err(_) => {
955336d762aSopenharmony_ci                            print(&mut Formatter::new(&self.writer), record);
956336d762aSopenharmony_ci                        }
957336d762aSopenharmony_ci                    }
958336d762aSopenharmony_ci                })
959336d762aSopenharmony_ci                .is_ok();
960336d762aSopenharmony_ci
961336d762aSopenharmony_ci            if !printed {
962336d762aSopenharmony_ci                // The thread-local storage was not available (because its
963336d762aSopenharmony_ci                // destructor has already run). Create a new single-use
964336d762aSopenharmony_ci                // Formatter on the stack for this call.
965336d762aSopenharmony_ci                print(&mut Formatter::new(&self.writer), record);
966336d762aSopenharmony_ci            }
967336d762aSopenharmony_ci        }
968336d762aSopenharmony_ci    }
969336d762aSopenharmony_ci
970336d762aSopenharmony_ci    fn flush(&self) {}
971336d762aSopenharmony_ci}
972336d762aSopenharmony_ci
973336d762aSopenharmony_ciimpl<'a> Env<'a> {
974336d762aSopenharmony_ci    /// Get a default set of environment variables.
975336d762aSopenharmony_ci    pub fn new() -> Self {
976336d762aSopenharmony_ci        Self::default()
977336d762aSopenharmony_ci    }
978336d762aSopenharmony_ci
979336d762aSopenharmony_ci    /// Specify an environment variable to read the filter from.
980336d762aSopenharmony_ci    pub fn filter<E>(mut self, filter_env: E) -> Self
981336d762aSopenharmony_ci    where
982336d762aSopenharmony_ci        E: Into<Cow<'a, str>>,
983336d762aSopenharmony_ci    {
984336d762aSopenharmony_ci        self.filter = Var::new(filter_env);
985336d762aSopenharmony_ci
986336d762aSopenharmony_ci        self
987336d762aSopenharmony_ci    }
988336d762aSopenharmony_ci
989336d762aSopenharmony_ci    /// Specify an environment variable to read the filter from.
990336d762aSopenharmony_ci    ///
991336d762aSopenharmony_ci    /// If the variable is not set, the default value will be used.
992336d762aSopenharmony_ci    pub fn filter_or<E, V>(mut self, filter_env: E, default: V) -> Self
993336d762aSopenharmony_ci    where
994336d762aSopenharmony_ci        E: Into<Cow<'a, str>>,
995336d762aSopenharmony_ci        V: Into<Cow<'a, str>>,
996336d762aSopenharmony_ci    {
997336d762aSopenharmony_ci        self.filter = Var::new_with_default(filter_env, default);
998336d762aSopenharmony_ci
999336d762aSopenharmony_ci        self
1000336d762aSopenharmony_ci    }
1001336d762aSopenharmony_ci
1002336d762aSopenharmony_ci    /// Use the default environment variable to read the filter from.
1003336d762aSopenharmony_ci    ///
1004336d762aSopenharmony_ci    /// If the variable is not set, the default value will be used.
1005336d762aSopenharmony_ci    pub fn default_filter_or<V>(mut self, default: V) -> Self
1006336d762aSopenharmony_ci    where
1007336d762aSopenharmony_ci        V: Into<Cow<'a, str>>,
1008336d762aSopenharmony_ci    {
1009336d762aSopenharmony_ci        self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default);
1010336d762aSopenharmony_ci
1011336d762aSopenharmony_ci        self
1012336d762aSopenharmony_ci    }
1013336d762aSopenharmony_ci
1014336d762aSopenharmony_ci    fn get_filter(&self) -> Option<String> {
1015336d762aSopenharmony_ci        self.filter.get()
1016336d762aSopenharmony_ci    }
1017336d762aSopenharmony_ci
1018336d762aSopenharmony_ci    /// Specify an environment variable to read the style from.
1019336d762aSopenharmony_ci    pub fn write_style<E>(mut self, write_style_env: E) -> Self
1020336d762aSopenharmony_ci    where
1021336d762aSopenharmony_ci        E: Into<Cow<'a, str>>,
1022336d762aSopenharmony_ci    {
1023336d762aSopenharmony_ci        self.write_style = Var::new(write_style_env);
1024336d762aSopenharmony_ci
1025336d762aSopenharmony_ci        self
1026336d762aSopenharmony_ci    }
1027336d762aSopenharmony_ci
1028336d762aSopenharmony_ci    /// Specify an environment variable to read the style from.
1029336d762aSopenharmony_ci    ///
1030336d762aSopenharmony_ci    /// If the variable is not set, the default value will be used.
1031336d762aSopenharmony_ci    pub fn write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self
1032336d762aSopenharmony_ci    where
1033336d762aSopenharmony_ci        E: Into<Cow<'a, str>>,
1034336d762aSopenharmony_ci        V: Into<Cow<'a, str>>,
1035336d762aSopenharmony_ci    {
1036336d762aSopenharmony_ci        self.write_style = Var::new_with_default(write_style_env, default);
1037336d762aSopenharmony_ci
1038336d762aSopenharmony_ci        self
1039336d762aSopenharmony_ci    }
1040336d762aSopenharmony_ci
1041336d762aSopenharmony_ci    /// Use the default environment variable to read the style from.
1042336d762aSopenharmony_ci    ///
1043336d762aSopenharmony_ci    /// If the variable is not set, the default value will be used.
1044336d762aSopenharmony_ci    pub fn default_write_style_or<V>(mut self, default: V) -> Self
1045336d762aSopenharmony_ci    where
1046336d762aSopenharmony_ci        V: Into<Cow<'a, str>>,
1047336d762aSopenharmony_ci    {
1048336d762aSopenharmony_ci        self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default);
1049336d762aSopenharmony_ci
1050336d762aSopenharmony_ci        self
1051336d762aSopenharmony_ci    }
1052336d762aSopenharmony_ci
1053336d762aSopenharmony_ci    fn get_write_style(&self) -> Option<String> {
1054336d762aSopenharmony_ci        self.write_style.get()
1055336d762aSopenharmony_ci    }
1056336d762aSopenharmony_ci}
1057336d762aSopenharmony_ci
1058336d762aSopenharmony_ciimpl<'a> Var<'a> {
1059336d762aSopenharmony_ci    fn new<E>(name: E) -> Self
1060336d762aSopenharmony_ci    where
1061336d762aSopenharmony_ci        E: Into<Cow<'a, str>>,
1062336d762aSopenharmony_ci    {
1063336d762aSopenharmony_ci        Var {
1064336d762aSopenharmony_ci            name: name.into(),
1065336d762aSopenharmony_ci            default: None,
1066336d762aSopenharmony_ci        }
1067336d762aSopenharmony_ci    }
1068336d762aSopenharmony_ci
1069336d762aSopenharmony_ci    fn new_with_default<E, V>(name: E, default: V) -> Self
1070336d762aSopenharmony_ci    where
1071336d762aSopenharmony_ci        E: Into<Cow<'a, str>>,
1072336d762aSopenharmony_ci        V: Into<Cow<'a, str>>,
1073336d762aSopenharmony_ci    {
1074336d762aSopenharmony_ci        Var {
1075336d762aSopenharmony_ci            name: name.into(),
1076336d762aSopenharmony_ci            default: Some(default.into()),
1077336d762aSopenharmony_ci        }
1078336d762aSopenharmony_ci    }
1079336d762aSopenharmony_ci
1080336d762aSopenharmony_ci    fn get(&self) -> Option<String> {
1081336d762aSopenharmony_ci        env::var(&*self.name)
1082336d762aSopenharmony_ci            .ok()
1083336d762aSopenharmony_ci            .or_else(|| self.default.to_owned().map(|v| v.into_owned()))
1084336d762aSopenharmony_ci    }
1085336d762aSopenharmony_ci}
1086336d762aSopenharmony_ci
1087336d762aSopenharmony_ciimpl<'a, T> From<T> for Env<'a>
1088336d762aSopenharmony_ciwhere
1089336d762aSopenharmony_ci    T: Into<Cow<'a, str>>,
1090336d762aSopenharmony_ci{
1091336d762aSopenharmony_ci    fn from(filter_env: T) -> Self {
1092336d762aSopenharmony_ci        Env::default().filter(filter_env.into())
1093336d762aSopenharmony_ci    }
1094336d762aSopenharmony_ci}
1095336d762aSopenharmony_ci
1096336d762aSopenharmony_ciimpl<'a> Default for Env<'a> {
1097336d762aSopenharmony_ci    fn default() -> Self {
1098336d762aSopenharmony_ci        Env {
1099336d762aSopenharmony_ci            filter: Var::new(DEFAULT_FILTER_ENV),
1100336d762aSopenharmony_ci            write_style: Var::new(DEFAULT_WRITE_STYLE_ENV),
1101336d762aSopenharmony_ci        }
1102336d762aSopenharmony_ci    }
1103336d762aSopenharmony_ci}
1104336d762aSopenharmony_ci
1105336d762aSopenharmony_cimod std_fmt_impls {
1106336d762aSopenharmony_ci    use super::*;
1107336d762aSopenharmony_ci    use std::fmt;
1108336d762aSopenharmony_ci
1109336d762aSopenharmony_ci    impl fmt::Debug for Logger {
1110336d762aSopenharmony_ci        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1111336d762aSopenharmony_ci            f.debug_struct("Logger")
1112336d762aSopenharmony_ci                .field("filter", &self.filter)
1113336d762aSopenharmony_ci                .finish()
1114336d762aSopenharmony_ci        }
1115336d762aSopenharmony_ci    }
1116336d762aSopenharmony_ci
1117336d762aSopenharmony_ci    impl fmt::Debug for Builder {
1118336d762aSopenharmony_ci        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1119336d762aSopenharmony_ci            if self.built {
1120336d762aSopenharmony_ci                f.debug_struct("Logger").field("built", &true).finish()
1121336d762aSopenharmony_ci            } else {
1122336d762aSopenharmony_ci                f.debug_struct("Logger")
1123336d762aSopenharmony_ci                    .field("filter", &self.filter)
1124336d762aSopenharmony_ci                    .field("writer", &self.writer)
1125336d762aSopenharmony_ci                    .finish()
1126336d762aSopenharmony_ci            }
1127336d762aSopenharmony_ci        }
1128336d762aSopenharmony_ci    }
1129336d762aSopenharmony_ci}
1130336d762aSopenharmony_ci
1131336d762aSopenharmony_ci/// Attempts to initialize the global logger with an env logger.
1132336d762aSopenharmony_ci///
1133336d762aSopenharmony_ci/// This should be called early in the execution of a Rust program. Any log
1134336d762aSopenharmony_ci/// events that occur before initialization will be ignored.
1135336d762aSopenharmony_ci///
1136336d762aSopenharmony_ci/// # Errors
1137336d762aSopenharmony_ci///
1138336d762aSopenharmony_ci/// This function will fail if it is called more than once, or if another
1139336d762aSopenharmony_ci/// library has already initialized a global logger.
1140336d762aSopenharmony_cipub fn try_init() -> Result<(), SetLoggerError> {
1141336d762aSopenharmony_ci    try_init_from_env(Env::default())
1142336d762aSopenharmony_ci}
1143336d762aSopenharmony_ci
1144336d762aSopenharmony_ci/// Initializes the global logger with an env logger.
1145336d762aSopenharmony_ci///
1146336d762aSopenharmony_ci/// This should be called early in the execution of a Rust program. Any log
1147336d762aSopenharmony_ci/// events that occur before initialization will be ignored.
1148336d762aSopenharmony_ci///
1149336d762aSopenharmony_ci/// # Panics
1150336d762aSopenharmony_ci///
1151336d762aSopenharmony_ci/// This function will panic if it is called more than once, or if another
1152336d762aSopenharmony_ci/// library has already initialized a global logger.
1153336d762aSopenharmony_cipub fn init() {
1154336d762aSopenharmony_ci    try_init().expect("env_logger::init should not be called after logger initialized");
1155336d762aSopenharmony_ci}
1156336d762aSopenharmony_ci
1157336d762aSopenharmony_ci/// Attempts to initialize the global logger with an env logger from the given
1158336d762aSopenharmony_ci/// environment variables.
1159336d762aSopenharmony_ci///
1160336d762aSopenharmony_ci/// This should be called early in the execution of a Rust program. Any log
1161336d762aSopenharmony_ci/// events that occur before initialization will be ignored.
1162336d762aSopenharmony_ci///
1163336d762aSopenharmony_ci/// # Examples
1164336d762aSopenharmony_ci///
1165336d762aSopenharmony_ci/// Initialise a logger using the `MY_LOG` environment variable for filters
1166336d762aSopenharmony_ci/// and `MY_LOG_STYLE` for writing colors:
1167336d762aSopenharmony_ci///
1168336d762aSopenharmony_ci/// ```
1169336d762aSopenharmony_ci/// use env_logger::{Builder, Env};
1170336d762aSopenharmony_ci///
1171336d762aSopenharmony_ci/// # fn run() -> Result<(), Box<::std::error::Error>> {
1172336d762aSopenharmony_ci/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
1173336d762aSopenharmony_ci///
1174336d762aSopenharmony_ci/// env_logger::try_init_from_env(env)?;
1175336d762aSopenharmony_ci///
1176336d762aSopenharmony_ci/// Ok(())
1177336d762aSopenharmony_ci/// # }
1178336d762aSopenharmony_ci/// # run().unwrap();
1179336d762aSopenharmony_ci/// ```
1180336d762aSopenharmony_ci///
1181336d762aSopenharmony_ci/// # Errors
1182336d762aSopenharmony_ci///
1183336d762aSopenharmony_ci/// This function will fail if it is called more than once, or if another
1184336d762aSopenharmony_ci/// library has already initialized a global logger.
1185336d762aSopenharmony_cipub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError>
1186336d762aSopenharmony_ciwhere
1187336d762aSopenharmony_ci    E: Into<Env<'a>>,
1188336d762aSopenharmony_ci{
1189336d762aSopenharmony_ci    let mut builder = Builder::from_env(env);
1190336d762aSopenharmony_ci
1191336d762aSopenharmony_ci    builder.try_init()
1192336d762aSopenharmony_ci}
1193336d762aSopenharmony_ci
1194336d762aSopenharmony_ci/// Initializes the global logger with an env logger from the given environment
1195336d762aSopenharmony_ci/// variables.
1196336d762aSopenharmony_ci///
1197336d762aSopenharmony_ci/// This should be called early in the execution of a Rust program. Any log
1198336d762aSopenharmony_ci/// events that occur before initialization will be ignored.
1199336d762aSopenharmony_ci///
1200336d762aSopenharmony_ci/// # Examples
1201336d762aSopenharmony_ci///
1202336d762aSopenharmony_ci/// Initialise a logger using the `MY_LOG` environment variable for filters
1203336d762aSopenharmony_ci/// and `MY_LOG_STYLE` for writing colors:
1204336d762aSopenharmony_ci///
1205336d762aSopenharmony_ci/// ```
1206336d762aSopenharmony_ci/// use env_logger::{Builder, Env};
1207336d762aSopenharmony_ci///
1208336d762aSopenharmony_ci/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
1209336d762aSopenharmony_ci///
1210336d762aSopenharmony_ci/// env_logger::init_from_env(env);
1211336d762aSopenharmony_ci/// ```
1212336d762aSopenharmony_ci///
1213336d762aSopenharmony_ci/// # Panics
1214336d762aSopenharmony_ci///
1215336d762aSopenharmony_ci/// This function will panic if it is called more than once, or if another
1216336d762aSopenharmony_ci/// library has already initialized a global logger.
1217336d762aSopenharmony_cipub fn init_from_env<'a, E>(env: E)
1218336d762aSopenharmony_ciwhere
1219336d762aSopenharmony_ci    E: Into<Env<'a>>,
1220336d762aSopenharmony_ci{
1221336d762aSopenharmony_ci    try_init_from_env(env)
1222336d762aSopenharmony_ci        .expect("env_logger::init_from_env should not be called after logger initialized");
1223336d762aSopenharmony_ci}
1224336d762aSopenharmony_ci
1225336d762aSopenharmony_ci/// Create a new builder with the default environment variables.
1226336d762aSopenharmony_ci///
1227336d762aSopenharmony_ci/// The builder can be configured before being initialized.
1228336d762aSopenharmony_ci/// This is a convenient way of calling [`Builder::from_default_env`].
1229336d762aSopenharmony_ci///
1230336d762aSopenharmony_ci/// [`Builder::from_default_env`]: struct.Builder.html#method.from_default_env
1231336d762aSopenharmony_cipub fn builder() -> Builder {
1232336d762aSopenharmony_ci    Builder::from_default_env()
1233336d762aSopenharmony_ci}
1234336d762aSopenharmony_ci
1235336d762aSopenharmony_ci/// Create a builder from the given environment variables.
1236336d762aSopenharmony_ci///
1237336d762aSopenharmony_ci/// The builder can be configured before being initialized.
1238336d762aSopenharmony_ci#[deprecated(
1239336d762aSopenharmony_ci    since = "0.8.0",
1240336d762aSopenharmony_ci    note = "Prefer `env_logger::Builder::from_env()` instead."
1241336d762aSopenharmony_ci)]
1242336d762aSopenharmony_cipub fn from_env<'a, E>(env: E) -> Builder
1243336d762aSopenharmony_ciwhere
1244336d762aSopenharmony_ci    E: Into<Env<'a>>,
1245336d762aSopenharmony_ci{
1246336d762aSopenharmony_ci    Builder::from_env(env)
1247336d762aSopenharmony_ci}
1248336d762aSopenharmony_ci
1249336d762aSopenharmony_ci#[cfg(test)]
1250336d762aSopenharmony_cimod tests {
1251336d762aSopenharmony_ci    use super::*;
1252336d762aSopenharmony_ci
1253336d762aSopenharmony_ci    #[test]
1254336d762aSopenharmony_ci    fn env_get_filter_reads_from_var_if_set() {
1255336d762aSopenharmony_ci        env::set_var("env_get_filter_reads_from_var_if_set", "from var");
1256336d762aSopenharmony_ci
1257336d762aSopenharmony_ci        let env = Env::new().filter_or("env_get_filter_reads_from_var_if_set", "from default");
1258336d762aSopenharmony_ci
1259336d762aSopenharmony_ci        assert_eq!(Some("from var".to_owned()), env.get_filter());
1260336d762aSopenharmony_ci    }
1261336d762aSopenharmony_ci
1262336d762aSopenharmony_ci    #[test]
1263336d762aSopenharmony_ci    fn env_get_filter_reads_from_default_if_var_not_set() {
1264336d762aSopenharmony_ci        env::remove_var("env_get_filter_reads_from_default_if_var_not_set");
1265336d762aSopenharmony_ci
1266336d762aSopenharmony_ci        let env = Env::new().filter_or(
1267336d762aSopenharmony_ci            "env_get_filter_reads_from_default_if_var_not_set",
1268336d762aSopenharmony_ci            "from default",
1269336d762aSopenharmony_ci        );
1270336d762aSopenharmony_ci
1271336d762aSopenharmony_ci        assert_eq!(Some("from default".to_owned()), env.get_filter());
1272336d762aSopenharmony_ci    }
1273336d762aSopenharmony_ci
1274336d762aSopenharmony_ci    #[test]
1275336d762aSopenharmony_ci    fn env_get_write_style_reads_from_var_if_set() {
1276336d762aSopenharmony_ci        env::set_var("env_get_write_style_reads_from_var_if_set", "from var");
1277336d762aSopenharmony_ci
1278336d762aSopenharmony_ci        let env =
1279336d762aSopenharmony_ci            Env::new().write_style_or("env_get_write_style_reads_from_var_if_set", "from default");
1280336d762aSopenharmony_ci
1281336d762aSopenharmony_ci        assert_eq!(Some("from var".to_owned()), env.get_write_style());
1282336d762aSopenharmony_ci    }
1283336d762aSopenharmony_ci
1284336d762aSopenharmony_ci    #[test]
1285336d762aSopenharmony_ci    fn env_get_write_style_reads_from_default_if_var_not_set() {
1286336d762aSopenharmony_ci        env::remove_var("env_get_write_style_reads_from_default_if_var_not_set");
1287336d762aSopenharmony_ci
1288336d762aSopenharmony_ci        let env = Env::new().write_style_or(
1289336d762aSopenharmony_ci            "env_get_write_style_reads_from_default_if_var_not_set",
1290336d762aSopenharmony_ci            "from default",
1291336d762aSopenharmony_ci        );
1292336d762aSopenharmony_ci
1293336d762aSopenharmony_ci        assert_eq!(Some("from default".to_owned()), env.get_write_style());
1294336d762aSopenharmony_ci    }
1295336d762aSopenharmony_ci
1296336d762aSopenharmony_ci    #[test]
1297336d762aSopenharmony_ci    fn builder_parse_env_overrides_existing_filters() {
1298336d762aSopenharmony_ci        env::set_var(
1299336d762aSopenharmony_ci            "builder_parse_default_env_overrides_existing_filters",
1300336d762aSopenharmony_ci            "debug",
1301336d762aSopenharmony_ci        );
1302336d762aSopenharmony_ci        let env = Env::new().filter("builder_parse_default_env_overrides_existing_filters");
1303336d762aSopenharmony_ci
1304336d762aSopenharmony_ci        let mut builder = Builder::new();
1305336d762aSopenharmony_ci        builder.filter_level(LevelFilter::Trace);
1306336d762aSopenharmony_ci        // Overrides global level to debug
1307336d762aSopenharmony_ci        builder.parse_env(env);
1308336d762aSopenharmony_ci
1309336d762aSopenharmony_ci        assert_eq!(builder.filter.build().filter(), LevelFilter::Debug);
1310336d762aSopenharmony_ci    }
1311336d762aSopenharmony_ci}
1312