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