1// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 2// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license 3// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your 4// option. This file may not be copied, modified, or distributed 5// except according to those terms. 6 7//! A simple logger that can be configured via environment variables, for use 8//! with the logging facade exposed by the [`log` crate][log-crate-url]. 9//! 10//! Despite having "env" in its name, **`env_logger`** can also be configured by 11//! other means besides environment variables. See [the examples][gh-repo-examples] 12//! in the source repository for more approaches. 13//! 14//! By default, `env_logger` writes logs to `stderr`, but can be configured to 15//! instead write them to `stdout`. 16//! 17//! ## Example 18//! 19//! ``` 20//! use log::{debug, error, log_enabled, info, Level}; 21//! 22//! env_logger::init(); 23//! 24//! debug!("this is a debug {}", "message"); 25//! error!("this is printed by default"); 26//! 27//! if log_enabled!(Level::Info) { 28//! let x = 3 * 4; // expensive computation 29//! info!("the answer was: {}", x); 30//! } 31//! ``` 32//! 33//! Assumes the binary is `main`: 34//! 35//! ```{.bash} 36//! $ RUST_LOG=error ./main 37//! [2017-11-09T02:12:24Z ERROR main] this is printed by default 38//! ``` 39//! 40//! ```{.bash} 41//! $ RUST_LOG=info ./main 42//! [2017-11-09T02:12:24Z ERROR main] this is printed by default 43//! [2017-11-09T02:12:24Z INFO main] the answer was: 12 44//! ``` 45//! 46//! ```{.bash} 47//! $ RUST_LOG=debug ./main 48//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message 49//! [2017-11-09T02:12:24Z ERROR main] this is printed by default 50//! [2017-11-09T02:12:24Z INFO main] the answer was: 12 51//! ``` 52//! 53//! You can also set the log level on a per module basis: 54//! 55//! ```{.bash} 56//! $ RUST_LOG=main=info ./main 57//! [2017-11-09T02:12:24Z ERROR main] this is printed by default 58//! [2017-11-09T02:12:24Z INFO main] the answer was: 12 59//! ``` 60//! 61//! And enable all logging: 62//! 63//! ```{.bash} 64//! $ RUST_LOG=main ./main 65//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message 66//! [2017-11-09T02:12:24Z ERROR main] this is printed by default 67//! [2017-11-09T02:12:24Z INFO main] the answer was: 12 68//! ``` 69//! 70//! If the binary name contains hyphens, you will need to replace 71//! them with underscores: 72//! 73//! ```{.bash} 74//! $ RUST_LOG=my_app ./my-app 75//! [2017-11-09T02:12:24Z DEBUG my_app] this is a debug message 76//! [2017-11-09T02:12:24Z ERROR my_app] this is printed by default 77//! [2017-11-09T02:12:24Z INFO my_app] the answer was: 12 78//! ``` 79//! 80//! This is because Rust modules and crates cannot contain hyphens 81//! in their name, although `cargo` continues to accept them. 82//! 83//! See the documentation for the [`log` crate][log-crate-url] for more 84//! information about its API. 85//! 86//! ## Enabling logging 87//! 88//! Log levels are controlled on a per-module basis, and **by default all 89//! logging is disabled except for the `error` level**. 90//! 91//! Logging is controlled via the **`RUST_LOG`** environment variable. The 92//! value of this environment variable is a comma-separated list of *logging 93//! directives*. A logging directive is of the form: 94//! 95//! ```text 96//! example::log::target=level 97//! ``` 98//! 99//! The log target is typically equal to the path of the module the message 100//! in question originated from, though it can be overriden. 101//! 102//! The path is rooted in the name of the crate it was compiled for, so if 103//! your program is in a file called, for example, `hello.rs`, the path would 104//! simply be be `hello`. 105//! 106//! Furthermore, the log can be filtered using prefix-search based on the 107//! specified log target. A value of, for example, `RUST_LOG=example`, would 108//! match all of the messages with targets: 109//! 110//! * `example` 111//! * `example::test` 112//! * `example::test::module::submodule` 113//! * `examples::and_more_examples` 114//! 115//! When providing the crate name or a module path, explicitly specifying the 116//! log level is optional. If omitted, all logging for the item will be 117//! enabled. 118//! 119//! The names of the log levels that may be specified correspond to the 120//! variations of the [`log::Level`][level-enum] enum from the `log` 121//! crate. They are: 122//! 123//! * `error` 124//! * `warn` 125//! * `info` 126//! * `debug` 127//! * `trace` 128//! 129//! There is also a pseudo logging level, `off`, which may be specified to 130//! disable all logging for a given module or for the entire application. As 131//! with the logging levels, the letter case is not significant[^fn-off]. 132//! 133//! [^fn-off]: Similar to the universe of log level names, the `off` pseudo 134//! log level feature is also provided by the underlying `log` crate. 135//! 136//! The letter case is not significant for the logging level names; e.g., 137//! `debug`, `DEBUG`, and `dEbuG` all represent the same logging level. For 138//! consistency, our convention is to use the lower case names. Where our docs 139//! do use other forms, they do so in the context of specific examples, so you 140//! won't be surprised if you see similar usage in the wild. 141//! 142//! As the log level for a module is optional, the module to enable logging for 143//! is also optional. **If only a level is provided, then the global log 144//! level for all modules is set to this value.** 145//! 146//! Some examples of valid values of `RUST_LOG` are: 147//! 148//! * `hello` turns on all logging for the 'hello' module 149//! * `trace` turns on all logging for the application, regardless of its name 150//! * `TRACE` turns on all logging for the application, regardless of its name (same as previous) 151//! * `info` turns on all info logging 152//! * `INFO` turns on all info logging (same as previous) 153//! * `hello=debug` turns on debug logging for 'hello' 154//! * `hello=DEBUG` turns on debug logging for 'hello' (same as previous) 155//! * `hello,std::option` turns on hello, and std's option logging 156//! * `error,hello=warn` turn on global error logging and also warn for hello 157//! * `error,hello=off` turn on global error logging, but turn off logging for hello 158//! * `off` turns off all logging for the application 159//! * `OFF` turns off all logging for the application (same as previous) 160//! 161//! ## Filtering results 162//! 163//! A `RUST_LOG` directive may include a regex filter. The syntax is to append `/` 164//! followed by a regex. Each message is checked against the regex, and is only 165//! logged if it matches. Note that the matching is done after formatting the 166//! log string but before adding any logging meta-data. There is a single filter 167//! for all modules. 168//! 169//! Some examples: 170//! 171//! * `hello/foo` turns on all logging for the 'hello' module where the log 172//! message includes 'foo'. 173//! * `info/f.o` turns on all info logging where the log message includes 'foo', 174//! 'f1o', 'fao', etc. 175//! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the log 176//! message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc. 177//! * `error,hello=warn/[0-9]scopes` turn on global error logging and also 178//! warn for hello. In both cases the log message must include a single digit 179//! number followed by 'scopes'. 180//! 181//! ## Capturing logs in tests 182//! 183//! Records logged during `cargo test` will not be captured by the test harness by default. 184//! The [`Builder::is_test`] method can be used in unit tests to ensure logs will be captured: 185//! 186//! ``` 187//! # #[macro_use] extern crate log; 188//! #[cfg(test)] 189//! mod tests { 190//! fn init() { 191//! let _ = env_logger::builder().is_test(true).try_init(); 192//! } 193//! 194//! #[test] 195//! fn it_works() { 196//! init(); 197//! 198//! info!("This record will be captured by `cargo test`"); 199//! 200//! assert_eq!(2, 1 + 1); 201//! } 202//! } 203//! ``` 204//! 205//! Enabling test capturing comes at the expense of color and other style support 206//! and may have performance implications. 207//! 208//! ## Disabling colors 209//! 210//! Colors and other styles can be configured with the `RUST_LOG_STYLE` 211//! environment variable. It accepts the following values: 212//! 213//! * `auto` (default) will attempt to print style characters, but don't force the issue. 214//! If the console isn't available on Windows, or if TERM=dumb, for example, then don't print colors. 215//! * `always` will always print style characters even if they aren't supported by the terminal. 216//! This includes emitting ANSI colors on Windows if the console API is unavailable. 217//! * `never` will never print style characters. 218//! 219//! ## Tweaking the default format 220//! 221//! Parts of the default format can be excluded from the log output using the [`Builder`]. 222//! The following example excludes the timestamp from the log output: 223//! 224//! ``` 225//! env_logger::builder() 226//! .format_timestamp(None) 227//! .init(); 228//! ``` 229//! 230//! ### Stability of the default format 231//! 232//! The default format won't optimise for long-term stability, and explicitly makes no 233//! guarantees about the stability of its output across major, minor or patch version 234//! bumps during `0.x`. 235//! 236//! If you want to capture or interpret the output of `env_logger` programmatically 237//! then you should use a custom format. 238//! 239//! ### Using a custom format 240//! 241//! Custom formats can be provided as closures to the [`Builder`]. 242//! These closures take a [`Formatter`] and `log::Record` as arguments: 243//! 244//! ``` 245//! use std::io::Write; 246//! 247//! env_logger::builder() 248//! .format(|buf, record| { 249//! writeln!(buf, "{}: {}", record.level(), record.args()) 250//! }) 251//! .init(); 252//! ``` 253//! 254//! See the [`fmt`] module for more details about custom formats. 255//! 256//! ## Specifying defaults for environment variables 257//! 258//! `env_logger` can read configuration from environment variables. 259//! If these variables aren't present, the default value to use can be tweaked with the [`Env`] type. 260//! The following example defaults to log `warn` and above if the `RUST_LOG` environment variable 261//! isn't set: 262//! 263//! ``` 264//! use env_logger::Env; 265//! 266//! env_logger::Builder::from_env(Env::default().default_filter_or("warn")).init(); 267//! ``` 268//! 269//! [gh-repo-examples]: https://github.com/env-logger-rs/env_logger/tree/main/examples 270//! [level-enum]: https://docs.rs/log/latest/log/enum.Level.html 271//! [log-crate-url]: https://docs.rs/log/ 272//! [`Builder`]: struct.Builder.html 273//! [`Builder::is_test`]: struct.Builder.html#method.is_test 274//! [`Env`]: struct.Env.html 275//! [`fmt`]: fmt/index.html 276 277#![doc( 278 html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", 279 html_favicon_url = "https://www.rust-lang.org/static/images/favicon.ico" 280)] 281// When compiled for the rustc compiler itself we want to make sure that this is 282// an unstable crate 283#![cfg_attr(rustbuild, feature(staged_api, rustc_private))] 284#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))] 285#![deny(missing_debug_implementations, missing_docs)] 286 287use std::{borrow::Cow, cell::RefCell, env, io}; 288 289use log::{LevelFilter, Log, Metadata, Record, SetLoggerError}; 290 291pub mod filter; 292pub mod fmt; 293 294pub use self::fmt::glob::*; 295 296use self::filter::Filter; 297use self::fmt::writer::{self, Writer}; 298use self::fmt::{FormatFn, Formatter}; 299 300/// The default name for the environment variable to read filters from. 301pub const DEFAULT_FILTER_ENV: &str = "RUST_LOG"; 302 303/// The default name for the environment variable to read style preferences from. 304pub const DEFAULT_WRITE_STYLE_ENV: &str = "RUST_LOG_STYLE"; 305 306/// Set of environment variables to configure from. 307/// 308/// # Default environment variables 309/// 310/// By default, the `Env` will read the following environment variables: 311/// 312/// - `RUST_LOG`: the level filter 313/// - `RUST_LOG_STYLE`: whether or not to print styles with records. 314/// 315/// These sources can be configured using the builder methods on `Env`. 316#[derive(Debug)] 317pub struct Env<'a> { 318 filter: Var<'a>, 319 write_style: Var<'a>, 320} 321 322#[derive(Debug)] 323struct Var<'a> { 324 name: Cow<'a, str>, 325 default: Option<Cow<'a, str>>, 326} 327 328/// The env logger. 329/// 330/// This struct implements the `Log` trait from the [`log` crate][log-crate-url], 331/// which allows it to act as a logger. 332/// 333/// The [`init()`], [`try_init()`], [`Builder::init()`] and [`Builder::try_init()`] 334/// methods will each construct a `Logger` and immediately initialize it as the 335/// default global logger. 336/// 337/// If you'd instead need access to the constructed `Logger`, you can use 338/// the associated [`Builder`] and install it with the 339/// [`log` crate][log-crate-url] directly. 340/// 341/// [log-crate-url]: https://docs.rs/log/ 342/// [`init()`]: fn.init.html 343/// [`try_init()`]: fn.try_init.html 344/// [`Builder::init()`]: struct.Builder.html#method.init 345/// [`Builder::try_init()`]: struct.Builder.html#method.try_init 346/// [`Builder`]: struct.Builder.html 347pub struct Logger { 348 writer: Writer, 349 filter: Filter, 350 format: FormatFn, 351} 352 353/// `Builder` acts as builder for initializing a `Logger`. 354/// 355/// It can be used to customize the log format, change the environment variable used 356/// to provide the logging directives and also set the default log level filter. 357/// 358/// # Examples 359/// 360/// ``` 361/// # #[macro_use] extern crate log; 362/// # use std::io::Write; 363/// use env_logger::Builder; 364/// use log::LevelFilter; 365/// 366/// let mut builder = Builder::from_default_env(); 367/// 368/// builder 369/// .format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args())) 370/// .filter(None, LevelFilter::Info) 371/// .init(); 372/// 373/// error!("error message"); 374/// info!("info message"); 375/// ``` 376#[derive(Default)] 377pub struct Builder { 378 filter: filter::Builder, 379 writer: writer::Builder, 380 format: fmt::Builder, 381 built: bool, 382} 383 384impl Builder { 385 /// Initializes the log builder with defaults. 386 /// 387 /// **NOTE:** This method won't read from any environment variables. 388 /// Use the [`filter`] and [`write_style`] methods to configure the builder 389 /// or use [`from_env`] or [`from_default_env`] instead. 390 /// 391 /// # Examples 392 /// 393 /// Create a new builder and configure filters and style: 394 /// 395 /// ``` 396 /// use log::LevelFilter; 397 /// use env_logger::{Builder, WriteStyle}; 398 /// 399 /// let mut builder = Builder::new(); 400 /// 401 /// builder 402 /// .filter(None, LevelFilter::Info) 403 /// .write_style(WriteStyle::Always) 404 /// .init(); 405 /// ``` 406 /// 407 /// [`filter`]: #method.filter 408 /// [`write_style`]: #method.write_style 409 /// [`from_env`]: #method.from_env 410 /// [`from_default_env`]: #method.from_default_env 411 pub fn new() -> Builder { 412 Default::default() 413 } 414 415 /// Initializes the log builder from the environment. 416 /// 417 /// The variables used to read configuration from can be tweaked before 418 /// passing in. 419 /// 420 /// # Examples 421 /// 422 /// Initialise a logger reading the log filter from an environment variable 423 /// called `MY_LOG`: 424 /// 425 /// ``` 426 /// use env_logger::Builder; 427 /// 428 /// let mut builder = Builder::from_env("MY_LOG"); 429 /// builder.init(); 430 /// ``` 431 /// 432 /// Initialise a logger using the `MY_LOG` variable for filtering and 433 /// `MY_LOG_STYLE` for whether or not to write styles: 434 /// 435 /// ``` 436 /// use env_logger::{Builder, Env}; 437 /// 438 /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); 439 /// 440 /// let mut builder = Builder::from_env(env); 441 /// builder.init(); 442 /// ``` 443 pub fn from_env<'a, E>(env: E) -> Self 444 where 445 E: Into<Env<'a>>, 446 { 447 let mut builder = Builder::new(); 448 builder.parse_env(env); 449 builder 450 } 451 452 /// Applies the configuration from the environment. 453 /// 454 /// This function allows a builder to be configured with default parameters, 455 /// to be then overridden by the environment. 456 /// 457 /// # Examples 458 /// 459 /// Initialise a logger with filter level `Off`, then override the log 460 /// filter from an environment variable called `MY_LOG`: 461 /// 462 /// ``` 463 /// use log::LevelFilter; 464 /// use env_logger::Builder; 465 /// 466 /// let mut builder = Builder::new(); 467 /// 468 /// builder.filter_level(LevelFilter::Off); 469 /// builder.parse_env("MY_LOG"); 470 /// builder.init(); 471 /// ``` 472 /// 473 /// Initialise a logger with filter level `Off`, then use the `MY_LOG` 474 /// variable to override filtering and `MY_LOG_STYLE` to override whether 475 /// or not to write styles: 476 /// 477 /// ``` 478 /// use log::LevelFilter; 479 /// use env_logger::{Builder, Env}; 480 /// 481 /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); 482 /// 483 /// let mut builder = Builder::new(); 484 /// builder.filter_level(LevelFilter::Off); 485 /// builder.parse_env(env); 486 /// builder.init(); 487 /// ``` 488 pub fn parse_env<'a, E>(&mut self, env: E) -> &mut Self 489 where 490 E: Into<Env<'a>>, 491 { 492 let env = env.into(); 493 494 if let Some(s) = env.get_filter() { 495 self.parse_filters(&s); 496 } 497 498 if let Some(s) = env.get_write_style() { 499 self.parse_write_style(&s); 500 } 501 502 self 503 } 504 505 /// Initializes the log builder from the environment using default variable names. 506 /// 507 /// This method is a convenient way to call `from_env(Env::default())` without 508 /// having to use the `Env` type explicitly. The builder will use the 509 /// [default environment variables]. 510 /// 511 /// # Examples 512 /// 513 /// Initialise a logger using the default environment variables: 514 /// 515 /// ``` 516 /// use env_logger::Builder; 517 /// 518 /// let mut builder = Builder::from_default_env(); 519 /// builder.init(); 520 /// ``` 521 /// 522 /// [default environment variables]: struct.Env.html#default-environment-variables 523 pub fn from_default_env() -> Self { 524 Self::from_env(Env::default()) 525 } 526 527 /// Applies the configuration from the environment using default variable names. 528 /// 529 /// This method is a convenient way to call `parse_env(Env::default())` without 530 /// having to use the `Env` type explicitly. The builder will use the 531 /// [default environment variables]. 532 /// 533 /// # Examples 534 /// 535 /// Initialise a logger with filter level `Off`, then configure it using the 536 /// default environment variables: 537 /// 538 /// ``` 539 /// use log::LevelFilter; 540 /// use env_logger::Builder; 541 /// 542 /// let mut builder = Builder::new(); 543 /// builder.filter_level(LevelFilter::Off); 544 /// builder.parse_default_env(); 545 /// builder.init(); 546 /// ``` 547 /// 548 /// [default environment variables]: struct.Env.html#default-environment-variables 549 pub fn parse_default_env(&mut self) -> &mut Self { 550 self.parse_env(Env::default()) 551 } 552 553 /// Sets the format function for formatting the log output. 554 /// 555 /// This function is called on each record logged and should format the 556 /// log record and output it to the given [`Formatter`]. 557 /// 558 /// The format function is expected to output the string directly to the 559 /// `Formatter` so that implementations can use the [`std::fmt`] macros 560 /// to format and output without intermediate heap allocations. The default 561 /// `env_logger` formatter takes advantage of this. 562 /// 563 /// # Examples 564 /// 565 /// Use a custom format to write only the log message: 566 /// 567 /// ``` 568 /// use std::io::Write; 569 /// use env_logger::Builder; 570 /// 571 /// let mut builder = Builder::new(); 572 /// 573 /// builder.format(|buf, record| writeln!(buf, "{}", record.args())); 574 /// ``` 575 /// 576 /// [`Formatter`]: fmt/struct.Formatter.html 577 /// [`String`]: https://doc.rust-lang.org/stable/std/string/struct.String.html 578 /// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html 579 pub fn format<F: 'static>(&mut self, format: F) -> &mut Self 580 where 581 F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send, 582 { 583 self.format.custom_format = Some(Box::new(format)); 584 self 585 } 586 587 /// Use the default format. 588 /// 589 /// This method will clear any custom format set on the builder. 590 pub fn default_format(&mut self) -> &mut Self { 591 self.format = Default::default(); 592 self 593 } 594 595 /// Whether or not to write the level in the default format. 596 pub fn format_level(&mut self, write: bool) -> &mut Self { 597 self.format.format_level = write; 598 self 599 } 600 601 /// Whether or not to write the module path in the default format. 602 pub fn format_module_path(&mut self, write: bool) -> &mut Self { 603 self.format.format_module_path = write; 604 self 605 } 606 607 /// Whether or not to write the target in the default format. 608 pub fn format_target(&mut self, write: bool) -> &mut Self { 609 self.format.format_target = write; 610 self 611 } 612 613 /// Configures the amount of spaces to use to indent multiline log records. 614 /// A value of `None` disables any kind of indentation. 615 pub fn format_indent(&mut self, indent: Option<usize>) -> &mut Self { 616 self.format.format_indent = indent; 617 self 618 } 619 620 /// Configures if timestamp should be included and in what precision. 621 pub fn format_timestamp(&mut self, timestamp: Option<fmt::TimestampPrecision>) -> &mut Self { 622 self.format.format_timestamp = timestamp; 623 self 624 } 625 626 /// Configures the timestamp to use second precision. 627 pub fn format_timestamp_secs(&mut self) -> &mut Self { 628 self.format_timestamp(Some(fmt::TimestampPrecision::Seconds)) 629 } 630 631 /// Configures the timestamp to use millisecond precision. 632 pub fn format_timestamp_millis(&mut self) -> &mut Self { 633 self.format_timestamp(Some(fmt::TimestampPrecision::Millis)) 634 } 635 636 /// Configures the timestamp to use microsecond precision. 637 pub fn format_timestamp_micros(&mut self) -> &mut Self { 638 self.format_timestamp(Some(fmt::TimestampPrecision::Micros)) 639 } 640 641 /// Configures the timestamp to use nanosecond precision. 642 pub fn format_timestamp_nanos(&mut self) -> &mut Self { 643 self.format_timestamp(Some(fmt::TimestampPrecision::Nanos)) 644 } 645 646 /// Configures the end of line suffix. 647 pub fn format_suffix(&mut self, suffix: &'static str) -> &mut Self { 648 self.format.format_suffix = suffix; 649 self 650 } 651 652 /// Adds a directive to the filter for a specific module. 653 /// 654 /// # Examples 655 /// 656 /// Only include messages for info and above for logs in `path::to::module`: 657 /// 658 /// ``` 659 /// use env_logger::Builder; 660 /// use log::LevelFilter; 661 /// 662 /// let mut builder = Builder::new(); 663 /// 664 /// builder.filter_module("path::to::module", LevelFilter::Info); 665 /// ``` 666 pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self { 667 self.filter.filter_module(module, level); 668 self 669 } 670 671 /// Adds a directive to the filter for all modules. 672 /// 673 /// # Examples 674 /// 675 /// Only include messages for info and above for logs globally: 676 /// 677 /// ``` 678 /// use env_logger::Builder; 679 /// use log::LevelFilter; 680 /// 681 /// let mut builder = Builder::new(); 682 /// 683 /// builder.filter_level(LevelFilter::Info); 684 /// ``` 685 pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self { 686 self.filter.filter_level(level); 687 self 688 } 689 690 /// Adds filters to the logger. 691 /// 692 /// The given module (if any) will log at most the specified level provided. 693 /// If no module is provided then the filter will apply to all log messages. 694 /// 695 /// # Examples 696 /// 697 /// Only include messages for info and above for logs in `path::to::module`: 698 /// 699 /// ``` 700 /// use env_logger::Builder; 701 /// use log::LevelFilter; 702 /// 703 /// let mut builder = Builder::new(); 704 /// 705 /// builder.filter(Some("path::to::module"), LevelFilter::Info); 706 /// ``` 707 pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self { 708 self.filter.filter(module, level); 709 self 710 } 711 712 /// Parses the directives string in the same form as the `RUST_LOG` 713 /// environment variable. 714 /// 715 /// See the module documentation for more details. 716 pub fn parse_filters(&mut self, filters: &str) -> &mut Self { 717 self.filter.parse(filters); 718 self 719 } 720 721 /// Sets the target for the log output. 722 /// 723 /// Env logger can log to either stdout, stderr or a custom pipe. The default is stderr. 724 /// 725 /// The custom pipe can be used to send the log messages to a custom sink (for example a file). 726 /// Do note that direct writes to a file can become a bottleneck due to IO operation times. 727 /// 728 /// # Examples 729 /// 730 /// Write log message to `stdout`: 731 /// 732 /// ``` 733 /// use env_logger::{Builder, Target}; 734 /// 735 /// let mut builder = Builder::new(); 736 /// 737 /// builder.target(Target::Stdout); 738 /// ``` 739 pub fn target(&mut self, target: fmt::Target) -> &mut Self { 740 self.writer.target(target); 741 self 742 } 743 744 /// Sets whether or not styles will be written. 745 /// 746 /// This can be useful in environments that don't support control characters 747 /// for setting colors. 748 /// 749 /// # Examples 750 /// 751 /// Never attempt to write styles: 752 /// 753 /// ``` 754 /// use env_logger::{Builder, WriteStyle}; 755 /// 756 /// let mut builder = Builder::new(); 757 /// 758 /// builder.write_style(WriteStyle::Never); 759 /// ``` 760 pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self { 761 self.writer.write_style(write_style); 762 self 763 } 764 765 /// Parses whether or not to write styles in the same form as the `RUST_LOG_STYLE` 766 /// environment variable. 767 /// 768 /// See the module documentation for more details. 769 pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self { 770 self.writer.parse_write_style(write_style); 771 self 772 } 773 774 /// Sets whether or not the logger will be used in unit tests. 775 /// 776 /// If `is_test` is `true` then the logger will allow the testing framework to 777 /// capture log records rather than printing them to the terminal directly. 778 pub fn is_test(&mut self, is_test: bool) -> &mut Self { 779 self.writer.is_test(is_test); 780 self 781 } 782 783 /// Initializes the global logger with the built env logger. 784 /// 785 /// This should be called early in the execution of a Rust program. Any log 786 /// events that occur before initialization will be ignored. 787 /// 788 /// # Errors 789 /// 790 /// This function will fail if it is called more than once, or if another 791 /// library has already initialized a global logger. 792 pub fn try_init(&mut self) -> Result<(), SetLoggerError> { 793 let logger = self.build(); 794 795 let max_level = logger.filter(); 796 let r = log::set_boxed_logger(Box::new(logger)); 797 798 if r.is_ok() { 799 log::set_max_level(max_level); 800 } 801 802 r 803 } 804 805 /// Initializes the global logger with the built env logger. 806 /// 807 /// This should be called early in the execution of a Rust program. Any log 808 /// events that occur before initialization will be ignored. 809 /// 810 /// # Panics 811 /// 812 /// This function will panic if it is called more than once, or if another 813 /// library has already initialized a global logger. 814 pub fn init(&mut self) { 815 self.try_init() 816 .expect("Builder::init should not be called after logger initialized"); 817 } 818 819 /// Build an env logger. 820 /// 821 /// The returned logger implements the `Log` trait and can be installed manually 822 /// or nested within another logger. 823 pub fn build(&mut self) -> Logger { 824 assert!(!self.built, "attempt to re-use consumed builder"); 825 self.built = true; 826 827 Logger { 828 writer: self.writer.build(), 829 filter: self.filter.build(), 830 format: self.format.build(), 831 } 832 } 833} 834 835impl Logger { 836 /// Creates the logger from the environment. 837 /// 838 /// The variables used to read configuration from can be tweaked before 839 /// passing in. 840 /// 841 /// # Examples 842 /// 843 /// Create a logger reading the log filter from an environment variable 844 /// called `MY_LOG`: 845 /// 846 /// ``` 847 /// use env_logger::Logger; 848 /// 849 /// let logger = Logger::from_env("MY_LOG"); 850 /// ``` 851 /// 852 /// Create a logger using the `MY_LOG` variable for filtering and 853 /// `MY_LOG_STYLE` for whether or not to write styles: 854 /// 855 /// ``` 856 /// use env_logger::{Logger, Env}; 857 /// 858 /// let env = Env::new().filter_or("MY_LOG", "info").write_style_or("MY_LOG_STYLE", "always"); 859 /// 860 /// let logger = Logger::from_env(env); 861 /// ``` 862 pub fn from_env<'a, E>(env: E) -> Self 863 where 864 E: Into<Env<'a>>, 865 { 866 Builder::from_env(env).build() 867 } 868 869 /// Creates the logger from the environment using default variable names. 870 /// 871 /// This method is a convenient way to call `from_env(Env::default())` without 872 /// having to use the `Env` type explicitly. The logger will use the 873 /// [default environment variables]. 874 /// 875 /// # Examples 876 /// 877 /// Creates a logger using the default environment variables: 878 /// 879 /// ``` 880 /// use env_logger::Logger; 881 /// 882 /// let logger = Logger::from_default_env(); 883 /// ``` 884 /// 885 /// [default environment variables]: struct.Env.html#default-environment-variables 886 pub fn from_default_env() -> Self { 887 Builder::from_default_env().build() 888 } 889 890 /// Returns the maximum `LevelFilter` that this env logger instance is 891 /// configured to output. 892 pub fn filter(&self) -> LevelFilter { 893 self.filter.filter() 894 } 895 896 /// Checks if this record matches the configured filter. 897 pub fn matches(&self, record: &Record) -> bool { 898 self.filter.matches(record) 899 } 900} 901 902impl Log for Logger { 903 fn enabled(&self, metadata: &Metadata) -> bool { 904 self.filter.enabled(metadata) 905 } 906 907 fn log(&self, record: &Record) { 908 if self.matches(record) { 909 // Log records are written to a thread-local buffer before being printed 910 // to the terminal. We clear these buffers afterwards, but they aren't shrinked 911 // so will always at least have capacity for the largest log record formatted 912 // on that thread. 913 // 914 // If multiple `Logger`s are used by the same threads then the thread-local 915 // formatter might have different color support. If this is the case the 916 // formatter and its buffer are discarded and recreated. 917 918 thread_local! { 919 static FORMATTER: RefCell<Option<Formatter>> = RefCell::new(None); 920 } 921 922 let print = |formatter: &mut Formatter, record: &Record| { 923 let _ = 924 (self.format)(formatter, record).and_then(|_| formatter.print(&self.writer)); 925 926 // Always clear the buffer afterwards 927 formatter.clear(); 928 }; 929 930 let printed = FORMATTER 931 .try_with(|tl_buf| { 932 match tl_buf.try_borrow_mut() { 933 // There are no active borrows of the buffer 934 Ok(mut tl_buf) => match *tl_buf { 935 // We have a previously set formatter 936 Some(ref mut formatter) => { 937 // Check the buffer style. If it's different from the logger's 938 // style then drop the buffer and recreate it. 939 if formatter.write_style() != self.writer.write_style() { 940 *formatter = Formatter::new(&self.writer); 941 } 942 943 print(formatter, record); 944 } 945 // We don't have a previously set formatter 946 None => { 947 let mut formatter = Formatter::new(&self.writer); 948 print(&mut formatter, record); 949 950 *tl_buf = Some(formatter); 951 } 952 }, 953 // There's already an active borrow of the buffer (due to re-entrancy) 954 Err(_) => { 955 print(&mut Formatter::new(&self.writer), record); 956 } 957 } 958 }) 959 .is_ok(); 960 961 if !printed { 962 // The thread-local storage was not available (because its 963 // destructor has already run). Create a new single-use 964 // Formatter on the stack for this call. 965 print(&mut Formatter::new(&self.writer), record); 966 } 967 } 968 } 969 970 fn flush(&self) {} 971} 972 973impl<'a> Env<'a> { 974 /// Get a default set of environment variables. 975 pub fn new() -> Self { 976 Self::default() 977 } 978 979 /// Specify an environment variable to read the filter from. 980 pub fn filter<E>(mut self, filter_env: E) -> Self 981 where 982 E: Into<Cow<'a, str>>, 983 { 984 self.filter = Var::new(filter_env); 985 986 self 987 } 988 989 /// Specify an environment variable to read the filter from. 990 /// 991 /// If the variable is not set, the default value will be used. 992 pub fn filter_or<E, V>(mut self, filter_env: E, default: V) -> Self 993 where 994 E: Into<Cow<'a, str>>, 995 V: Into<Cow<'a, str>>, 996 { 997 self.filter = Var::new_with_default(filter_env, default); 998 999 self 1000 } 1001 1002 /// Use the default environment variable to read the filter from. 1003 /// 1004 /// If the variable is not set, the default value will be used. 1005 pub fn default_filter_or<V>(mut self, default: V) -> Self 1006 where 1007 V: Into<Cow<'a, str>>, 1008 { 1009 self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default); 1010 1011 self 1012 } 1013 1014 fn get_filter(&self) -> Option<String> { 1015 self.filter.get() 1016 } 1017 1018 /// Specify an environment variable to read the style from. 1019 pub fn write_style<E>(mut self, write_style_env: E) -> Self 1020 where 1021 E: Into<Cow<'a, str>>, 1022 { 1023 self.write_style = Var::new(write_style_env); 1024 1025 self 1026 } 1027 1028 /// Specify an environment variable to read the style from. 1029 /// 1030 /// If the variable is not set, the default value will be used. 1031 pub fn write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self 1032 where 1033 E: Into<Cow<'a, str>>, 1034 V: Into<Cow<'a, str>>, 1035 { 1036 self.write_style = Var::new_with_default(write_style_env, default); 1037 1038 self 1039 } 1040 1041 /// Use the default environment variable to read the style from. 1042 /// 1043 /// If the variable is not set, the default value will be used. 1044 pub fn default_write_style_or<V>(mut self, default: V) -> Self 1045 where 1046 V: Into<Cow<'a, str>>, 1047 { 1048 self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default); 1049 1050 self 1051 } 1052 1053 fn get_write_style(&self) -> Option<String> { 1054 self.write_style.get() 1055 } 1056} 1057 1058impl<'a> Var<'a> { 1059 fn new<E>(name: E) -> Self 1060 where 1061 E: Into<Cow<'a, str>>, 1062 { 1063 Var { 1064 name: name.into(), 1065 default: None, 1066 } 1067 } 1068 1069 fn new_with_default<E, V>(name: E, default: V) -> Self 1070 where 1071 E: Into<Cow<'a, str>>, 1072 V: Into<Cow<'a, str>>, 1073 { 1074 Var { 1075 name: name.into(), 1076 default: Some(default.into()), 1077 } 1078 } 1079 1080 fn get(&self) -> Option<String> { 1081 env::var(&*self.name) 1082 .ok() 1083 .or_else(|| self.default.to_owned().map(|v| v.into_owned())) 1084 } 1085} 1086 1087impl<'a, T> From<T> for Env<'a> 1088where 1089 T: Into<Cow<'a, str>>, 1090{ 1091 fn from(filter_env: T) -> Self { 1092 Env::default().filter(filter_env.into()) 1093 } 1094} 1095 1096impl<'a> Default for Env<'a> { 1097 fn default() -> Self { 1098 Env { 1099 filter: Var::new(DEFAULT_FILTER_ENV), 1100 write_style: Var::new(DEFAULT_WRITE_STYLE_ENV), 1101 } 1102 } 1103} 1104 1105mod std_fmt_impls { 1106 use super::*; 1107 use std::fmt; 1108 1109 impl fmt::Debug for Logger { 1110 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1111 f.debug_struct("Logger") 1112 .field("filter", &self.filter) 1113 .finish() 1114 } 1115 } 1116 1117 impl fmt::Debug for Builder { 1118 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1119 if self.built { 1120 f.debug_struct("Logger").field("built", &true).finish() 1121 } else { 1122 f.debug_struct("Logger") 1123 .field("filter", &self.filter) 1124 .field("writer", &self.writer) 1125 .finish() 1126 } 1127 } 1128 } 1129} 1130 1131/// Attempts to initialize the global logger with an env logger. 1132/// 1133/// This should be called early in the execution of a Rust program. Any log 1134/// events that occur before initialization will be ignored. 1135/// 1136/// # Errors 1137/// 1138/// This function will fail if it is called more than once, or if another 1139/// library has already initialized a global logger. 1140pub fn try_init() -> Result<(), SetLoggerError> { 1141 try_init_from_env(Env::default()) 1142} 1143 1144/// Initializes the global logger with an env logger. 1145/// 1146/// This should be called early in the execution of a Rust program. Any log 1147/// events that occur before initialization will be ignored. 1148/// 1149/// # Panics 1150/// 1151/// This function will panic if it is called more than once, or if another 1152/// library has already initialized a global logger. 1153pub fn init() { 1154 try_init().expect("env_logger::init should not be called after logger initialized"); 1155} 1156 1157/// Attempts to initialize the global logger with an env logger from the given 1158/// environment variables. 1159/// 1160/// This should be called early in the execution of a Rust program. Any log 1161/// events that occur before initialization will be ignored. 1162/// 1163/// # Examples 1164/// 1165/// Initialise a logger using the `MY_LOG` environment variable for filters 1166/// and `MY_LOG_STYLE` for writing colors: 1167/// 1168/// ``` 1169/// use env_logger::{Builder, Env}; 1170/// 1171/// # fn run() -> Result<(), Box<::std::error::Error>> { 1172/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); 1173/// 1174/// env_logger::try_init_from_env(env)?; 1175/// 1176/// Ok(()) 1177/// # } 1178/// # run().unwrap(); 1179/// ``` 1180/// 1181/// # Errors 1182/// 1183/// This function will fail if it is called more than once, or if another 1184/// library has already initialized a global logger. 1185pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError> 1186where 1187 E: Into<Env<'a>>, 1188{ 1189 let mut builder = Builder::from_env(env); 1190 1191 builder.try_init() 1192} 1193 1194/// Initializes the global logger with an env logger from the given environment 1195/// variables. 1196/// 1197/// This should be called early in the execution of a Rust program. Any log 1198/// events that occur before initialization will be ignored. 1199/// 1200/// # Examples 1201/// 1202/// Initialise a logger using the `MY_LOG` environment variable for filters 1203/// and `MY_LOG_STYLE` for writing colors: 1204/// 1205/// ``` 1206/// use env_logger::{Builder, Env}; 1207/// 1208/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); 1209/// 1210/// env_logger::init_from_env(env); 1211/// ``` 1212/// 1213/// # Panics 1214/// 1215/// This function will panic if it is called more than once, or if another 1216/// library has already initialized a global logger. 1217pub fn init_from_env<'a, E>(env: E) 1218where 1219 E: Into<Env<'a>>, 1220{ 1221 try_init_from_env(env) 1222 .expect("env_logger::init_from_env should not be called after logger initialized"); 1223} 1224 1225/// Create a new builder with the default environment variables. 1226/// 1227/// The builder can be configured before being initialized. 1228/// This is a convenient way of calling [`Builder::from_default_env`]. 1229/// 1230/// [`Builder::from_default_env`]: struct.Builder.html#method.from_default_env 1231pub fn builder() -> Builder { 1232 Builder::from_default_env() 1233} 1234 1235/// Create a builder from the given environment variables. 1236/// 1237/// The builder can be configured before being initialized. 1238#[deprecated( 1239 since = "0.8.0", 1240 note = "Prefer `env_logger::Builder::from_env()` instead." 1241)] 1242pub fn from_env<'a, E>(env: E) -> Builder 1243where 1244 E: Into<Env<'a>>, 1245{ 1246 Builder::from_env(env) 1247} 1248 1249#[cfg(test)] 1250mod tests { 1251 use super::*; 1252 1253 #[test] 1254 fn env_get_filter_reads_from_var_if_set() { 1255 env::set_var("env_get_filter_reads_from_var_if_set", "from var"); 1256 1257 let env = Env::new().filter_or("env_get_filter_reads_from_var_if_set", "from default"); 1258 1259 assert_eq!(Some("from var".to_owned()), env.get_filter()); 1260 } 1261 1262 #[test] 1263 fn env_get_filter_reads_from_default_if_var_not_set() { 1264 env::remove_var("env_get_filter_reads_from_default_if_var_not_set"); 1265 1266 let env = Env::new().filter_or( 1267 "env_get_filter_reads_from_default_if_var_not_set", 1268 "from default", 1269 ); 1270 1271 assert_eq!(Some("from default".to_owned()), env.get_filter()); 1272 } 1273 1274 #[test] 1275 fn env_get_write_style_reads_from_var_if_set() { 1276 env::set_var("env_get_write_style_reads_from_var_if_set", "from var"); 1277 1278 let env = 1279 Env::new().write_style_or("env_get_write_style_reads_from_var_if_set", "from default"); 1280 1281 assert_eq!(Some("from var".to_owned()), env.get_write_style()); 1282 } 1283 1284 #[test] 1285 fn env_get_write_style_reads_from_default_if_var_not_set() { 1286 env::remove_var("env_get_write_style_reads_from_default_if_var_not_set"); 1287 1288 let env = Env::new().write_style_or( 1289 "env_get_write_style_reads_from_default_if_var_not_set", 1290 "from default", 1291 ); 1292 1293 assert_eq!(Some("from default".to_owned()), env.get_write_style()); 1294 } 1295 1296 #[test] 1297 fn builder_parse_env_overrides_existing_filters() { 1298 env::set_var( 1299 "builder_parse_default_env_overrides_existing_filters", 1300 "debug", 1301 ); 1302 let env = Env::new().filter("builder_parse_default_env_overrides_existing_filters"); 1303 1304 let mut builder = Builder::new(); 1305 builder.filter_level(LevelFilter::Trace); 1306 // Overrides global level to debug 1307 builder.parse_env(env); 1308 1309 assert_eq!(builder.filter.build().filter(), LevelFilter::Debug); 1310 } 1311} 1312