doc: Runnable examples logging.

Also use //! Instead of /*! in liblog.
This commit is contained in:
Jonas Hietala 2014-08-29 12:00:39 +02:00
parent dee8423531
commit 26b40be7ed
2 changed files with 236 additions and 141 deletions

View File

@ -8,120 +8,154 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*!
Utilities for program-wide and customizable logging
## Example
```
#![feature(phase)]
#[phase(plugin, link)] extern crate log;
fn main() {
debug!("this is a debug {}", "message");
error!("this is printed by default");
if log_enabled!(log::INFO) {
let x = 3i * 4i; // expensive computation
info!("the answer was: {}", x);
}
}
```
## Logging Macros
There are five macros that the logging subsystem uses:
* `log!(level, ...)` - the generic logging macro, takes a level as a u32 and any
related `format!` arguments
* `debug!(...)` - a macro hard-wired to the log level of `DEBUG`
* `info!(...)` - a macro hard-wired to the log level of `INFO`
* `warn!(...)` - a macro hard-wired to the log level of `WARN`
* `error!(...)` - a macro hard-wired to the log level of `ERROR`
All of these macros use the same style of syntax as the `format!` syntax
extension. Details about the syntax can be found in the documentation of
`std::fmt` along with the Rust tutorial/manual.
If you want to check at runtime if a given logging level is enabled (e.g. if the
information you would want to log is expensive to produce), you can use the
following macro:
* `log_enabled!(level)` - returns true if logging of the given level is enabled
## Enabling logging
Log levels are controlled on a per-module basis, and by default all logging is
disabled except for `error!` (a log level of 1). 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
path::to::module=log_level
```
The path to the module is rooted in the name of the crate it was compiled for,
so if your program is contained in a file `hello.rs`, for example, to turn on
logging for this file you would use a value of `RUST_LOG=hello`.
Furthermore, this path is a prefix-search, so all modules nested in the
specified module will also have logging enabled.
The actual `log_level` is optional to specify. If omitted, all logging will be
enabled. If specified, the it must be either a numeric in the range of 1-255, or
it must be one of the strings `debug`, `error`, `info`, or `warn`. If a numeric
is specified, then all logging less than or equal to that numeral is enabled.
For example, if logging level 3 is active, error, warn, and info logs will be
printed, but debug will be omitted.
As the log level for a module is optional, the module to enable logging for is
also optional. If only a `log_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
* `info` turns on all info logging
* `hello=debug` turns on debug logging for 'hello'
* `hello=3` turns on info logging for 'hello'
* `hello,std::option` turns on hello, and std's option logging
* `error,hello=warn` turn on global error logging and also warn for hello
## 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 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'
## Performance and Side Effects
Each of these macros will expand to code similar to:
```rust,ignore
if log_level <= my_module_log_level() {
::log::log(log_level, format!(...));
}
```
What this means is that each of these macros are very cheap at runtime if
they're turned off (just a load and an integer comparison). This also means that
if logging is disabled, none of the components of the log will be executed.
*/
//! Utilities for program-wide and customizable logging
//!
//! ## Example
//!
//! ```
//! #![feature(phase)]
//! #[phase(plugin, link)] extern crate log;
//!
//! fn main() {
//! debug!("this is a debug {}", "message");
//! error!("this is printed by default");
//!
//! if log_enabled!(log::INFO) {
//! let x = 3i * 4i; // expensive computation
//! info!("the answer was: {}", x);
//! }
//! }
//! ```
//!
//! Assumes the binary is `main`:
//!
//! ```{.bash}
//! $ RUST_LOG=error ./main
//! ERROR:main: this is printed by default
//! ```
//!
//! ```{.bash}
//! $ RUST_LOG=info ./main
//! ERROR:main: this is printed by default
//! INFO:main: the answer was: 12
//! ```
//!
//! ```{.bash}
//! $ RUST_LOG=debug ./main
//! DEBUG:main: this is a debug message
//! ERROR:main: this is printed by default
//! INFO:main: the answer was: 12
//! ```
//!
//! You can also set the log level on a per module basis:
//!
//! ```{.bash}
//! $ RUST_LOG=main=info ./main
//! ERROR:main: this is printed by default
//! INFO:main: the answer was: 12
//! ```
//!
//! And enable all logging:
//!
//! ```{.bash}
//! $ RUST_LOG=main ./main
//! DEBUG:main: this is a debug message
//! ERROR:main: this is printed by default
//! INFO:main: the answer was: 12
//! ```
//!
//!
//! ## Logging Macros
//!
//! There are five macros that the logging subsystem uses:
//!
//! * `log!(level, ...)` - the generic logging macro, takes a level as a u32 and any
//! related `format!` arguments
//! * `debug!(...)` - a macro hard-wired to the log level of `DEBUG`
//! * `info!(...)` - a macro hard-wired to the log level of `INFO`
//! * `warn!(...)` - a macro hard-wired to the log level of `WARN`
//! * `error!(...)` - a macro hard-wired to the log level of `ERROR`
//!
//! All of these macros use the same style of syntax as the `format!` syntax
//! extension. Details about the syntax can be found in the documentation of
//! `std::fmt` along with the Rust tutorial/manual.
//!
//! If you want to check at runtime if a given logging level is enabled (e.g. if the
//! information you would want to log is expensive to produce), you can use the
//! following macro:
//!
//! * `log_enabled!(level)` - returns true if logging of the given level is enabled
//!
//! ## Enabling logging
//!
//! Log levels are controlled on a per-module basis, and by default all logging is
//! disabled except for `error!` (a log level of 1). 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
//! path::to::module=log_level
//! ```
//!
//! The path to the module is rooted in the name of the crate it was compiled for,
//! so if your program is contained in a file `hello.rs`, for example, to turn on
//! logging for this file you would use a value of `RUST_LOG=hello`.
//! Furthermore, this path is a prefix-search, so all modules nested in the
//! specified module will also have logging enabled.
//!
//! The actual `log_level` is optional to specify. If omitted, all logging will be
//! enabled. If specified, the it must be either a numeric in the range of 1-255, or
//! it must be one of the strings `debug`, `error`, `info`, or `warn`. If a numeric
//! is specified, then all logging less than or equal to that numeral is enabled.
//! For example, if logging level 3 is active, error, warn, and info logs will be
//! printed, but debug will be omitted.
//!
//! As the log level for a module is optional, the module to enable logging for is
//! also optional. If only a `log_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
//! * `info` turns on all info logging
//! * `hello=debug` turns on debug logging for 'hello'
//! * `hello=3` turns on info logging for 'hello'
//! * `hello,std::option` turns on hello, and std's option logging
//! * `error,hello=warn` turn on global error logging and also warn for hello
//!
//! ## 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 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'
//!
//! ## Performance and Side Effects
//!
//! Each of these macros will expand to code similar to:
//!
//! ```rust,ignore
//! if log_level <= my_module_log_level() {
//! ::log::log(log_level, format!(...));
//! }
//! ```
//!
//! What this means is that each of these macros are very cheap at runtime if
//! they're turned off (just a load and an integer comparison). This also means that
//! if logging is disabled, none of the components of the log will be executed.
#![crate_name = "log"]
#![experimental]

