/rust/registry/src/index.crates.io-1949cf8c6b5b557f/env_logger-0.11.8/src/logger.rs
Line | Count | Source |
1 | | use std::{borrow::Cow, cell::RefCell, env, io}; |
2 | | |
3 | | use log::{LevelFilter, Log, Metadata, Record, SetLoggerError}; |
4 | | |
5 | | use crate::fmt; |
6 | | use crate::fmt::writer::{self, Writer}; |
7 | | use crate::fmt::{FormatFn, Formatter}; |
8 | | |
9 | | /// The default name for the environment variable to read filters from. |
10 | | pub const DEFAULT_FILTER_ENV: &str = "RUST_LOG"; |
11 | | |
12 | | /// The default name for the environment variable to read style preferences from. |
13 | | pub const DEFAULT_WRITE_STYLE_ENV: &str = "RUST_LOG_STYLE"; |
14 | | |
15 | | /// `Builder` acts as builder for initializing a `Logger`. |
16 | | /// |
17 | | /// It can be used to customize the log format, change the environment variable used |
18 | | /// to provide the logging directives and also set the default log level filter. |
19 | | /// |
20 | | /// # Examples |
21 | | /// |
22 | | /// ``` |
23 | | /// # use std::io::Write; |
24 | | /// use env_logger::Builder; |
25 | | /// use log::{LevelFilter, error, info}; |
26 | | /// |
27 | | /// let mut builder = Builder::from_default_env(); |
28 | | /// |
29 | | /// builder |
30 | | /// .format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args())) |
31 | | /// .filter(None, LevelFilter::Info) |
32 | | /// .init(); |
33 | | /// |
34 | | /// error!("error message"); |
35 | | /// info!("info message"); |
36 | | /// ``` |
37 | | #[derive(Default)] |
38 | | pub struct Builder { |
39 | | filter: env_filter::Builder, |
40 | | writer: writer::Builder, |
41 | | format: fmt::Builder, |
42 | | built: bool, |
43 | | } |
44 | | |
45 | | impl Builder { |
46 | | /// Initializes the log builder with defaults. |
47 | | /// |
48 | | /// **NOTE:** This method won't read from any environment variables. |
49 | | /// Use the [`filter`] and [`write_style`] methods to configure the builder |
50 | | /// or use [`from_env`] or [`from_default_env`] instead. |
51 | | /// |
52 | | /// # Examples |
53 | | /// |
54 | | /// Create a new builder and configure filters and style: |
55 | | /// |
56 | | /// ``` |
57 | | /// use log::LevelFilter; |
58 | | /// use env_logger::{Builder, WriteStyle}; |
59 | | /// |
60 | | /// let mut builder = Builder::new(); |
61 | | /// |
62 | | /// builder |
63 | | /// .filter(None, LevelFilter::Info) |
64 | | /// .write_style(WriteStyle::Always) |
65 | | /// .init(); |
66 | | /// ``` |
67 | | /// |
68 | | /// [`filter`]: #method.filter |
69 | | /// [`write_style`]: #method.write_style |
70 | | /// [`from_env`]: #method.from_env |
71 | | /// [`from_default_env`]: #method.from_default_env |
72 | 4 | pub fn new() -> Builder { |
73 | 4 | Default::default() |
74 | 4 | } |
75 | | |
76 | | /// Initializes the log builder from the environment. |
77 | | /// |
78 | | /// The variables used to read configuration from can be tweaked before |
79 | | /// passing in. |
80 | | /// |
81 | | /// # Examples |
82 | | /// |
83 | | /// Initialise a logger reading the log filter from an environment variable |
84 | | /// called `MY_LOG`: |
85 | | /// |
86 | | /// ``` |
87 | | /// use env_logger::Builder; |
88 | | /// |
89 | | /// let mut builder = Builder::from_env("MY_LOG"); |
90 | | /// builder.init(); |
91 | | /// ``` |
92 | | /// |
93 | | /// Initialise a logger using the `MY_LOG` variable for filtering and |
94 | | /// `MY_LOG_STYLE` for whether or not to write styles: |
95 | | /// |
96 | | /// ``` |
97 | | /// use env_logger::{Builder, Env}; |
98 | | /// |
99 | | /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); |
100 | | /// |
101 | | /// let mut builder = Builder::from_env(env); |
102 | | /// builder.init(); |
103 | | /// ``` |
104 | 4 | pub fn from_env<'a, E>(env: E) -> Self |
105 | 4 | where |
106 | 4 | E: Into<Env<'a>>, |
107 | | { |
108 | 4 | let mut builder = Builder::new(); |
109 | 4 | builder.parse_env(env); |
110 | 4 | builder |
111 | 4 | } |
112 | | |
113 | | /// Applies the configuration from the environment. |
114 | | /// |
115 | | /// This function allows a builder to be configured with default parameters, |
116 | | /// to be then overridden by the environment. |
117 | | /// |
118 | | /// # Examples |
119 | | /// |
120 | | /// Initialise a logger with filter level `Off`, then override the log |
121 | | /// filter from an environment variable called `MY_LOG`: |
122 | | /// |
123 | | /// ``` |
124 | | /// use log::LevelFilter; |
125 | | /// use env_logger::Builder; |
126 | | /// |
127 | | /// let mut builder = Builder::new(); |
128 | | /// |
129 | | /// builder.filter_level(LevelFilter::Off); |
130 | | /// builder.parse_env("MY_LOG"); |
131 | | /// builder.init(); |
132 | | /// ``` |
133 | | /// |
134 | | /// Initialise a logger with filter level `Off`, then use the `MY_LOG` |
135 | | /// variable to override filtering and `MY_LOG_STYLE` to override whether |
136 | | /// or not to write styles: |
137 | | /// |
138 | | /// ``` |
139 | | /// use log::LevelFilter; |
140 | | /// use env_logger::{Builder, Env}; |
141 | | /// |
142 | | /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); |
143 | | /// |
144 | | /// let mut builder = Builder::new(); |
145 | | /// builder.filter_level(LevelFilter::Off); |
146 | | /// builder.parse_env(env); |
147 | | /// builder.init(); |
148 | | /// ``` |
149 | 4 | pub fn parse_env<'a, E>(&mut self, env: E) -> &mut Self |
150 | 4 | where |
151 | 4 | E: Into<Env<'a>>, |
152 | | { |
153 | 4 | let env = env.into(); |
154 | | |
155 | 4 | if let Some(s) = env.get_filter() { |
156 | 0 | self.parse_filters(&s); |
157 | 4 | } |
158 | | |
159 | 4 | if let Some(s) = env.get_write_style() { |
160 | 0 | self.parse_write_style(&s); |
161 | 4 | } |
162 | | |
163 | 4 | self |
164 | 4 | } |
165 | | |
166 | | /// Initializes the log builder from the environment using default variable names. |
167 | | /// |
168 | | /// This method is a convenient way to call `from_env(Env::default())` without |
169 | | /// having to use the `Env` type explicitly. The builder will use the |
170 | | /// [default environment variables]. |
171 | | /// |
172 | | /// # Examples |
173 | | /// |
174 | | /// Initialise a logger using the default environment variables: |
175 | | /// |
176 | | /// ``` |
177 | | /// use env_logger::Builder; |
178 | | /// |
179 | | /// let mut builder = Builder::from_default_env(); |
180 | | /// builder.init(); |
181 | | /// ``` |
182 | | /// |
183 | | /// [default environment variables]: struct.Env.html#default-environment-variables |
184 | 4 | pub fn from_default_env() -> Self { |
185 | 4 | Self::from_env(Env::default()) |
186 | 4 | } |
187 | | |
188 | | /// Applies the configuration from the environment using default variable names. |
189 | | /// |
190 | | /// This method is a convenient way to call `parse_env(Env::default())` without |
191 | | /// having to use the `Env` type explicitly. The builder will use the |
192 | | /// [default environment variables]. |
193 | | /// |
194 | | /// # Examples |
195 | | /// |
196 | | /// Initialise a logger with filter level `Off`, then configure it using the |
197 | | /// default environment variables: |
198 | | /// |
199 | | /// ``` |
200 | | /// use log::LevelFilter; |
201 | | /// use env_logger::Builder; |
202 | | /// |
203 | | /// let mut builder = Builder::new(); |
204 | | /// builder.filter_level(LevelFilter::Off); |
205 | | /// builder.parse_default_env(); |
206 | | /// builder.init(); |
207 | | /// ``` |
208 | | /// |
209 | | /// [default environment variables]: struct.Env.html#default-environment-variables |
210 | 0 | pub fn parse_default_env(&mut self) -> &mut Self { |
211 | 0 | self.parse_env(Env::default()) |
212 | 0 | } |
213 | | |
214 | | /// Sets the format function for formatting the log output. |
215 | | /// |
216 | | /// This function is called on each record logged and should format the |
217 | | /// log record and output it to the given [`Formatter`]. |
218 | | /// |
219 | | /// The format function is expected to output the string directly to the |
220 | | /// `Formatter` so that implementations can use the [`std::fmt`] macros |
221 | | /// to format and output without intermediate heap allocations. The default |
222 | | /// `env_logger` formatter takes advantage of this. |
223 | | /// |
224 | | /// When the `color` feature is enabled, styling via ANSI escape codes is supported and the |
225 | | /// output will automatically respect [`Builder::write_style`]. |
226 | | /// |
227 | | /// # Examples |
228 | | /// |
229 | | /// Use a custom format to write only the log message: |
230 | | /// |
231 | | /// ``` |
232 | | /// use std::io::Write; |
233 | | /// use env_logger::Builder; |
234 | | /// |
235 | | /// let mut builder = Builder::new(); |
236 | | /// |
237 | | /// builder.format(|buf, record| writeln!(buf, "{}", record.args())); |
238 | | /// ``` |
239 | | /// |
240 | | /// [`Formatter`]: fmt/struct.Formatter.html |
241 | | /// [`String`]: https://doc.rust-lang.org/stable/std/string/struct.String.html |
242 | | /// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html |
243 | 0 | pub fn format<F>(&mut self, format: F) -> &mut Self |
244 | 0 | where |
245 | 0 | F: Fn(&mut Formatter, &Record<'_>) -> io::Result<()> + Sync + Send + 'static, |
246 | | { |
247 | 0 | self.format.custom_format = Some(Box::new(format)); |
248 | 0 | self |
249 | 0 | } |
250 | | |
251 | | /// Use the default format. |
252 | | /// |
253 | | /// This method will clear any custom format set on the builder. |
254 | 0 | pub fn default_format(&mut self) -> &mut Self { |
255 | 0 | self.format = Default::default(); |
256 | 0 | self |
257 | 0 | } |
258 | | |
259 | | /// Whether or not to write the level in the default format. |
260 | 0 | pub fn format_level(&mut self, write: bool) -> &mut Self { |
261 | 0 | self.format.default_format.level(write); |
262 | 0 | self |
263 | 0 | } |
264 | | |
265 | | /// Whether or not to write the source file path in the default format. |
266 | 0 | pub fn format_file(&mut self, write: bool) -> &mut Self { |
267 | 0 | self.format.default_format.file(write); |
268 | 0 | self |
269 | 0 | } |
270 | | |
271 | | /// Whether or not to write the source line number path in the default format. |
272 | | /// |
273 | | /// Only has effect if `format_file` is also enabled |
274 | 0 | pub fn format_line_number(&mut self, write: bool) -> &mut Self { |
275 | 0 | self.format.default_format.line_number(write); |
276 | 0 | self |
277 | 0 | } |
278 | | |
279 | | /// Whether or not to write the source path and line number |
280 | | /// |
281 | | /// Equivalent to calling both `format_file` and `format_line_number` |
282 | | /// with `true` |
283 | 0 | pub fn format_source_path(&mut self, write: bool) -> &mut Self { |
284 | 0 | self.format_file(write).format_line_number(write); |
285 | 0 | self |
286 | 0 | } |
287 | | |
288 | | /// Whether or not to write the module path in the default format. |
289 | 0 | pub fn format_module_path(&mut self, write: bool) -> &mut Self { |
290 | 0 | self.format.default_format.module_path(write); |
291 | 0 | self |
292 | 0 | } |
293 | | |
294 | | /// Whether or not to write the target in the default format. |
295 | 0 | pub fn format_target(&mut self, write: bool) -> &mut Self { |
296 | 0 | self.format.default_format.target(write); |
297 | 0 | self |
298 | 0 | } |
299 | | |
300 | | /// Configures the amount of spaces to use to indent multiline log records. |
301 | | /// A value of `None` disables any kind of indentation. |
302 | 0 | pub fn format_indent(&mut self, indent: Option<usize>) -> &mut Self { |
303 | 0 | self.format.default_format.indent(indent); |
304 | 0 | self |
305 | 0 | } |
306 | | |
307 | | /// Configures if timestamp should be included and in what precision. |
308 | 4 | pub fn format_timestamp(&mut self, timestamp: Option<fmt::TimestampPrecision>) -> &mut Self { |
309 | 4 | self.format.default_format.timestamp(timestamp); |
310 | 4 | self |
311 | 4 | } |
312 | | |
313 | | /// Configures the timestamp to use second precision. |
314 | 0 | pub fn format_timestamp_secs(&mut self) -> &mut Self { |
315 | 0 | self.format_timestamp(Some(fmt::TimestampPrecision::Seconds)) |
316 | 0 | } |
317 | | |
318 | | /// Configures the timestamp to use millisecond precision. |
319 | 0 | pub fn format_timestamp_millis(&mut self) -> &mut Self { |
320 | 0 | self.format_timestamp(Some(fmt::TimestampPrecision::Millis)) |
321 | 0 | } |
322 | | |
323 | | /// Configures the timestamp to use microsecond precision. |
324 | 0 | pub fn format_timestamp_micros(&mut self) -> &mut Self { |
325 | 0 | self.format_timestamp(Some(fmt::TimestampPrecision::Micros)) |
326 | 0 | } |
327 | | |
328 | | /// Configures the timestamp to use nanosecond precision. |
329 | 4 | pub fn format_timestamp_nanos(&mut self) -> &mut Self { |
330 | 4 | self.format_timestamp(Some(fmt::TimestampPrecision::Nanos)) |
331 | 4 | } |
332 | | |
333 | | /// Configures the end of line suffix. |
334 | 0 | pub fn format_suffix(&mut self, suffix: &'static str) -> &mut Self { |
335 | 0 | self.format.default_format.suffix(suffix); |
336 | 0 | self |
337 | 0 | } |
338 | | |
339 | | /// Set the format for structured key/value pairs in the log record |
340 | | /// |
341 | | /// With the default format, this function is called for each record and should format |
342 | | /// the structured key-value pairs as returned by [`log::Record::key_values`]. |
343 | | /// |
344 | | /// The format function is expected to output the string directly to the `Formatter` so that |
345 | | /// implementations can use the [`std::fmt`] macros, similar to the main format function. |
346 | | /// |
347 | | /// The default format uses a space to separate each key-value pair, with an "=" between |
348 | | /// the key and value. |
349 | | #[cfg(feature = "kv")] |
350 | | pub fn format_key_values<F>(&mut self, format: F) -> &mut Self |
351 | | where |
352 | | F: Fn(&mut Formatter, &dyn log::kv::Source) -> io::Result<()> + Sync + Send + 'static, |
353 | | { |
354 | | self.format.default_format.key_values(format); |
355 | | self |
356 | | } |
357 | | |
358 | | /// Adds a directive to the filter for a specific module. |
359 | | /// |
360 | | /// # Examples |
361 | | /// |
362 | | /// Only include messages for info and above for logs in `path::to::module`: |
363 | | /// |
364 | | /// ``` |
365 | | /// use env_logger::Builder; |
366 | | /// use log::LevelFilter; |
367 | | /// |
368 | | /// let mut builder = Builder::new(); |
369 | | /// |
370 | | /// builder.filter_module("path::to::module", LevelFilter::Info); |
371 | | /// ``` |
372 | 0 | pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self { |
373 | 0 | self.filter.filter_module(module, level); |
374 | 0 | self |
375 | 0 | } |
376 | | |
377 | | /// Adds a directive to the filter for all modules. |
378 | | /// |
379 | | /// # Examples |
380 | | /// |
381 | | /// Only include messages for info and above for logs globally: |
382 | | /// |
383 | | /// ``` |
384 | | /// use env_logger::Builder; |
385 | | /// use log::LevelFilter; |
386 | | /// |
387 | | /// let mut builder = Builder::new(); |
388 | | /// |
389 | | /// builder.filter_level(LevelFilter::Info); |
390 | | /// ``` |
391 | 0 | pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self { |
392 | 0 | self.filter.filter_level(level); |
393 | 0 | self |
394 | 0 | } |
395 | | |
396 | | /// Adds filters to the logger. |
397 | | /// |
398 | | /// The given module (if any) will log at most the specified level provided. |
399 | | /// If no module is provided then the filter will apply to all log messages. |
400 | | /// |
401 | | /// # Examples |
402 | | /// |
403 | | /// Only include messages for info and above for logs in `path::to::module`: |
404 | | /// |
405 | | /// ``` |
406 | | /// use env_logger::Builder; |
407 | | /// use log::LevelFilter; |
408 | | /// |
409 | | /// let mut builder = Builder::new(); |
410 | | /// |
411 | | /// builder.filter(Some("path::to::module"), LevelFilter::Info); |
412 | | /// ``` |
413 | 0 | pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self { |
414 | 0 | self.filter.filter(module, level); |
415 | 0 | self |
416 | 0 | } |
417 | | |
418 | | /// Parses the directives string in the same form as the `RUST_LOG` |
419 | | /// environment variable. |
420 | | /// |
421 | | /// See the module documentation for more details. |
422 | 0 | pub fn parse_filters(&mut self, filters: &str) -> &mut Self { |
423 | 0 | self.filter.parse(filters); |
424 | 0 | self |
425 | 0 | } |
426 | | |
427 | | /// Sets the target for the log output. |
428 | | /// |
429 | | /// Env logger can log to either stdout, stderr or a custom pipe. The default is stderr. |
430 | | /// |
431 | | /// The custom pipe can be used to send the log messages to a custom sink (for example a file). |
432 | | /// Do note that direct writes to a file can become a bottleneck due to IO operation times. |
433 | | /// |
434 | | /// # Examples |
435 | | /// |
436 | | /// Write log message to `stdout`: |
437 | | /// |
438 | | /// ``` |
439 | | /// use env_logger::{Builder, Target}; |
440 | | /// |
441 | | /// let mut builder = Builder::new(); |
442 | | /// |
443 | | /// builder.target(Target::Stdout); |
444 | | /// ``` |
445 | 0 | pub fn target(&mut self, target: fmt::Target) -> &mut Self { |
446 | 0 | self.writer.target(target); |
447 | 0 | self |
448 | 0 | } |
449 | | |
450 | | /// Sets whether or not styles will be written. |
451 | | /// |
452 | | /// This can be useful in environments that don't support control characters |
453 | | /// for setting colors. |
454 | | /// |
455 | | /// # Examples |
456 | | /// |
457 | | /// Never attempt to write styles: |
458 | | /// |
459 | | /// ``` |
460 | | /// use env_logger::{Builder, WriteStyle}; |
461 | | /// |
462 | | /// let mut builder = Builder::new(); |
463 | | /// |
464 | | /// builder.write_style(WriteStyle::Never); |
465 | | /// ``` |
466 | 0 | pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self { |
467 | 0 | self.writer.write_style(write_style); |
468 | 0 | self |
469 | 0 | } |
470 | | |
471 | | /// Parses whether or not to write styles in the same form as the `RUST_LOG_STYLE` |
472 | | /// environment variable. |
473 | | /// |
474 | | /// See the module documentation for more details. |
475 | 0 | pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self { |
476 | 0 | self.writer.parse_write_style(write_style); |
477 | 0 | self |
478 | 0 | } |
479 | | |
480 | | /// Sets whether or not the logger will be used in unit tests. |
481 | | /// |
482 | | /// If `is_test` is `true` then the logger will allow the testing framework to |
483 | | /// capture log records rather than printing them to the terminal directly. |
484 | 0 | pub fn is_test(&mut self, is_test: bool) -> &mut Self { |
485 | 0 | self.writer.is_test(is_test); |
486 | 0 | self |
487 | 0 | } |
488 | | |
489 | | /// Initializes the global logger with the built env logger. |
490 | | /// |
491 | | /// This should be called early in the execution of a Rust program. Any log |
492 | | /// events that occur before initialization will be ignored. |
493 | | /// |
494 | | /// # Errors |
495 | | /// |
496 | | /// This function will fail if it is called more than once, or if another |
497 | | /// library has already initialized a global logger. |
498 | 4 | pub fn try_init(&mut self) -> Result<(), SetLoggerError> { |
499 | 4 | let logger = self.build(); |
500 | | |
501 | 4 | let max_level = logger.filter(); |
502 | 4 | let r = log::set_boxed_logger(Box::new(logger)); |
503 | | |
504 | 4 | if r.is_ok() { |
505 | 4 | log::set_max_level(max_level); |
506 | 4 | } |
507 | | |
508 | 4 | r |
509 | 4 | } |
510 | | |
511 | | /// Initializes the global logger with the built env logger. |
512 | | /// |
513 | | /// This should be called early in the execution of a Rust program. Any log |
514 | | /// events that occur before initialization will be ignored. |
515 | | /// |
516 | | /// # Panics |
517 | | /// |
518 | | /// This function will panic if it is called more than once, or if another |
519 | | /// library has already initialized a global logger. |
520 | 4 | pub fn init(&mut self) { |
521 | 4 | self.try_init() |
522 | 4 | .expect("Builder::init should not be called after logger initialized"); |
523 | 4 | } |
524 | | |
525 | | /// Build an env logger. |
526 | | /// |
527 | | /// The returned logger implements the `Log` trait and can be installed manually |
528 | | /// or nested within another logger. |
529 | 4 | pub fn build(&mut self) -> Logger { |
530 | 4 | assert!(!self.built, "attempt to re-use consumed builder"); |
531 | 4 | self.built = true; |
532 | | |
533 | 4 | Logger { |
534 | 4 | writer: self.writer.build(), |
535 | 4 | filter: self.filter.build(), |
536 | 4 | format: self.format.build(), |
537 | 4 | } |
538 | 4 | } |
539 | | } |
540 | | |
541 | | impl std::fmt::Debug for Builder { |
542 | 0 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
543 | 0 | if self.built { |
544 | 0 | f.debug_struct("Logger").field("built", &true).finish() |
545 | | } else { |
546 | 0 | f.debug_struct("Logger") |
547 | 0 | .field("filter", &self.filter) |
548 | 0 | .field("writer", &self.writer) |
549 | 0 | .finish() |
550 | | } |
551 | 0 | } |
552 | | } |
553 | | |
554 | | /// The env logger. |
555 | | /// |
556 | | /// This struct implements the `Log` trait from the [`log` crate][log-crate-url], |
557 | | /// which allows it to act as a logger. |
558 | | /// |
559 | | /// The [`init()`], [`try_init()`], [`Builder::init()`] and [`Builder::try_init()`] |
560 | | /// methods will each construct a `Logger` and immediately initialize it as the |
561 | | /// default global logger. |
562 | | /// |
563 | | /// If you'd instead need access to the constructed `Logger`, you can use |
564 | | /// the associated [`Builder`] and install it with the |
565 | | /// [`log` crate][log-crate-url] directly. |
566 | | /// |
567 | | /// [log-crate-url]: https://docs.rs/log |
568 | | /// [`init()`]: fn.init.html |
569 | | /// [`try_init()`]: fn.try_init.html |
570 | | /// [`Builder::init()`]: struct.Builder.html#method.init |
571 | | /// [`Builder::try_init()`]: struct.Builder.html#method.try_init |
572 | | /// [`Builder`]: struct.Builder.html |
573 | | pub struct Logger { |
574 | | writer: Writer, |
575 | | filter: env_filter::Filter, |
576 | | format: FormatFn, |
577 | | } |
578 | | |
579 | | impl Logger { |
580 | | /// Creates the logger from the environment. |
581 | | /// |
582 | | /// The variables used to read configuration from can be tweaked before |
583 | | /// passing in. |
584 | | /// |
585 | | /// # Examples |
586 | | /// |
587 | | /// Create a logger reading the log filter from an environment variable |
588 | | /// called `MY_LOG`: |
589 | | /// |
590 | | /// ``` |
591 | | /// use env_logger::Logger; |
592 | | /// |
593 | | /// let logger = Logger::from_env("MY_LOG"); |
594 | | /// ``` |
595 | | /// |
596 | | /// Create a logger using the `MY_LOG` variable for filtering and |
597 | | /// `MY_LOG_STYLE` for whether or not to write styles: |
598 | | /// |
599 | | /// ``` |
600 | | /// use env_logger::{Logger, Env}; |
601 | | /// |
602 | | /// let env = Env::new().filter_or("MY_LOG", "info").write_style_or("MY_LOG_STYLE", "always"); |
603 | | /// |
604 | | /// let logger = Logger::from_env(env); |
605 | | /// ``` |
606 | 0 | pub fn from_env<'a, E>(env: E) -> Self |
607 | 0 | where |
608 | 0 | E: Into<Env<'a>>, |
609 | | { |
610 | 0 | Builder::from_env(env).build() |
611 | 0 | } |
612 | | |
613 | | /// Creates the logger from the environment using default variable names. |
614 | | /// |
615 | | /// This method is a convenient way to call `from_env(Env::default())` without |
616 | | /// having to use the `Env` type explicitly. The logger will use the |
617 | | /// [default environment variables]. |
618 | | /// |
619 | | /// # Examples |
620 | | /// |
621 | | /// Creates a logger using the default environment variables: |
622 | | /// |
623 | | /// ``` |
624 | | /// use env_logger::Logger; |
625 | | /// |
626 | | /// let logger = Logger::from_default_env(); |
627 | | /// ``` |
628 | | /// |
629 | | /// [default environment variables]: struct.Env.html#default-environment-variables |
630 | 0 | pub fn from_default_env() -> Self { |
631 | 0 | Builder::from_default_env().build() |
632 | 0 | } |
633 | | |
634 | | /// Returns the maximum `LevelFilter` that this env logger instance is |
635 | | /// configured to output. |
636 | 4 | pub fn filter(&self) -> LevelFilter { |
637 | 4 | self.filter.filter() |
638 | 4 | } |
639 | | |
640 | | /// Checks if this record matches the configured filter. |
641 | 0 | pub fn matches(&self, record: &Record<'_>) -> bool { |
642 | 0 | self.filter.matches(record) |
643 | 0 | } |
644 | | } |
645 | | |
646 | | impl Log for Logger { |
647 | 0 | fn enabled(&self, metadata: &Metadata<'_>) -> bool { |
648 | 0 | self.filter.enabled(metadata) |
649 | 0 | } |
650 | | |
651 | 0 | fn log(&self, record: &Record<'_>) { |
652 | 0 | if self.matches(record) { |
653 | | // Log records are written to a thread-local buffer before being printed |
654 | | // to the terminal. We clear these buffers afterwards, but they aren't shrunk |
655 | | // so will always at least have capacity for the largest log record formatted |
656 | | // on that thread. |
657 | | // |
658 | | // If multiple `Logger`s are used by the same threads then the thread-local |
659 | | // formatter might have different color support. If this is the case the |
660 | | // formatter and its buffer are discarded and recreated. |
661 | | |
662 | | thread_local! { |
663 | | static FORMATTER: RefCell<Option<Formatter>> = const { RefCell::new(None) }; |
664 | | } |
665 | | |
666 | 0 | let print = |formatter: &mut Formatter, record: &Record<'_>| { |
667 | 0 | let _ = self |
668 | 0 | .format |
669 | 0 | .format(formatter, record) |
670 | 0 | .and_then(|_| formatter.print(&self.writer)); |
671 | | |
672 | | // Always clear the buffer afterwards |
673 | 0 | formatter.clear(); |
674 | 0 | }; |
675 | | |
676 | 0 | let printed = FORMATTER |
677 | 0 | .try_with(|tl_buf| { |
678 | 0 | if let Ok(mut tl_buf) = tl_buf.try_borrow_mut() { |
679 | | // There are no active borrows of the buffer |
680 | 0 | if let Some(ref mut formatter) = *tl_buf { |
681 | | // We have a previously set formatter |
682 | | |
683 | | // Check the buffer style. If it's different from the logger's |
684 | | // style then drop the buffer and recreate it. |
685 | 0 | if formatter.write_style() != self.writer.write_style() { |
686 | 0 | *formatter = Formatter::new(&self.writer); |
687 | 0 | } |
688 | | |
689 | 0 | print(formatter, record); |
690 | 0 | } else { |
691 | 0 | // We don't have a previously set formatter |
692 | 0 | let mut formatter = Formatter::new(&self.writer); |
693 | 0 | print(&mut formatter, record); |
694 | 0 |
|
695 | 0 | *tl_buf = Some(formatter); |
696 | 0 | } |
697 | 0 | } else { |
698 | 0 | // There's already an active borrow of the buffer (due to re-entrancy) |
699 | 0 | print(&mut Formatter::new(&self.writer), record); |
700 | 0 | } |
701 | 0 | }) |
702 | 0 | .is_ok(); |
703 | | |
704 | 0 | if !printed { |
705 | 0 | // The thread-local storage was not available (because its |
706 | 0 | // destructor has already run). Create a new single-use |
707 | 0 | // Formatter on the stack for this call. |
708 | 0 | print(&mut Formatter::new(&self.writer), record); |
709 | 0 | } |
710 | 0 | } |
711 | 0 | } |
712 | | |
713 | 0 | fn flush(&self) {} |
714 | | } |
715 | | |
716 | | impl std::fmt::Debug for Logger { |
717 | 0 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
718 | 0 | f.debug_struct("Logger") |
719 | 0 | .field("filter", &self.filter) |
720 | 0 | .finish() |
721 | 0 | } |
722 | | } |
723 | | |
724 | | /// Set of environment variables to configure from. |
725 | | /// |
726 | | /// # Default environment variables |
727 | | /// |
728 | | /// By default, the `Env` will read the following environment variables: |
729 | | /// |
730 | | /// - `RUST_LOG`: the level filter |
731 | | /// - `RUST_LOG_STYLE`: whether or not to print styles with records. |
732 | | /// |
733 | | /// These sources can be configured using the builder methods on `Env`. |
734 | | #[derive(Debug)] |
735 | | pub struct Env<'a> { |
736 | | filter: Var<'a>, |
737 | | write_style: Var<'a>, |
738 | | } |
739 | | |
740 | | impl<'a> Env<'a> { |
741 | | /// Get a default set of environment variables. |
742 | 0 | pub fn new() -> Self { |
743 | 0 | Self::default() |
744 | 0 | } |
745 | | |
746 | | /// Specify an environment variable to read the filter from. |
747 | 0 | pub fn filter<E>(mut self, filter_env: E) -> Self |
748 | 0 | where |
749 | 0 | E: Into<Cow<'a, str>>, |
750 | | { |
751 | 0 | self.filter = Var::new(filter_env); |
752 | | |
753 | 0 | self |
754 | 0 | } |
755 | | |
756 | | /// Specify an environment variable to read the filter from. |
757 | | /// |
758 | | /// If the variable is not set, the default value will be used. |
759 | 0 | pub fn filter_or<E, V>(mut self, filter_env: E, default: V) -> Self |
760 | 0 | where |
761 | 0 | E: Into<Cow<'a, str>>, |
762 | 0 | V: Into<Cow<'a, str>>, |
763 | | { |
764 | 0 | self.filter = Var::new_with_default(filter_env, default); |
765 | | |
766 | 0 | self |
767 | 0 | } |
768 | | |
769 | | /// Use the default environment variable to read the filter from. |
770 | | /// |
771 | | /// If the variable is not set, the default value will be used. |
772 | 0 | pub fn default_filter_or<V>(mut self, default: V) -> Self |
773 | 0 | where |
774 | 0 | V: Into<Cow<'a, str>>, |
775 | | { |
776 | 0 | self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default); |
777 | | |
778 | 0 | self |
779 | 0 | } |
780 | | |
781 | 4 | fn get_filter(&self) -> Option<String> { |
782 | 4 | self.filter.get() |
783 | 4 | } |
784 | | |
785 | | /// Specify an environment variable to read the style from. |
786 | 0 | pub fn write_style<E>(mut self, write_style_env: E) -> Self |
787 | 0 | where |
788 | 0 | E: Into<Cow<'a, str>>, |
789 | | { |
790 | 0 | self.write_style = Var::new(write_style_env); |
791 | | |
792 | 0 | self |
793 | 0 | } |
794 | | |
795 | | /// Specify an environment variable to read the style from. |
796 | | /// |
797 | | /// If the variable is not set, the default value will be used. |
798 | 0 | pub fn write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self |
799 | 0 | where |
800 | 0 | E: Into<Cow<'a, str>>, |
801 | 0 | V: Into<Cow<'a, str>>, |
802 | | { |
803 | 0 | self.write_style = Var::new_with_default(write_style_env, default); |
804 | | |
805 | 0 | self |
806 | 0 | } |
807 | | |
808 | | /// Use the default environment variable to read the style from. |
809 | | /// |
810 | | /// If the variable is not set, the default value will be used. |
811 | 0 | pub fn default_write_style_or<V>(mut self, default: V) -> Self |
812 | 0 | where |
813 | 0 | V: Into<Cow<'a, str>>, |
814 | | { |
815 | 0 | self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default); |
816 | | |
817 | 0 | self |
818 | 0 | } |
819 | | |
820 | 4 | fn get_write_style(&self) -> Option<String> { |
821 | 4 | self.write_style.get() |
822 | 4 | } |
823 | | } |
824 | | |
825 | | impl<'a, T> From<T> for Env<'a> |
826 | | where |
827 | | T: Into<Cow<'a, str>>, |
828 | | { |
829 | 0 | fn from(filter_env: T) -> Self { |
830 | 0 | Env::default().filter(filter_env.into()) |
831 | 0 | } |
832 | | } |
833 | | |
834 | | impl Default for Env<'_> { |
835 | 4 | fn default() -> Self { |
836 | 4 | Env { |
837 | 4 | filter: Var::new(DEFAULT_FILTER_ENV), |
838 | 4 | write_style: Var::new(DEFAULT_WRITE_STYLE_ENV), |
839 | 4 | } |
840 | 4 | } |
841 | | } |
842 | | |
843 | | #[derive(Debug)] |
844 | | struct Var<'a> { |
845 | | name: Cow<'a, str>, |
846 | | default: Option<Cow<'a, str>>, |
847 | | } |
848 | | |
849 | | impl<'a> Var<'a> { |
850 | 8 | fn new<E>(name: E) -> Self |
851 | 8 | where |
852 | 8 | E: Into<Cow<'a, str>>, |
853 | | { |
854 | 8 | Var { |
855 | 8 | name: name.into(), |
856 | 8 | default: None, |
857 | 8 | } |
858 | 8 | } |
859 | | |
860 | 0 | fn new_with_default<E, V>(name: E, default: V) -> Self |
861 | 0 | where |
862 | 0 | E: Into<Cow<'a, str>>, |
863 | 0 | V: Into<Cow<'a, str>>, |
864 | | { |
865 | 0 | Var { |
866 | 0 | name: name.into(), |
867 | 0 | default: Some(default.into()), |
868 | 0 | } |
869 | 0 | } |
870 | | |
871 | 8 | fn get(&self) -> Option<String> { |
872 | 8 | env::var(&*self.name) |
873 | 8 | .ok() |
874 | 8 | .or_else(|| self.default.clone().map(|v| v.into_owned())) |
875 | 8 | } |
876 | | } |
877 | | |
878 | | /// Attempts to initialize the global logger with an env logger. |
879 | | /// |
880 | | /// This should be called early in the execution of a Rust program. Any log |
881 | | /// events that occur before initialization will be ignored. |
882 | | /// |
883 | | /// # Errors |
884 | | /// |
885 | | /// This function will fail if it is called more than once, or if another |
886 | | /// library has already initialized a global logger. |
887 | 0 | pub fn try_init() -> Result<(), SetLoggerError> { |
888 | 0 | try_init_from_env(Env::default()) |
889 | 0 | } |
890 | | |
891 | | /// Initializes the global logger with an env logger. |
892 | | /// |
893 | | /// This should be called early in the execution of a Rust program. Any log |
894 | | /// events that occur before initialization will be ignored. |
895 | | /// |
896 | | /// # Panics |
897 | | /// |
898 | | /// This function will panic if it is called more than once, or if another |
899 | | /// library has already initialized a global logger. |
900 | 0 | pub fn init() { |
901 | 0 | try_init().expect("env_logger::init should not be called after logger initialized"); |
902 | 0 | } |
903 | | |
904 | | /// Attempts to initialize the global logger with an env logger from the given |
905 | | /// environment variables. |
906 | | /// |
907 | | /// This should be called early in the execution of a Rust program. Any log |
908 | | /// events that occur before initialization will be ignored. |
909 | | /// |
910 | | /// # Examples |
911 | | /// |
912 | | /// Initialise a logger using the `MY_LOG` environment variable for filters |
913 | | /// and `MY_LOG_STYLE` for writing colors: |
914 | | /// |
915 | | /// ``` |
916 | | /// use env_logger::{Builder, Env}; |
917 | | /// |
918 | | /// # fn run() -> Result<(), Box<dyn ::std::error::Error>> { |
919 | | /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); |
920 | | /// |
921 | | /// env_logger::try_init_from_env(env)?; |
922 | | /// |
923 | | /// Ok(()) |
924 | | /// # } |
925 | | /// # run().unwrap(); |
926 | | /// ``` |
927 | | /// |
928 | | /// # Errors |
929 | | /// |
930 | | /// This function will fail if it is called more than once, or if another |
931 | | /// library has already initialized a global logger. |
932 | 0 | pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError> |
933 | 0 | where |
934 | 0 | E: Into<Env<'a>>, |
935 | | { |
936 | 0 | let mut builder = Builder::from_env(env); |
937 | | |
938 | 0 | builder.try_init() |
939 | 0 | } |
940 | | |
941 | | /// Initializes the global logger with an env logger from the given environment |
942 | | /// variables. |
943 | | /// |
944 | | /// This should be called early in the execution of a Rust program. Any log |
945 | | /// events that occur before initialization will be ignored. |
946 | | /// |
947 | | /// # Examples |
948 | | /// |
949 | | /// Initialise a logger using the `MY_LOG` environment variable for filters |
950 | | /// and `MY_LOG_STYLE` for writing colors: |
951 | | /// |
952 | | /// ``` |
953 | | /// use env_logger::{Builder, Env}; |
954 | | /// |
955 | | /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); |
956 | | /// |
957 | | /// env_logger::init_from_env(env); |
958 | | /// ``` |
959 | | /// |
960 | | /// # Panics |
961 | | /// |
962 | | /// This function will panic if it is called more than once, or if another |
963 | | /// library has already initialized a global logger. |
964 | 0 | pub fn init_from_env<'a, E>(env: E) |
965 | 0 | where |
966 | 0 | E: Into<Env<'a>>, |
967 | | { |
968 | 0 | try_init_from_env(env) |
969 | 0 | .expect("env_logger::init_from_env should not be called after logger initialized"); |
970 | 0 | } |
971 | | |
972 | | /// Create a new builder with the default environment variables. |
973 | | /// |
974 | | /// The builder can be configured before being initialized. |
975 | | /// This is a convenient way of calling [`Builder::from_default_env`]. |
976 | | /// |
977 | | /// [`Builder::from_default_env`]: struct.Builder.html#method.from_default_env |
978 | 4 | pub fn builder() -> Builder { |
979 | 4 | Builder::from_default_env() |
980 | 4 | } |
981 | | |
982 | | /// Create a builder from the given environment variables. |
983 | | /// |
984 | | /// The builder can be configured before being initialized. |
985 | | #[deprecated( |
986 | | since = "0.8.0", |
987 | | note = "Prefer `env_logger::Builder::from_env()` instead." |
988 | | )] |
989 | 0 | pub fn from_env<'a, E>(env: E) -> Builder |
990 | 0 | where |
991 | 0 | E: Into<Env<'a>>, |
992 | | { |
993 | 0 | Builder::from_env(env) |
994 | 0 | } |
995 | | |
996 | | #[cfg(test)] |
997 | | mod tests { |
998 | | use super::*; |
999 | | |
1000 | | #[test] |
1001 | | fn env_get_filter_reads_from_var_if_set() { |
1002 | | env::set_var("env_get_filter_reads_from_var_if_set", "from var"); |
1003 | | |
1004 | | let env = Env::new().filter_or("env_get_filter_reads_from_var_if_set", "from default"); |
1005 | | |
1006 | | assert_eq!(Some("from var".to_owned()), env.get_filter()); |
1007 | | } |
1008 | | |
1009 | | #[test] |
1010 | | fn env_get_filter_reads_from_default_if_var_not_set() { |
1011 | | env::remove_var("env_get_filter_reads_from_default_if_var_not_set"); |
1012 | | |
1013 | | let env = Env::new().filter_or( |
1014 | | "env_get_filter_reads_from_default_if_var_not_set", |
1015 | | "from default", |
1016 | | ); |
1017 | | |
1018 | | assert_eq!(Some("from default".to_owned()), env.get_filter()); |
1019 | | } |
1020 | | |
1021 | | #[test] |
1022 | | fn env_get_write_style_reads_from_var_if_set() { |
1023 | | env::set_var("env_get_write_style_reads_from_var_if_set", "from var"); |
1024 | | |
1025 | | let env = |
1026 | | Env::new().write_style_or("env_get_write_style_reads_from_var_if_set", "from default"); |
1027 | | |
1028 | | assert_eq!(Some("from var".to_owned()), env.get_write_style()); |
1029 | | } |
1030 | | |
1031 | | #[test] |
1032 | | fn env_get_write_style_reads_from_default_if_var_not_set() { |
1033 | | env::remove_var("env_get_write_style_reads_from_default_if_var_not_set"); |
1034 | | |
1035 | | let env = Env::new().write_style_or( |
1036 | | "env_get_write_style_reads_from_default_if_var_not_set", |
1037 | | "from default", |
1038 | | ); |
1039 | | |
1040 | | assert_eq!(Some("from default".to_owned()), env.get_write_style()); |
1041 | | } |
1042 | | |
1043 | | #[test] |
1044 | | fn builder_parse_env_overrides_existing_filters() { |
1045 | | env::set_var( |
1046 | | "builder_parse_default_env_overrides_existing_filters", |
1047 | | "debug", |
1048 | | ); |
1049 | | let env = Env::new().filter("builder_parse_default_env_overrides_existing_filters"); |
1050 | | |
1051 | | let mut builder = Builder::new(); |
1052 | | builder.filter_level(LevelFilter::Trace); |
1053 | | // Overrides global level to debug |
1054 | | builder.parse_env(env); |
1055 | | |
1056 | | assert_eq!(builder.filter.build().filter(), LevelFilter::Debug); |
1057 | | } |
1058 | | } |