Skip to content
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ features = ["std", "serde"]
name = "filters"
harness = false

[[test]]
name = "log_v"
harness = false

[features]
max_level_off = []
max_level_error = []
Expand Down
205 changes: 155 additions & 50 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,149 @@
//! by this crate, and the consumer of those libraries can choose the logging
//! implementation that is most suitable for its use case.
//!
//! If no logging implementation is selected, the facade falls back to a "noop"
//! implementation that ignores all log messages. The overhead in this case
//! is very small - just an integer load, comparison and jump.
//! If no logging implementation is selected, the facade falls back to a
//! _no-op_ implementation that ignores all log messages. The overhead in this
//! case is very smalljust an integer load, comparison and jump.
//!
//! A log request consists of a _target_, a _level_, and a _body_. A target is a
//! string which defaults to the module path of the location of the log request,
//! though that default may be overridden. Logger implementations typically use
//! the target to filter requests based on some user configuration.
//! A log `Record` includes a target, level, and message body. Logger
//! implementations typically use the target and level to filter records,
//! based on user configuration.
//!
//! # Use
//! ## Logging macros
//!
//! The basic use of the log crate is through the five logging macros: [`error!`],
//! [`warn!`], [`info!`], [`debug!`] and [`trace!`]
//! where `error!` represents the highest-priority log messages
//! and `trace!` the lowest. The log messages are filtered by configuring
//! the log level to exclude messages with a lower priority.
//! Each of these macros accept format strings similarly to [`println!`].
//! The `log` crate is primarly used through logging [macros](#macros). These
//! include formatted logging macros for each of the supported levels, from
//! highest to lowest priority: `error!`, `warn!`, `info!`, `debug!` and
//! `trace!`. There is an additional set of “_-v_” suffix macros
//! (e.g. `debugv!`) that provide _inline expression and value_ logging. Both
//! sets of macros are described below, with examples using aribitrary log
//! levels.
//!
//! ### Formatted logging
//!
//! [`error!`]: ./macro.error.html
//! [`warn!`]: ./macro.warn.html
//! [`info!`]: ./macro.info.html
//! [`debug!`]: ./macro.debug.html
//! [`trace!`]: ./macro.trace.html
//! [`println!`]: https://doc.rust-lang.org/stable/std/macro.println.html
//! The formatted logging macros require a literal format string, supporting
//! the same syntax as `println!`, via [`std::fmt`]:
//!
//! ## In libraries
//! ```rust
//! # #[macro_use] extern crate log;
//! # fn main() {
//! info!("Landing gear retracted");
//! let altitude = 3000;
//! let target = 10500;
//! debug!("Altitude target: {}, current: {}", target, altitude);
//! # }
//! ```
//!
//! If for example, the configured maximum logging level is `Info`, then the
//! above `debug!` statement does not log, and the cost of formatting the
//! message string is avoided.
//!
//! ### Testing for output
//!
//! The [`log_enabled!`](macro.log_enabled.html) macro may be used to
//! explicitly test if logging is enabled, and may be useful to avoid
//! expensive computations used only for logging.
//!
//! Libraries should link only to the `log` crate, and use the provided
//! macros to log whatever information will be useful to downstream consumers.
//! ```rust
//! # #[macro_use] extern crate log;
//! # struct Foo;
//! # impl Foo {
//! # fn volume(&self) -> f32 { 0.1 }
//! # fn mass(&self) -> f32 { 0.2 }
//! # }
//! # fn analyze(a: u32) -> Foo { Foo }
//! use log::Level::Debug;
//! # fn main() {
//!
//! # let asteroid = 1;
//! if log_enabled!(Debug) {
//! let e = analyze(asteroid); // expensive!
//! debug!("Asteroid volume: {}, mass: {}", e.volume(), e.mass());
//! }
//! # }
//! ```
//!
//! ### Inline expression and value logging
//!
//! The _-v_ macros support inline expression and value logging. A _single_
//! expression argument is evaluated exactly once, regardless of if the
//! logging level is enabled, and its value is returned from the macro. Given
//! this code as a starting point:
//!
//! ```rust
//! # fn main() {
//! let n = 12;
//! let m = n / 2 - 1;
//! assert_eq!(m, 5);
//! # }
//! ```
//!
//! The `debugv!` macro may be inserted inline around any expression or
//! sub-expression:
//!
//! ```rust
//! # #[macro_use] extern crate log;
//! # fn main() {
//! let n = 12;
//! let m = debugv!(n / 2) - 1;
//! // ^-- debug log message: "n / 2 = 6"
//! assert_eq!(m, 5);
//! # }
//! ```
//!
//! This feature is a superset of the [`std::dbg!`] macro for the logging
//! system. Note that the value of the expression is moved and then
//! returned. The type must implement `Copy`, but this includes immutable
//! references to non-`Copy` types.
//!
//! The _default_ format string for the _-v_ macros is `"{} = {:?}"`, where
//! the `stringify!`-ed expression and resulting value are passed, in that
//! order. If the log record is not filtered out, the `Debug` implementation
//! for the type of the given expression value is used (`{:?}`). A custom
//! format string can _also_ be passed to the _-v_ macros, for more flexible
//! output:
//!
//! ```rust
//! # #![allow(unstable)]
//! # #[macro_use] extern crate log;
//! # fn main() {
//! let i = 32;
//! infov!("{} = {}", i); // use `Display` instead of `Debug`
//! infov!("{} = {:x}", i); // hexadecimal format value
//! infov!("{} = {:#?}", i); // use pretty, multi-line format
//! infov!("index {1:5?} ({0})", i); // prefix, value first with padding
//! # }
//! ```
//!
//! ### Specifying the logging target
//!
//! For _all_ logging macros, the _target_ defaults to the module path of the
//! current location of use, but may be overridden with the `target:` marker
//! and string literal as the first argument:
//!
//! ```rust
//! # #[macro_use] extern crate log;
//! # fn stats() -> i32 { 33 }
//! # fn main() {
//! use log::Level::Info;
//!
//! let i = 33;
//! let j = warnv!(target: "maths", (i-1) / 2);
//! assert_eq!(j, 16);
//!
//! if log_enabled!(target: "special", Info) {
//! info!(target: "special", "{}", stats());
//! }
//! # }
//! ```
//!
//! [`std::fmt`]: https://doc.rust-lang.org/stable/std/fmt/index.html
//! [`std::dbg!`]: https://doc.rust-lang.org/std/macro.dbg.html
//!
//! ## Use in libraries
//!
//! Libraries should link only to the `log` crate, and use the provided macros
//! to log whatever information will be useful to downstream consumers.
//!
//! ### Examples
//!
Expand Down Expand Up @@ -75,25 +188,22 @@
//! # fn main() {}
//! ```
//!
//! ## In executables
//!
//! Executables should choose a logging implementation and initialize it early in the
//! runtime of the program. Logging implementations will typically include a
//! function to do this. Any log messages generated before
//! the implementation is initialized will be ignored.
//! ## Use in executables
//!
//! The executable itself may use the `log` crate to log as well.
//! Executables should choose a logging implementation and initialize it early
//! in the runtime of the program. Logging implementations will typically
//! include a function to do this. Any log messages generated before the
//! implementation is initialized will be ignored.
//!
//! ### Warning
//! _Warning_: The logging system may only be initialized once.
//!
//! The logging system may only be initialized once.
//! The executable may also use the `log` crate to log.
//!
//! # Available logging implementations
//! ### Available logging implementations
//!
//! In order to produce log output executables have to use
//! a logger implementation compatible with the facade.
//! There are many available implementations to choose from,
//! here are some of the most popular ones:
//! In order to produce log output executables have to use a logger
//! implementation compatible with the facade. There are many available
//! implementations to choose from, here are some of the most popular ones:
//!
//! * Simple minimal loggers:
//! * [env_logger]
Expand All @@ -109,7 +219,7 @@
//! * [syslog]
//! * [slog-stdlog]
//!
//! # Implementing a Logger
//! ### Implementing a Logger
//!
//! Loggers implement the [`Log`] trait. Here's a very basic example that simply
//! logs all messages at the [`Error`][level_link], [`Warn`][level_link] or
Expand Down Expand Up @@ -173,7 +283,7 @@
//! Implementations that adjust their configurations at runtime should take care
//! to adjust the maximum log level as well.
//!
//! # Use with `std`
//! ### Use with `std`
//!
//! `set_logger` requires you to provide a `&'static Log`, which can be hard to
//! obtain if your logger depends on some runtime configuration. The
Expand Down Expand Up @@ -220,7 +330,7 @@
//!
//! These features control the value of the `STATIC_MAX_LEVEL` constant. The logging macros check
//! this value before logging a message. By default, no levels are disabled.
//!
//!
//! Libraries should avoid using the max level features because they're global and can't be changed
//! once they're set.
//!
Expand Down Expand Up @@ -679,7 +789,8 @@ impl LevelFilter {
/// `Record` structures are passed as parameters to the [`log`][method.log]
/// method of the [`Log`] trait. Logger implementors manipulate these
/// structures in order to display log messages. `Record`s are automatically
/// created by the [`log!`] macro and so are not seen by log users.
/// created by the various logging macros and so are not typically seen
/// directly by `log` users.
///
/// Note that the [`level()`] and [`target()`] accessors are equivalent to
/// `self.metadata().level()` and `self.metadata().target()` respectively.
Expand Down Expand Up @@ -1073,16 +1184,10 @@ pub fn set_max_level(level: LevelFilter) {

/// Returns the current maximum log level.
///
/// The [`log!`], [`error!`], [`warn!`], [`info!`], [`debug!`], and [`trace!`] macros check
/// this value and discard any message logged at a higher level. The maximum
/// log level is set by the [`set_max_level`] function.
/// The logging macros check this value and discard any message logged at a
/// higher level. The maximum log level is set by the [`set_max_level`]
/// function.
///
/// [`log!`]: macro.log.html
/// [`error!`]: macro.error.html
/// [`warn!`]: macro.warn.html
/// [`info!`]: macro.info.html
/// [`debug!`]: macro.debug.html
/// [`trace!`]: macro.trace.html
/// [`set_max_level`]: fn.set_max_level.html
#[inline(always)]
pub fn max_level() -> LevelFilter {
Expand Down
Loading