View File

@ -24,11 +24,31 @@
/// #![feature(phase)]
/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// log!(log::DEBUG, "this is a debug message");
/// log!(log::WARN, "this is a warning {}", "message");
/// log!(6, "this is a custom logging level: {level}", level=6u);
/// # }
/// fn main() {
/// log!(log::WARN, "this is a warning {}", "message");
/// log!(log::DEBUG, "this is a debug message");
/// log!(6, "this is a custom logging level: {level}", level=6u);
/// }
/// ```
///
/// Assumes the binary is `main`:
///
/// ```{.bash}
/// $ RUST_LOG=warn ./main
/// WARN:main: this is a warning message
/// ```
///
/// ```{.bash}
/// $ RUST_LOG=debug ./main
/// DEBUG:main: this is a debug message
/// WARN:main: this is a warning message
/// ```
///
/// ```{.bash}
/// $ RUST_LOG=6 ./main
/// DEBUG:main: this is a debug message
/// WARN:main: this is a warning message
/// 6:main: this is a custom logging level: 6
/// ```
#[macro_export]
macro_rules! log(
@ -53,11 +73,19 @@ macro_rules! log(
/// #![feature(phase)]
/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// # let error = 3u;
/// error!("the build has failed with error code: {}", error);
/// # }
/// fn main() {
/// let error = 3u;
/// error!("the build has failed with error code: {}", error);
/// }
/// ```
///
/// Assumes the binary is `main`:
///
/// ```{.bash}
/// $ RUST_LOG=error ./main
/// ERROR:main: the build has failed with error code: 3
/// ```
///
#[macro_export]
macro_rules! error(
($($arg:tt)*) => (log!(::log::ERROR, $($arg)*))
@ -71,10 +99,17 @@ macro_rules! error(
/// #![feature(phase)]
/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// # let code = 3u;
/// warn!("you may like to know that a process exited with: {}", code);
/// # }
/// fn main() {
/// let code = 3u;
/// warn!("you may like to know that a process exited with: {}", code);
/// }
/// ```
///
/// Assumes the binary is `main`:
///
/// ```{.bash}
/// $ RUST_LOG=warn ./main
/// WARN:main: you may like to know that a process exited with: 3
/// ```
#[macro_export]
macro_rules! warn(
@ -89,10 +124,17 @@ macro_rules! warn(
/// #![feature(phase)]
/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// # let ret = 3i;
/// info!("this function is about to return: {}", ret);
/// # }
/// fn main() {
/// let ret = 3i;
/// info!("this function is about to return: {}", ret);
/// }
/// ```
///
/// Assumes the binary is `main`:
///
/// ```{.bash}
/// $ RUST_LOG=info ./main
/// INFO:main: this function is about to return: 3
/// ```
#[macro_export]
macro_rules! info(
@ -109,9 +151,16 @@ macro_rules! info(
/// #![feature(phase)]
/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// debug!("x = {x}, y = {y}", x=10i, y=20i);
/// # }
/// fn main() {
/// debug!("x = {x}, y = {y}", x=10i, y=20i);
/// }
/// ```
///
/// Assumes the binary is `main`:
///
/// ```{.bash}
/// $ RUST_LOG=debug ./main
/// DEBUG:main: x = 10, y = 20
/// ```
#[macro_export]
macro_rules! debug(
@ -126,14 +175,26 @@ macro_rules! debug(
/// #![feature(phase)]
/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// # struct Point { x: int, y: int }
/// # fn some_expensive_computation() -> Point { Point { x: 1, y: 2 } }
/// if log_enabled!(log::DEBUG) {
/// let x = some_expensive_computation();
/// debug!("x.x = {}, x.y = {}", x.x, x.y);
/// struct Point { x: int, y: int }
/// fn some_expensive_computation() -> Point { Point { x: 1, y: 2 } }
///
/// fn main() {
/// if log_enabled!(log::DEBUG) {
/// let x = some_expensive_computation();
/// debug!("x.x = {}, x.y = {}", x.x, x.y);
/// }
/// }
/// # }
/// ```
///
/// Assumes the binary is `main`:
///
/// ```{.bash}
/// $ RUST_LOG=error ./main
/// ```
///
/// ```{.bash}
/// $ RUST_LOG=debug ./main
/// DEBUG:main: x.x = 1, x.y = 2
/// ```
#[macro_export]
macro_rules! log_enabled(