1336d762aSopenharmony_ci# env_logger
2336d762aSopenharmony_ci
3336d762aSopenharmony_ci[![crates.io](https://img.shields.io/crates/v/env_logger.svg)](https://crates.io/crates/env_logger)
4336d762aSopenharmony_ci[![Documentation](https://docs.rs/env_logger/badge.svg)](https://docs.rs/env_logger)
5336d762aSopenharmony_ci[![Documentation](https://img.shields.io/badge/docs-main-blue.svg)](https://env-logger-rs.github.io/env_logger/env_logger/index.html)
6336d762aSopenharmony_ci
7336d762aSopenharmony_ciImplements a logger that can be configured via environment variables.
8336d762aSopenharmony_ci
9336d762aSopenharmony_ci## Usage
10336d762aSopenharmony_ci
11336d762aSopenharmony_ci### In libraries
12336d762aSopenharmony_ci
13336d762aSopenharmony_ci`env_logger` makes sense when used in executables (binary projects). Libraries should use the [`log`](https://docs.rs/log) crate instead.
14336d762aSopenharmony_ci
15336d762aSopenharmony_ci### In executables
16336d762aSopenharmony_ci
17336d762aSopenharmony_ciIt must be added along with `log` to the project dependencies:
18336d762aSopenharmony_ci
19336d762aSopenharmony_ci```toml
20336d762aSopenharmony_ci[dependencies]
21336d762aSopenharmony_cilog = "0.4.0"
22336d762aSopenharmony_cienv_logger = "0.9.0"
23336d762aSopenharmony_ci```
24336d762aSopenharmony_ci
25336d762aSopenharmony_ci`env_logger` must be initialized as early as possible in the project. After it's initialized, you can use the `log` macros to do actual logging.
26336d762aSopenharmony_ci
27336d762aSopenharmony_ci```rust
28336d762aSopenharmony_ci#[macro_use]
29336d762aSopenharmony_ciextern crate log;
30336d762aSopenharmony_ci
31336d762aSopenharmony_cifn main() {
32336d762aSopenharmony_ci    env_logger::init();
33336d762aSopenharmony_ci
34336d762aSopenharmony_ci    info!("starting up");
35336d762aSopenharmony_ci
36336d762aSopenharmony_ci    // ...
37336d762aSopenharmony_ci}
38336d762aSopenharmony_ci```
39336d762aSopenharmony_ci
40336d762aSopenharmony_ciThen when running the executable, specify a value for the **`RUST_LOG`**
41336d762aSopenharmony_cienvironment variable that corresponds with the log messages you want to show.
42336d762aSopenharmony_ci
43336d762aSopenharmony_ci```bash
44336d762aSopenharmony_ci$ RUST_LOG=info ./main
45336d762aSopenharmony_ci[2018-11-03T06:09:06Z INFO  default] starting up
46336d762aSopenharmony_ci```
47336d762aSopenharmony_ci
48336d762aSopenharmony_ciThe letter case is not significant for the logging level names; e.g., `debug`,
49336d762aSopenharmony_ci`DEBUG`, and `dEbuG` all represent the same logging level. Therefore, the
50336d762aSopenharmony_ciprevious example could also have been written this way, specifying the log
51336d762aSopenharmony_cilevel as `INFO` rather than as `info`:
52336d762aSopenharmony_ci
53336d762aSopenharmony_ci```bash
54336d762aSopenharmony_ci$ RUST_LOG=INFO ./main
55336d762aSopenharmony_ci[2018-11-03T06:09:06Z INFO  default] starting up
56336d762aSopenharmony_ci```
57336d762aSopenharmony_ci
58336d762aSopenharmony_ciSo which form should you use? For consistency, our convention is to use lower
59336d762aSopenharmony_cicase names. Where our docs do use other forms, they do so in the context of
60336d762aSopenharmony_cispecific examples, so you won't be surprised if you see similar usage in the
61336d762aSopenharmony_ciwild.
62336d762aSopenharmony_ci
63336d762aSopenharmony_ciThe log levels that may be specified correspond to the [`log::Level`][level-enum]
64336d762aSopenharmony_cienum from the `log` crate. They are:
65336d762aSopenharmony_ci
66336d762aSopenharmony_ci   * `error`
67336d762aSopenharmony_ci   * `warn`
68336d762aSopenharmony_ci   * `info`
69336d762aSopenharmony_ci   * `debug`
70336d762aSopenharmony_ci   * `trace`
71336d762aSopenharmony_ci
72336d762aSopenharmony_ci[level-enum]:  https://docs.rs/log/latest/log/enum.Level.html  "log::Level (docs.rs)"
73336d762aSopenharmony_ci
74336d762aSopenharmony_ciThere is also a pseudo logging level, `off`, which may be specified to disable
75336d762aSopenharmony_ciall logging for a given module or for the entire application. As with the
76336d762aSopenharmony_cilogging levels, the letter case is not significant.
77336d762aSopenharmony_ci
78336d762aSopenharmony_ci`env_logger` can be configured in other ways besides an environment variable. See [the examples](https://github.com/env-logger-rs/env_logger/tree/main/examples) for more approaches.
79336d762aSopenharmony_ci
80336d762aSopenharmony_ci### In tests
81336d762aSopenharmony_ci
82336d762aSopenharmony_ciTests can use the `env_logger` crate to see log messages generated during that test:
83336d762aSopenharmony_ci
84336d762aSopenharmony_ci```toml
85336d762aSopenharmony_ci[dependencies]
86336d762aSopenharmony_cilog = "0.4.0"
87336d762aSopenharmony_ci
88336d762aSopenharmony_ci[dev-dependencies]
89336d762aSopenharmony_cienv_logger = "0.9.0"
90336d762aSopenharmony_ci```
91336d762aSopenharmony_ci
92336d762aSopenharmony_ci```rust
93336d762aSopenharmony_ci#[macro_use]
94336d762aSopenharmony_ciextern crate log;
95336d762aSopenharmony_ci
96336d762aSopenharmony_cifn add_one(num: i32) -> i32 {
97336d762aSopenharmony_ci    info!("add_one called with {}", num);
98336d762aSopenharmony_ci    num + 1
99336d762aSopenharmony_ci}
100336d762aSopenharmony_ci
101336d762aSopenharmony_ci#[cfg(test)]
102336d762aSopenharmony_cimod tests {
103336d762aSopenharmony_ci    use super::*;
104336d762aSopenharmony_ci
105336d762aSopenharmony_ci    fn init() {
106336d762aSopenharmony_ci        let _ = env_logger::builder().is_test(true).try_init();
107336d762aSopenharmony_ci    }
108336d762aSopenharmony_ci
109336d762aSopenharmony_ci    #[test]
110336d762aSopenharmony_ci    fn it_adds_one() {
111336d762aSopenharmony_ci        init();
112336d762aSopenharmony_ci
113336d762aSopenharmony_ci        info!("can log from the test too");
114336d762aSopenharmony_ci        assert_eq!(3, add_one(2));
115336d762aSopenharmony_ci    }
116336d762aSopenharmony_ci
117336d762aSopenharmony_ci    #[test]
118336d762aSopenharmony_ci    fn it_handles_negative_numbers() {
119336d762aSopenharmony_ci        init();
120336d762aSopenharmony_ci
121336d762aSopenharmony_ci        info!("logging from another test");
122336d762aSopenharmony_ci        assert_eq!(-7, add_one(-8));
123336d762aSopenharmony_ci    }
124336d762aSopenharmony_ci}
125336d762aSopenharmony_ci```
126336d762aSopenharmony_ci
127336d762aSopenharmony_ciAssuming the module under test is called `my_lib`, running the tests with the
128336d762aSopenharmony_ci`RUST_LOG` filtering to info messages from this module looks like:
129336d762aSopenharmony_ci
130336d762aSopenharmony_ci```bash
131336d762aSopenharmony_ci$ RUST_LOG=my_lib=info cargo test
132336d762aSopenharmony_ci     Running target/debug/my_lib-...
133336d762aSopenharmony_ci
134336d762aSopenharmony_cirunning 2 tests
135336d762aSopenharmony_ci[INFO my_lib::tests] logging from another test
136336d762aSopenharmony_ci[INFO my_lib] add_one called with -8
137336d762aSopenharmony_citest tests::it_handles_negative_numbers ... ok
138336d762aSopenharmony_ci[INFO my_lib::tests] can log from the test too
139336d762aSopenharmony_ci[INFO my_lib] add_one called with 2
140336d762aSopenharmony_citest tests::it_adds_one ... ok
141336d762aSopenharmony_ci
142336d762aSopenharmony_citest result: ok. 2 passed; 0 failed; 0 ignored; 0 measured
143336d762aSopenharmony_ci```
144336d762aSopenharmony_ci
145336d762aSopenharmony_ciNote that `env_logger::try_init()` needs to be called in each test in which you
146336d762aSopenharmony_ciwant to enable logging. Additionally, the default behavior of tests to
147336d762aSopenharmony_cirun in parallel means that logging output may be interleaved with test output.
148336d762aSopenharmony_ciEither run tests in a single thread by specifying `RUST_TEST_THREADS=1` or by
149336d762aSopenharmony_cirunning one test by specifying its name as an argument to the test binaries as
150336d762aSopenharmony_cidirected by the `cargo test` help docs:
151336d762aSopenharmony_ci
152336d762aSopenharmony_ci```bash
153336d762aSopenharmony_ci$ RUST_LOG=my_lib=info cargo test it_adds_one
154336d762aSopenharmony_ci     Running target/debug/my_lib-...
155336d762aSopenharmony_ci
156336d762aSopenharmony_cirunning 1 test
157336d762aSopenharmony_ci[INFO my_lib::tests] can log from the test too
158336d762aSopenharmony_ci[INFO my_lib] add_one called with 2
159336d762aSopenharmony_citest tests::it_adds_one ... ok
160336d762aSopenharmony_ci
161336d762aSopenharmony_citest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
162336d762aSopenharmony_ci```
163336d762aSopenharmony_ci
164336d762aSopenharmony_ci## Configuring log target
165336d762aSopenharmony_ci
166336d762aSopenharmony_ciBy default, `env_logger` logs to stderr. If you want to log to stdout instead,
167336d762aSopenharmony_ciyou can use the `Builder` to change the log target:
168336d762aSopenharmony_ci
169336d762aSopenharmony_ci```rust
170336d762aSopenharmony_ciuse std::env;
171336d762aSopenharmony_ciuse env_logger::{Builder, Target};
172336d762aSopenharmony_ci
173336d762aSopenharmony_cilet mut builder = Builder::from_default_env();
174336d762aSopenharmony_cibuilder.target(Target::Stdout);
175336d762aSopenharmony_ci
176336d762aSopenharmony_cibuilder.init();
177336d762aSopenharmony_ci```
178336d762aSopenharmony_ci
179336d762aSopenharmony_ci## Stability of the default format
180336d762aSopenharmony_ci
181336d762aSopenharmony_ciThe default format won't optimise for long-term stability, and explicitly makes no guarantees about the stability of its output across major, minor or patch version bumps during `0.x`.
182336d762aSopenharmony_ci
183336d762aSopenharmony_ciIf you want to capture or interpret the output of `env_logger` programmatically then you should use a custom format.
184