//! A simple logger that can be configured via environment variables, for use //! with the logging facade exposed by the [`log` crate][log-crate-url]. //! //! Despite having "env" in its name, **`env_logger`** can also be configured by //! other means besides environment variables. See [the examples][gh-repo-examples] //! in the source repository for more approaches. //! //! By default, `env_logger` writes logs to `stderr`, but can be configured to //! instead write them to `stdout`. //! //! ## Example //! //! ``` //! use log::{debug, error, log_enabled, info, Level}; //! //! env_logger::init(); //! //! debug!("this is a debug {}", "message"); //! error!("this is printed by default"); //! //! if log_enabled!(Level::Info) { //! let x = 3 * 4; // expensive computation //! info!("the answer was: {}", x); //! } //! ``` //! //! Assumes the binary is `main`: //! //! ```{.bash} //! $ RUST_LOG=error ./main //! [2017-11-09T02:12:24Z ERROR main] this is printed by default //! ``` //! //! ```{.bash} //! $ RUST_LOG=info ./main //! [2017-11-09T02:12:24Z ERROR main] this is printed by default //! [2017-11-09T02:12:24Z INFO main] the answer was: 12 //! ``` //! //! ```{.bash} //! $ RUST_LOG=debug ./main //! [2017-11-09T02:12:24Z DEBUG main] this is a debug message //! [2017-11-09T02:12:24Z ERROR main] this is printed by default //! [2017-11-09T02:12:24Z INFO main] the answer was: 12 //! ``` //! //! You can also set the log level on a per module basis: //! //! ```{.bash} //! $ RUST_LOG=main=info ./main //! [2017-11-09T02:12:24Z ERROR main] this is printed by default //! [2017-11-09T02:12:24Z INFO main] the answer was: 12 //! ``` //! //! And enable all logging: //! //! ```{.bash} //! $ RUST_LOG=main ./main //! [2017-11-09T02:12:24Z DEBUG main] this is a debug message //! [2017-11-09T02:12:24Z ERROR main] this is printed by default //! [2017-11-09T02:12:24Z INFO main] the answer was: 12 //! ``` //! //! If the binary name contains hyphens, you will need to replace //! them with underscores: //! //! ```{.bash} //! $ RUST_LOG=my_app ./my-app //! [2017-11-09T02:12:24Z DEBUG my_app] this is a debug message //! [2017-11-09T02:12:24Z ERROR my_app] this is printed by default //! [2017-11-09T02:12:24Z INFO my_app] the answer was: 12 //! ``` //! //! This is because Rust modules and crates cannot contain hyphens //! in their name, although `cargo` continues to accept them. //! //! See the documentation for the [`log` crate][log-crate-url] for more //! information about its API. //! //! ## Enabling logging //! //! Log levels are controlled on a per-module basis, and **by default all //! logging is disabled except for the `error` level**. //! //! Logging is controlled via the **`RUST_LOG`** environment variable. The //! value of this environment variable is a comma-separated list of *logging //! directives*. A logging directive is of the form: //! //! ```text //! example::log::target=level //! ``` //! //! The log target is typically equal to the path of the module the message //! in question originated from, though it can be overridden. //! //! The path is rooted in the name of the crate it was compiled for, so if //! your program is in a file called, for example, `hello.rs`, the path would //! simply be be `hello`. //! //! Furthermore, the log can be filtered using prefix-search based on the //! specified log target. A value of, for example, `RUST_LOG=example`, would //! match all of the messages with targets: //! //! * `example` //! * `example::test` //! * `example::test::module::submodule` //! * `examples::and_more_examples` //! //! When providing the crate name or a module path, explicitly specifying the //! log level is optional. If omitted, all logging for the item will be //! enabled. //! //! The names of the log levels that may be specified correspond to the //! variations of the [`log::Level`][level-enum] enum from the `log` //! crate. They are: //! //! * `error` //! * `warn` //! * `info` //! * `debug` //! * `trace` //! //! There is also a pseudo logging level, `off`, which may be specified to //! disable all logging for a given module or for the entire application. As //! with the logging levels, the letter case is not significant[^fn-off]. //! //! [^fn-off]: Similar to the universe of log level names, the `off` pseudo //! log level feature is also provided by the underlying `log` crate. //! //! The letter case is not significant for the logging level names; e.g., //! `debug`, `DEBUG`, and `dEbuG` all represent the same logging level. For //! consistency, our convention is to use the lower case names. Where our docs //! do use other forms, they do so in the context of specific examples, so you //! won't be surprised if you see similar usage in the wild. //! //! As the log level for a module is optional, the module to enable logging for //! is also optional. **If only a level is provided, then the global log //! level for all modules is set to this value.** //! //! Some examples of valid values of `RUST_LOG` are: //! //! * `hello` turns on all logging for the 'hello' module //! * `trace` turns on all logging for the application, regardless of its name //! * `TRACE` turns on all logging for the application, regardless of its name (same as previous) //! * `info` turns on all info logging //! * `INFO` turns on all info logging (same as previous) //! * `hello=debug` turns on debug logging for 'hello' //! * `hello=DEBUG` turns on debug logging for 'hello' (same as previous) //! * `hello,std::option` turns on hello, and std's option logging //! * `error,hello=warn` turn on global error logging and also warn for hello //! * `error,hello=off` turn on global error logging, but turn off logging for hello //! * `off` turns off all logging for the application //! * `OFF` turns off all logging for the application (same as previous) //! //! ## Filtering results //! //! A `RUST_LOG` directive may include a regex filter. The syntax is to append `/` //! followed by a regex. Each message is checked against the regex, and is only //! logged if it matches. Note that the matching is done after formatting the //! log string but before adding any logging meta-data. There is a single filter //! for all modules. //! //! Some examples: //! //! * `hello/foo` turns on all logging for the 'hello' module where the log //! message includes 'foo'. //! * `info/f.o` turns on all info logging where the log message includes 'foo', //! 'f1o', 'fao', etc. //! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the log //! message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc. //! * `error,hello=warn/[0-9]scopes` turn on global error logging and also //! warn for hello. In both cases the log message must include a single digit //! number followed by 'scopes'. //! //! ## Capturing logs in tests //! //! Records logged during `cargo test` will not be captured by the test harness by default. //! The [`Builder::is_test`] method can be used in unit tests to ensure logs will be captured: //! //! ``` //! # #[macro_use] extern crate log; //! #[cfg(test)] //! mod tests { //! fn init() { //! let _ = env_logger::builder().is_test(true).try_init(); //! } //! //! #[test] //! fn it_works() { //! init(); //! //! info!("This record will be captured by `cargo test`"); //! //! assert_eq!(2, 1 + 1); //! } //! } //! ``` //! //! Enabling test capturing comes at the expense of color and other style support //! and may have performance implications. //! //! ## Disabling colors //! //! Colors and other styles can be configured with the `RUST_LOG_STYLE` //! environment variable. It accepts the following values: //! //! * `auto` (default) will attempt to print style characters, but don't force the issue. //! If the console isn't available on Windows, or if TERM=dumb, for example, then don't print colors. //! * `always` will always print style characters even if they aren't supported by the terminal. //! This includes emitting ANSI colors on Windows if the console API is unavailable. //! * `never` will never print style characters. //! //! ## Tweaking the default format //! //! Parts of the default format can be excluded from the log output using the [`Builder`]. //! The following example excludes the timestamp from the log output: //! //! ``` //! env_logger::builder() //! .format_timestamp(None) //! .init(); //! ``` //! //! ### Stability of the default format //! //! The default format won't optimise for long-term stability, and explicitly makes no //! guarantees about the stability of its output across major, minor or patch version //! bumps during `0.x`. //! //! If you want to capture or interpret the output of `env_logger` programmatically //! then you should use a custom format. //! //! ### Using a custom format //! //! Custom formats can be provided as closures to the [`Builder`]. //! These closures take a [`Formatter`] and `log::Record` as arguments: //! //! ``` //! use std::io::Write; //! //! env_logger::builder() //! .format(|buf, record| { //! writeln!(buf, "{}: {}", record.level(), record.args()) //! }) //! .init(); //! ``` //! //! See the [`fmt`] module for more details about custom formats. //! //! ## Specifying defaults for environment variables //! //! `env_logger` can read configuration from environment variables. //! If these variables aren't present, the default value to use can be tweaked with the [`Env`] type. //! The following example defaults to log `warn` and above if the `RUST_LOG` environment variable //! isn't set: //! //! ``` //! use env_logger::Env; //! //! env_logger::Builder::from_env(Env::default().default_filter_or("warn")).init(); //! ``` //! //! [gh-repo-examples]: https://github.com/env-logger-rs/env_logger/tree/main/examples //! [level-enum]: https://docs.rs/log/latest/log/enum.Level.html //! [log-crate-url]: https://docs.rs/log/ //! [`Builder`]: struct.Builder.html //! [`Builder::is_test`]: struct.Builder.html#method.is_test //! [`Env`]: struct.Env.html //! [`fmt`]: fmt/index.html
#![doc(
html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://www.rust-lang.org/static/images/favicon.ico"
)] // When compiled for the rustc compiler itself we want to make sure that this is // an unstable crate #![cfg_attr(rustbuild, feature(staged_api, rustc_private))] #![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))] #![deny(missing_debug_implementations, missing_docs)]
use std::{borrow::Cow, cell::RefCell, env, io};
use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};
/// The default name for the environment variable to read filters from. pubconst DEFAULT_FILTER_ENV: &str = "RUST_LOG";
/// The default name for the environment variable to read style preferences from. pubconst DEFAULT_WRITE_STYLE_ENV: &str = "RUST_LOG_STYLE";
/// Set of environment variables to configure from. /// /// # Default environment variables /// /// By default, the `Env` will read the following environment variables: /// /// - `RUST_LOG`: the level filter /// - `RUST_LOG_STYLE`: whether or not to print styles with records. /// /// These sources can be configured using the builder methods on `Env`. #[derive(Debug)] pubstruct Env<'a> {
filter: Var<'a>,
write_style: Var<'a>,
}
/// The env logger. /// /// This struct implements the `Log` trait from the [`log` crate][log-crate-url], /// which allows it to act as a logger. /// /// The [`init()`], [`try_init()`], [`Builder::init()`] and [`Builder::try_init()`] /// methods will each construct a `Logger` and immediately initialize it as the /// default global logger. /// /// If you'd instead need access to the constructed `Logger`, you can use /// the associated [`Builder`] and install it with the /// [`log` crate][log-crate-url] directly. /// /// [log-crate-url]: https://docs.rs/log/ /// [`init()`]: fn.init.html /// [`try_init()`]: fn.try_init.html /// [`Builder::init()`]: struct.Builder.html#method.init /// [`Builder::try_init()`]: struct.Builder.html#method.try_init /// [`Builder`]: struct.Builder.html pubstruct Logger {
writer: Writer,
filter: Filter,
format: FormatFn,
}
/// `Builder` acts as builder for initializing a `Logger`. /// /// It can be used to customize the log format, change the environment variable used /// to provide the logging directives and also set the default log level filter. /// /// # Examples /// /// ``` /// # #[macro_use] extern crate log; /// # use std::io::Write; /// use env_logger::Builder; /// use log::LevelFilter; /// /// let mut builder = Builder::from_default_env(); /// /// builder /// .format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args())) /// .filter(None, LevelFilter::Info) /// .init(); /// /// error!("error message"); /// info!("info message"); /// ``` #[derive(Default)] pubstruct Builder {
filter: filter::Builder,
writer: writer::Builder,
format: fmt::Builder,
built: bool,
}
impl Builder { /// Initializes the log builder with defaults. /// /// **NOTE:** This method won't read from any environment variables. /// Use the [`filter`] and [`write_style`] methods to configure the builder /// or use [`from_env`] or [`from_default_env`] instead. /// /// # Examples /// /// Create a new builder and configure filters and style: /// /// ``` /// use log::LevelFilter; /// use env_logger::{Builder, WriteStyle}; /// /// let mut builder = Builder::new(); /// /// builder /// .filter(None, LevelFilter::Info) /// .write_style(WriteStyle::Always) /// .init(); /// ``` /// /// [`filter`]: #method.filter /// [`write_style`]: #method.write_style /// [`from_env`]: #method.from_env /// [`from_default_env`]: #method.from_default_env pubfn new() -> Builder {
Default::default()
}
/// Initializes the log builder from the environment. /// /// The variables used to read configuration from can be tweaked before /// passing in. /// /// # Examples /// /// Initialise a logger reading the log filter from an environment variable /// called `MY_LOG`: /// /// ``` /// use env_logger::Builder; /// /// let mut builder = Builder::from_env("MY_LOG"); /// builder.init(); /// ``` /// /// Initialise a logger using the `MY_LOG` variable for filtering and /// `MY_LOG_STYLE` for whether or not to write styles: /// /// ``` /// use env_logger::{Builder, Env}; /// /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); /// /// let mut builder = Builder::from_env(env); /// builder.init(); /// ``` pubfn from_env<'a, E>(env: E) -> Self where
E: Into<Env<'a>>,
{ letmut builder = Builder::new();
builder.parse_env(env);
builder
}
/// Applies the configuration from the environment. /// /// This function allows a builder to be configured with default parameters, /// to be then overridden by the environment. /// /// # Examples /// /// Initialise a logger with filter level `Off`, then override the log /// filter from an environment variable called `MY_LOG`: /// /// ``` /// use log::LevelFilter; /// use env_logger::Builder; /// /// let mut builder = Builder::new(); /// /// builder.filter_level(LevelFilter::Off); /// builder.parse_env("MY_LOG"); /// builder.init(); /// ``` /// /// Initialise a logger with filter level `Off`, then use the `MY_LOG` /// variable to override filtering and `MY_LOG_STYLE` to override whether /// or not to write styles: /// /// ``` /// use log::LevelFilter; /// use env_logger::{Builder, Env}; /// /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); /// /// let mut builder = Builder::new(); /// builder.filter_level(LevelFilter::Off); /// builder.parse_env(env); /// builder.init(); /// ``` pubfn parse_env<'a, E>(&mut self, env: E) -> &mut Self where
E: Into<Env<'a>>,
{ let env = env.into();
/// Initializes the log builder from the environment using default variable names. /// /// This method is a convenient way to call `from_env(Env::default())` without /// having to use the `Env` type explicitly. The builder will use the /// [default environment variables]. /// /// # Examples /// /// Initialise a logger using the default environment variables: /// /// ``` /// use env_logger::Builder; /// /// let mut builder = Builder::from_default_env(); /// builder.init(); /// ``` /// /// [default environment variables]: struct.Env.html#default-environment-variables pubfn from_default_env() -> Self { Self::from_env(Env::default())
}
/// Applies the configuration from the environment using default variable names. /// /// This method is a convenient way to call `parse_env(Env::default())` without /// having to use the `Env` type explicitly. The builder will use the /// [default environment variables]. /// /// # Examples /// /// Initialise a logger with filter level `Off`, then configure it using the /// default environment variables: /// /// ``` /// use log::LevelFilter; /// use env_logger::Builder; /// /// let mut builder = Builder::new(); /// builder.filter_level(LevelFilter::Off); /// builder.parse_default_env(); /// builder.init(); /// ``` /// /// [default environment variables]: struct.Env.html#default-environment-variables pubfn parse_default_env(&mutself) -> &mutSelf { self.parse_env(Env::default())
}
/// Sets the format function for formatting the log output. /// /// This function is called on each record logged and should format the /// log record and output it to the given [`Formatter`]. /// /// The format function is expected to output the string directly to the /// `Formatter` so that implementations can use the [`std::fmt`] macros /// to format and output without intermediate heap allocations. The default /// `env_logger` formatter takes advantage of this. /// /// # Examples /// /// Use a custom format to write only the log message: /// /// ``` /// use std::io::Write; /// use env_logger::Builder; /// /// let mut builder = Builder::new(); /// /// builder.format(|buf, record| writeln!(buf, "{}", record.args())); /// ``` /// /// [`Formatter`]: fmt/struct.Formatter.html /// [`String`]: https://doc.rust-lang.org/stable/std/string/struct.String.html /// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html pubfn format<F: 'static>(&mut self, format: F) -> &mut Self where
F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send,
{ self.format.custom_format = Some(Box::new(format)); self
}
/// Use the default format. /// /// This method will clear any custom format set on the builder. pubfn default_format(&mutself) -> &mutSelf { self.format = Default::default(); self
}
/// Whether or not to write the level in the default format. pubfn format_level(&mutself, write: bool) -> &mutSelf { self.format.format_level = write; self
}
/// Whether or not to write the module path in the default format. pubfn format_module_path(&mutself, write: bool) -> &mutSelf { self.format.format_module_path = write; self
}
/// Whether or not to write the target in the default format. pubfn format_target(&mutself, write: bool) -> &mutSelf { self.format.format_target = write; self
}
/// Configures the amount of spaces to use to indent multiline log records. /// A value of `None` disables any kind of indentation. pubfn format_indent(&mutself, indent: Option<usize>) -> &='color:red'>mutSelf { self.format.format_indent = indent; self
}
/// Configures if timestamp should be included and in what precision. pubfn format_timestamp(&mutself, timestamp: Option<fmt::TimestampPrecision>) -> &mutSelf { self.format.format_timestamp = timestamp; self
}
/// Configures the timestamp to use second precision. pubfn format_timestamp_secs(&mutself) -> &mutSelf { self.format_timestamp(Some(fmt::TimestampPrecision::Seconds))
}
/// Configures the timestamp to use millisecond precision. pubfn format_timestamp_millis(&mutself) -> &mutSelf { self.format_timestamp(Some(fmt::TimestampPrecision::Millis))
}
/// Configures the timestamp to use microsecond precision. pubfn format_timestamp_micros(&mutself) -> &mutSelf { self.format_timestamp(Some(fmt::TimestampPrecision::Micros))
}
/// Configures the timestamp to use nanosecond precision. pubfn format_timestamp_nanos(&mutself) -> &mutSelf { self.format_timestamp(Some(fmt::TimestampPrecision::Nanos))
}
/// Configures the end of line suffix. pubfn format_suffix(&mutself, suffix: &>'static str) -> &mut Self { self.format.format_suffix = suffix; self
}
/// Adds a directive to the filter for a specific module. /// /// # Examples /// /// Only include messages for info and above for logs in `path::to::module`: /// /// ``` /// use env_logger::Builder; /// use log::LevelFilter; /// /// let mut builder = Builder::new(); /// /// builder.filter_module("path::to::module", LevelFilter::Info); /// ``` pubfn filter_module(&mutself, module: &str, level: LevelFilter) -> &mutSelf { self.filter.filter_module(module, level); self
}
/// Adds a directive to the filter for all modules. /// /// # Examples /// /// Only include messages for info and above for logs globally: /// /// ``` /// use env_logger::Builder; /// use log::LevelFilter; /// /// let mut builder = Builder::new(); /// /// builder.filter_level(LevelFilter::Info); /// ``` pubfn filter_level(&mutself, level: LevelFilter) -> &mutSelf { self.filter.filter_level(level); self
}
/// Adds filters to the logger. /// /// The given module (if any) will log at most the specified level provided. /// If no module is provided then the filter will apply to all log messages. /// /// # Examples /// /// Only include messages for info and above for logs in `path::to::module`: /// /// ``` /// use env_logger::Builder; /// use log::LevelFilter; /// /// let mut builder = Builder::new(); /// /// builder.filter(Some("path::to::module"), LevelFilter::Info); /// ``` pubfn filter(&mutself, module: Option<&str>, level: LevelFilter) -> &pan style='color:red'>mut Self { self.filter.filter(module, level); self
}
/// Parses the directives string in the same form as the `RUST_LOG` /// environment variable. /// /// See the module documentation for more details. pubfn parse_filters(&mutself, filters: &str) -> &mutSelf { self.filter.parse(filters); self
}
/// Sets the target for the log output. /// /// Env logger can log to either stdout, stderr or a custom pipe. The default is stderr. /// /// The custom pipe can be used to send the log messages to a custom sink (for example a file). /// Do note that direct writes to a file can become a bottleneck due to IO operation times. /// /// # Examples /// /// Write log message to `stdout`: /// /// ``` /// use env_logger::{Builder, Target}; /// /// let mut builder = Builder::new(); /// /// builder.target(Target::Stdout); /// ``` pubfn target(&mutself, target: fmt::Target) -> &mutSelf { self.writer.target(target); self
}
/// Sets whether or not styles will be written. /// /// This can be useful in environments that don't support control characters /// for setting colors. /// /// # Examples /// /// Never attempt to write styles: /// /// ``` /// use env_logger::{Builder, WriteStyle}; /// /// let mut builder = Builder::new(); /// /// builder.write_style(WriteStyle::Never); /// ``` pubfn write_style(&mutself, write_style: fmt::WriteStyle) -> &n style='color:red'>mut Self { self.writer.write_style(write_style); self
}
/// Parses whether or not to write styles in the same form as the `RUST_LOG_STYLE` /// environment variable. /// /// See the module documentation for more details. pubfn parse_write_style(&mutself, write_style: &str) -> &le='color:red'>mutSelf { self.writer.parse_write_style(write_style); self
}
/// Sets whether or not the logger will be used in unit tests. /// /// If `is_test` is `true` then the logger will allow the testing framework to /// capture log records rather than printing them to the terminal directly. pubfn is_test(&mutself, is_test: bool) -> &>mutSelf { self.writer.is_test(is_test); self
}
/// Initializes the global logger with the built env logger. /// /// This should be called early in the execution of a Rust program. Any log /// events that occur before initialization will be ignored. /// /// # Errors /// /// This function will fail if it is called more than once, or if another /// library has already initialized a global logger. pubfn try_init(&mutself) -> Result<(), SetLoggerError> { let logger = self.build();
let max_level = logger.filter(); let r = log::set_boxed_logger(Box::new(logger));
if r.is_ok() {
log::set_max_level(max_level);
}
r
}
/// Initializes the global logger with the built env logger. /// /// This should be called early in the execution of a Rust program. Any log /// events that occur before initialization will be ignored. /// /// # Panics /// /// This function will panic if it is called more than once, or if another /// library has already initialized a global logger. pubfn init(&mutself) { self.try_init()
.expect("Builder::init should not be called after logger initialized");
}
/// Build an env logger. /// /// The returned logger implements the `Log` trait and can be installed manually /// or nested within another logger. pubfn build(&mutself) -> Logger {
assert!(!self.built, "attempt to re-use consumed builder"); self.built = true;
impl Logger { /// Creates the logger from the environment. /// /// The variables used to read configuration from can be tweaked before /// passing in. /// /// # Examples /// /// Create a logger reading the log filter from an environment variable /// called `MY_LOG`: /// /// ``` /// use env_logger::Logger; /// /// let logger = Logger::from_env("MY_LOG"); /// ``` /// /// Create a logger using the `MY_LOG` variable for filtering and /// `MY_LOG_STYLE` for whether or not to write styles: /// /// ``` /// use env_logger::{Logger, Env}; /// /// let env = Env::new().filter_or("MY_LOG", "info").write_style_or("MY_LOG_STYLE", "always"); /// /// let logger = Logger::from_env(env); /// ``` pubfn from_env<'a, E>(env: E) -> Self where
E: Into<Env<'a>>,
{
Builder::from_env(env).build()
}
/// Creates the logger from the environment using default variable names. /// /// This method is a convenient way to call `from_env(Env::default())` without /// having to use the `Env` type explicitly. The logger will use the /// [default environment variables]. /// /// # Examples /// /// Creates a logger using the default environment variables: /// /// ``` /// use env_logger::Logger; /// /// let logger = Logger::from_default_env(); /// ``` /// /// [default environment variables]: struct.Env.html#default-environment-variables pubfn from_default_env() -> Self {
Builder::from_default_env().build()
}
/// Returns the maximum `LevelFilter` that this env logger instance is /// configured to output. pubfn filter(&self) -> LevelFilter { self.filter.filter()
}
/// Checks if this record matches the configured filter. pubfn matches(&self, record: &Record) -> bool { self.filter.matches(record)
}
}
fn log(&self, record: &Record) { ifself.matches(record) { // Log records are written to a thread-local buffer before being printed // to the terminal. We clear these buffers afterwards, but they aren't shrunk // so will always at least have capacity for the largest log record formatted // on that thread. // // If multiple `Logger`s are used by the same threads then the thread-local // formatter might have different color support. If this is the case the // formatter and its buffer are discarded and recreated.
let print = |formatter: &mut Formatter, record: &Record| { let _ =
(self.format)(formatter, record).and_then(|_| formatter.print(&self.writer));
// Always clear the buffer afterwards
formatter.clear();
};
let printed = FORMATTER
.try_with(|tl_buf| { match tl_buf.try_borrow_mut() { // There are no active borrows of the buffer
Ok(mut tl_buf) => match *tl_buf { // We have a previously set formatter
Some(refmut formatter) => { // Check the buffer style. If it's different from the logger's // style then drop the buffer and recreate it. if formatter.write_style() != self.writer.write_style() {
*formatter = Formatter::new(&self.writer);
}
print(formatter, record);
} // We don't have a previously set formatter
None => { letmut formatter = Formatter::new(&self.writer);
print(&mut formatter, record);
*tl_buf = Some(formatter);
}
}, // There's already an active borrow of the buffer (due to re-entrancy)
Err(_) => {
print(&mut Formatter::new(&self.writer), record);
}
}
})
.is_ok();
if !printed { // The thread-local storage was not available (because its // destructor has already run). Create a new single-use // Formatter on the stack for this call.
print(&mut Formatter::new(&self.writer), record);
}
}
}
fn flush(&self) {}
}
impl<'a> Env<'a> { /// Get a default set of environment variables. pubfn new() -> Self { Self::default()
}
/// Specify an environment variable to read the filter from. pubfn filter<E>(mutself, filter_env: E) -> Self where
E: Into<Cow<'a, str>>,
{ self.filter = Var::new(filter_env);
self
}
/// Specify an environment variable to read the filter from. /// /// If the variable is not set, the default value will be used. pubfn filter_or<E, V>(mutself, filter_env: E, default: V) -> Self where
E: Into<Cow<'a, str>>,
V: Into<Cow<'a, str>>,
{ self.filter = Var::new_with_default(filter_env, default);
self
}
/// Use the default environment variable to read the filter from. /// /// If the variable is not set, the default value will be used. pubfn default_filter_or<V>(mutself, default: V) -> Self where
V: Into<Cow<'a, str>>,
{ self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default);
/// Specify an environment variable to read the style from. pubfn write_style<E>(mutself, write_style_env: E) -> Self where
E: Into<Cow<'a, str>>,
{ self.write_style = Var::new(write_style_env);
self
}
/// Specify an environment variable to read the style from. /// /// If the variable is not set, the default value will be used. pubfn write_style_or<E, V>(mutself, write_style_env: E, default: V) -> Self where
E: Into<Cow<'a, str>>,
V: Into<Cow<'a, str>>,
{ self.write_style = Var::new_with_default(write_style_env, default);
self
}
/// Use the default environment variable to read the style from. /// /// If the variable is not set, the default value will be used. pubfn default_write_style_or<V>(mutself, default: V) -> Self where
V: Into<Cow<'a, str>>,
{ self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default);
/// Attempts to initialize the global logger with an env logger. /// /// This should be called early in the execution of a Rust program. Any log /// events that occur before initialization will be ignored. /// /// # Errors /// /// This function will fail if it is called more than once, or if another /// library has already initialized a global logger. pubfn try_init() -> Result<(), SetLoggerError> {
try_init_from_env(Env::default())
}
/// Initializes the global logger with an env logger. /// /// This should be called early in the execution of a Rust program. Any log /// events that occur before initialization will be ignored. /// /// # Panics /// /// This function will panic if it is called more than once, or if another /// library has already initialized a global logger. pubfn init() {
try_init().expect("env_logger::init should not be called after logger initialized");
}
/// Attempts to initialize the global logger with an env logger from the given /// environment variables. /// /// This should be called early in the execution of a Rust program. Any log /// events that occur before initialization will be ignored. /// /// # Examples /// /// Initialise a logger using the `MY_LOG` environment variable for filters /// and `MY_LOG_STYLE` for writing colors: /// /// ``` /// use env_logger::{Builder, Env}; /// /// # fn run() -> Result<(), Box<dyn ::std::error::Error>> { /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); /// /// env_logger::try_init_from_env(env)?; /// /// Ok(()) /// # } /// # run().unwrap(); /// ``` /// /// # Errors /// /// This function will fail if it is called more than once, or if another /// library has already initialized a global logger. pubfn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError> where
E: Into<Env<'a>>,
{ letmut builder = Builder::from_env(env);
builder.try_init()
}
/// Initializes the global logger with an env logger from the given environment /// variables. /// /// This should be called early in the execution of a Rust program. Any log /// events that occur before initialization will be ignored. /// /// # Examples /// /// Initialise a logger using the `MY_LOG` environment variable for filters /// and `MY_LOG_STYLE` for writing colors: /// /// ``` /// use env_logger::{Builder, Env}; /// /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); /// /// env_logger::init_from_env(env); /// ``` /// /// # Panics /// /// This function will panic if it is called more than once, or if another /// library has already initialized a global logger. pubfn init_from_env<'a, E>(env: E) where
E: Into<Env<'a>>,
{
try_init_from_env(env)
.expect("env_logger::init_from_env should not be called after logger initialized");
}
/// Create a new builder with the default environment variables. /// /// The builder can be configured before being initialized. /// This is a convenient way of calling [`Builder::from_default_env`]. /// /// [`Builder::from_default_env`]: struct.Builder.html#method.from_default_env pubfn builder() -> Builder {
Builder::from_default_env()
}
/// Create a builder from the given environment variables. /// /// The builder can be configured before being initialized. #[deprecated(
since = "0.8.0",
note = "Prefer `env_logger::Builder::from_env()` instead."
)] pubfn from_env<'a, E>(env: E) -> Builder where
E: Into<Env<'a>>,
{
Builder::from_env(env)
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.