12d8ae3abSopenharmony_ci// Copyright 2015 The Rust Project Developers. See the COPYRIGHT 22d8ae3abSopenharmony_ci// file at the top-level directory of this distribution and at 32d8ae3abSopenharmony_ci// http://rust-lang.org/COPYRIGHT. 42d8ae3abSopenharmony_ci// 52d8ae3abSopenharmony_ci// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 62d8ae3abSopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 72d8ae3abSopenharmony_ci// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 82d8ae3abSopenharmony_ci// option. This file may not be copied, modified, or distributed 92d8ae3abSopenharmony_ci// except according to those terms. 102d8ae3abSopenharmony_ci 112d8ae3abSopenharmony_ci//! A lightweight logging facade. 122d8ae3abSopenharmony_ci//! 132d8ae3abSopenharmony_ci//! The `log` crate provides a single logging API that abstracts over the 142d8ae3abSopenharmony_ci//! actual logging implementation. Libraries can use the logging API provided 152d8ae3abSopenharmony_ci//! by this crate, and the consumer of those libraries can choose the logging 162d8ae3abSopenharmony_ci//! implementation that is most suitable for its use case. 172d8ae3abSopenharmony_ci//! 182d8ae3abSopenharmony_ci//! If no logging implementation is selected, the facade falls back to a "noop" 192d8ae3abSopenharmony_ci//! implementation that ignores all log messages. The overhead in this case 202d8ae3abSopenharmony_ci//! is very small - just an integer load, comparison and jump. 212d8ae3abSopenharmony_ci//! 222d8ae3abSopenharmony_ci//! A log request consists of a _target_, a _level_, and a _body_. A target is a 232d8ae3abSopenharmony_ci//! string which defaults to the module path of the location of the log request, 242d8ae3abSopenharmony_ci//! though that default may be overridden. Logger implementations typically use 252d8ae3abSopenharmony_ci//! the target to filter requests based on some user configuration. 262d8ae3abSopenharmony_ci//! 272d8ae3abSopenharmony_ci//! # Usage 282d8ae3abSopenharmony_ci//! 292d8ae3abSopenharmony_ci//! The basic use of the log crate is through the five logging macros: [`error!`], 302d8ae3abSopenharmony_ci//! [`warn!`], [`info!`], [`debug!`] and [`trace!`] 312d8ae3abSopenharmony_ci//! where `error!` represents the highest-priority log messages 322d8ae3abSopenharmony_ci//! and `trace!` the lowest. The log messages are filtered by configuring 332d8ae3abSopenharmony_ci//! the log level to exclude messages with a lower priority. 342d8ae3abSopenharmony_ci//! Each of these macros accept format strings similarly to [`println!`]. 352d8ae3abSopenharmony_ci//! 362d8ae3abSopenharmony_ci//! 372d8ae3abSopenharmony_ci//! [`error!`]: ./macro.error.html 382d8ae3abSopenharmony_ci//! [`warn!`]: ./macro.warn.html 392d8ae3abSopenharmony_ci//! [`info!`]: ./macro.info.html 402d8ae3abSopenharmony_ci//! [`debug!`]: ./macro.debug.html 412d8ae3abSopenharmony_ci//! [`trace!`]: ./macro.trace.html 422d8ae3abSopenharmony_ci//! [`println!`]: https://doc.rust-lang.org/stable/std/macro.println.html 432d8ae3abSopenharmony_ci//! 442d8ae3abSopenharmony_ci//! ## In libraries 452d8ae3abSopenharmony_ci//! 462d8ae3abSopenharmony_ci//! Libraries should link only to the `log` crate, and use the provided 472d8ae3abSopenharmony_ci//! macros to log whatever information will be useful to downstream consumers. 482d8ae3abSopenharmony_ci//! 492d8ae3abSopenharmony_ci//! ### Examples 502d8ae3abSopenharmony_ci//! 512d8ae3abSopenharmony_ci//! ```edition2018 522d8ae3abSopenharmony_ci//! # #[derive(Debug)] pub struct Yak(String); 532d8ae3abSopenharmony_ci//! # impl Yak { fn shave(&mut self, _: u32) {} } 542d8ae3abSopenharmony_ci//! # fn find_a_razor() -> Result<u32, u32> { Ok(1) } 552d8ae3abSopenharmony_ci//! use log::{info, warn}; 562d8ae3abSopenharmony_ci//! 572d8ae3abSopenharmony_ci//! pub fn shave_the_yak(yak: &mut Yak) { 582d8ae3abSopenharmony_ci//! info!(target: "yak_events", "Commencing yak shaving for {:?}", yak); 592d8ae3abSopenharmony_ci//! 602d8ae3abSopenharmony_ci//! loop { 612d8ae3abSopenharmony_ci//! match find_a_razor() { 622d8ae3abSopenharmony_ci//! Ok(razor) => { 632d8ae3abSopenharmony_ci//! info!("Razor located: {}", razor); 642d8ae3abSopenharmony_ci//! yak.shave(razor); 652d8ae3abSopenharmony_ci//! break; 662d8ae3abSopenharmony_ci//! } 672d8ae3abSopenharmony_ci//! Err(err) => { 682d8ae3abSopenharmony_ci//! warn!("Unable to locate a razor: {}, retrying", err); 692d8ae3abSopenharmony_ci//! } 702d8ae3abSopenharmony_ci//! } 712d8ae3abSopenharmony_ci//! } 722d8ae3abSopenharmony_ci//! } 732d8ae3abSopenharmony_ci//! # fn main() {} 742d8ae3abSopenharmony_ci//! ``` 752d8ae3abSopenharmony_ci//! 762d8ae3abSopenharmony_ci//! ## In executables 772d8ae3abSopenharmony_ci//! 782d8ae3abSopenharmony_ci//! Executables should choose a logging implementation and initialize it early in the 792d8ae3abSopenharmony_ci//! runtime of the program. Logging implementations will typically include a 802d8ae3abSopenharmony_ci//! function to do this. Any log messages generated before 812d8ae3abSopenharmony_ci//! the implementation is initialized will be ignored. 822d8ae3abSopenharmony_ci//! 832d8ae3abSopenharmony_ci//! The executable itself may use the `log` crate to log as well. 842d8ae3abSopenharmony_ci//! 852d8ae3abSopenharmony_ci//! ### Warning 862d8ae3abSopenharmony_ci//! 872d8ae3abSopenharmony_ci//! The logging system may only be initialized once. 882d8ae3abSopenharmony_ci//! 892d8ae3abSopenharmony_ci//! ## Structured logging 902d8ae3abSopenharmony_ci//! 912d8ae3abSopenharmony_ci//! If you enable the `kv_unstable` feature you can associate structured values 922d8ae3abSopenharmony_ci//! with your log records. If we take the example from before, we can include 932d8ae3abSopenharmony_ci//! some additional context besides what's in the formatted message: 942d8ae3abSopenharmony_ci//! 952d8ae3abSopenharmony_ci//! ```edition2018 962d8ae3abSopenharmony_ci//! # #[macro_use] extern crate serde; 972d8ae3abSopenharmony_ci//! # #[derive(Debug, Serialize)] pub struct Yak(String); 982d8ae3abSopenharmony_ci//! # impl Yak { fn shave(&mut self, _: u32) {} } 992d8ae3abSopenharmony_ci//! # fn find_a_razor() -> Result<u32, std::io::Error> { Ok(1) } 1002d8ae3abSopenharmony_ci//! # #[cfg(feature = "kv_unstable_serde")] 1012d8ae3abSopenharmony_ci//! # fn main() { 1022d8ae3abSopenharmony_ci//! use log::{info, warn, as_serde, as_error}; 1032d8ae3abSopenharmony_ci//! 1042d8ae3abSopenharmony_ci//! pub fn shave_the_yak(yak: &mut Yak) { 1052d8ae3abSopenharmony_ci//! info!(target: "yak_events", yak = as_serde!(yak); "Commencing yak shaving"); 1062d8ae3abSopenharmony_ci//! 1072d8ae3abSopenharmony_ci//! loop { 1082d8ae3abSopenharmony_ci//! match find_a_razor() { 1092d8ae3abSopenharmony_ci//! Ok(razor) => { 1102d8ae3abSopenharmony_ci//! info!(razor = razor; "Razor located"); 1112d8ae3abSopenharmony_ci//! yak.shave(razor); 1122d8ae3abSopenharmony_ci//! break; 1132d8ae3abSopenharmony_ci//! } 1142d8ae3abSopenharmony_ci//! Err(err) => { 1152d8ae3abSopenharmony_ci//! warn!(err = as_error!(err); "Unable to locate a razor, retrying"); 1162d8ae3abSopenharmony_ci//! } 1172d8ae3abSopenharmony_ci//! } 1182d8ae3abSopenharmony_ci//! } 1192d8ae3abSopenharmony_ci//! } 1202d8ae3abSopenharmony_ci//! # } 1212d8ae3abSopenharmony_ci//! # #[cfg(not(feature = "kv_unstable_serde"))] 1222d8ae3abSopenharmony_ci//! # fn main() {} 1232d8ae3abSopenharmony_ci//! ``` 1242d8ae3abSopenharmony_ci//! 1252d8ae3abSopenharmony_ci//! # Available logging implementations 1262d8ae3abSopenharmony_ci//! 1272d8ae3abSopenharmony_ci//! In order to produce log output executables have to use 1282d8ae3abSopenharmony_ci//! a logger implementation compatible with the facade. 1292d8ae3abSopenharmony_ci//! There are many available implementations to choose from, 1302d8ae3abSopenharmony_ci//! here are some of the most popular ones: 1312d8ae3abSopenharmony_ci//! 1322d8ae3abSopenharmony_ci//! * Simple minimal loggers: 1332d8ae3abSopenharmony_ci//! * [env_logger] 1342d8ae3abSopenharmony_ci//! * [simple_logger] 1352d8ae3abSopenharmony_ci//! * [simplelog] 1362d8ae3abSopenharmony_ci//! * [pretty_env_logger] 1372d8ae3abSopenharmony_ci//! * [stderrlog] 1382d8ae3abSopenharmony_ci//! * [flexi_logger] 1392d8ae3abSopenharmony_ci//! * Complex configurable frameworks: 1402d8ae3abSopenharmony_ci//! * [log4rs] 1412d8ae3abSopenharmony_ci//! * [fern] 1422d8ae3abSopenharmony_ci//! * Adaptors for other facilities: 1432d8ae3abSopenharmony_ci//! * [syslog] 1442d8ae3abSopenharmony_ci//! * [slog-stdlog] 1452d8ae3abSopenharmony_ci//! * [systemd-journal-logger] 1462d8ae3abSopenharmony_ci//! * [android_log] 1472d8ae3abSopenharmony_ci//! * [win_dbg_logger] 1482d8ae3abSopenharmony_ci//! * [db_logger] 1492d8ae3abSopenharmony_ci//! * For WebAssembly binaries: 1502d8ae3abSopenharmony_ci//! * [console_log] 1512d8ae3abSopenharmony_ci//! * For dynamic libraries: 1522d8ae3abSopenharmony_ci//! * You may need to construct an FFI-safe wrapper over `log` to initialize in your libraries 1532d8ae3abSopenharmony_ci//! 1542d8ae3abSopenharmony_ci//! # Implementing a Logger 1552d8ae3abSopenharmony_ci//! 1562d8ae3abSopenharmony_ci//! Loggers implement the [`Log`] trait. Here's a very basic example that simply 1572d8ae3abSopenharmony_ci//! logs all messages at the [`Error`][level_link], [`Warn`][level_link] or 1582d8ae3abSopenharmony_ci//! [`Info`][level_link] levels to stdout: 1592d8ae3abSopenharmony_ci//! 1602d8ae3abSopenharmony_ci//! ```edition2018 1612d8ae3abSopenharmony_ci//! use log::{Record, Level, Metadata}; 1622d8ae3abSopenharmony_ci//! 1632d8ae3abSopenharmony_ci//! struct SimpleLogger; 1642d8ae3abSopenharmony_ci//! 1652d8ae3abSopenharmony_ci//! impl log::Log for SimpleLogger { 1662d8ae3abSopenharmony_ci//! fn enabled(&self, metadata: &Metadata) -> bool { 1672d8ae3abSopenharmony_ci//! metadata.level() <= Level::Info 1682d8ae3abSopenharmony_ci//! } 1692d8ae3abSopenharmony_ci//! 1702d8ae3abSopenharmony_ci//! fn log(&self, record: &Record) { 1712d8ae3abSopenharmony_ci//! if self.enabled(record.metadata()) { 1722d8ae3abSopenharmony_ci//! println!("{} - {}", record.level(), record.args()); 1732d8ae3abSopenharmony_ci//! } 1742d8ae3abSopenharmony_ci//! } 1752d8ae3abSopenharmony_ci//! 1762d8ae3abSopenharmony_ci//! fn flush(&self) {} 1772d8ae3abSopenharmony_ci//! } 1782d8ae3abSopenharmony_ci//! 1792d8ae3abSopenharmony_ci//! # fn main() {} 1802d8ae3abSopenharmony_ci//! ``` 1812d8ae3abSopenharmony_ci//! 1822d8ae3abSopenharmony_ci//! Loggers are installed by calling the [`set_logger`] function. The maximum 1832d8ae3abSopenharmony_ci//! log level also needs to be adjusted via the [`set_max_level`] function. The 1842d8ae3abSopenharmony_ci//! logging facade uses this as an optimization to improve performance of log 1852d8ae3abSopenharmony_ci//! messages at levels that are disabled. It's important to set it, as it 1862d8ae3abSopenharmony_ci//! defaults to [`Off`][filter_link], so no log messages will ever be captured! 1872d8ae3abSopenharmony_ci//! In the case of our example logger, we'll want to set the maximum log level 1882d8ae3abSopenharmony_ci//! to [`Info`][filter_link], since we ignore any [`Debug`][level_link] or 1892d8ae3abSopenharmony_ci//! [`Trace`][level_link] level log messages. A logging implementation should 1902d8ae3abSopenharmony_ci//! provide a function that wraps a call to [`set_logger`] and 1912d8ae3abSopenharmony_ci//! [`set_max_level`], handling initialization of the logger: 1922d8ae3abSopenharmony_ci//! 1932d8ae3abSopenharmony_ci//! ```edition2018 1942d8ae3abSopenharmony_ci//! # use log::{Level, Metadata}; 1952d8ae3abSopenharmony_ci//! # struct SimpleLogger; 1962d8ae3abSopenharmony_ci//! # impl log::Log for SimpleLogger { 1972d8ae3abSopenharmony_ci//! # fn enabled(&self, _: &Metadata) -> bool { false } 1982d8ae3abSopenharmony_ci//! # fn log(&self, _: &log::Record) {} 1992d8ae3abSopenharmony_ci//! # fn flush(&self) {} 2002d8ae3abSopenharmony_ci//! # } 2012d8ae3abSopenharmony_ci//! # fn main() {} 2022d8ae3abSopenharmony_ci//! use log::{SetLoggerError, LevelFilter}; 2032d8ae3abSopenharmony_ci//! 2042d8ae3abSopenharmony_ci//! static LOGGER: SimpleLogger = SimpleLogger; 2052d8ae3abSopenharmony_ci//! 2062d8ae3abSopenharmony_ci//! pub fn init() -> Result<(), SetLoggerError> { 2072d8ae3abSopenharmony_ci//! log::set_logger(&LOGGER) 2082d8ae3abSopenharmony_ci//! .map(|()| log::set_max_level(LevelFilter::Info)) 2092d8ae3abSopenharmony_ci//! } 2102d8ae3abSopenharmony_ci//! ``` 2112d8ae3abSopenharmony_ci//! 2122d8ae3abSopenharmony_ci//! Implementations that adjust their configurations at runtime should take care 2132d8ae3abSopenharmony_ci//! to adjust the maximum log level as well. 2142d8ae3abSopenharmony_ci//! 2152d8ae3abSopenharmony_ci//! # Use with `std` 2162d8ae3abSopenharmony_ci//! 2172d8ae3abSopenharmony_ci//! `set_logger` requires you to provide a `&'static Log`, which can be hard to 2182d8ae3abSopenharmony_ci//! obtain if your logger depends on some runtime configuration. The 2192d8ae3abSopenharmony_ci//! `set_boxed_logger` function is available with the `std` Cargo feature. It is 2202d8ae3abSopenharmony_ci//! identical to `set_logger` except that it takes a `Box<Log>` rather than a 2212d8ae3abSopenharmony_ci//! `&'static Log`: 2222d8ae3abSopenharmony_ci//! 2232d8ae3abSopenharmony_ci//! ```edition2018 2242d8ae3abSopenharmony_ci//! # use log::{Level, LevelFilter, Log, SetLoggerError, Metadata}; 2252d8ae3abSopenharmony_ci//! # struct SimpleLogger; 2262d8ae3abSopenharmony_ci//! # impl log::Log for SimpleLogger { 2272d8ae3abSopenharmony_ci//! # fn enabled(&self, _: &Metadata) -> bool { false } 2282d8ae3abSopenharmony_ci//! # fn log(&self, _: &log::Record) {} 2292d8ae3abSopenharmony_ci//! # fn flush(&self) {} 2302d8ae3abSopenharmony_ci//! # } 2312d8ae3abSopenharmony_ci//! # fn main() {} 2322d8ae3abSopenharmony_ci//! # #[cfg(feature = "std")] 2332d8ae3abSopenharmony_ci//! pub fn init() -> Result<(), SetLoggerError> { 2342d8ae3abSopenharmony_ci//! log::set_boxed_logger(Box::new(SimpleLogger)) 2352d8ae3abSopenharmony_ci//! .map(|()| log::set_max_level(LevelFilter::Info)) 2362d8ae3abSopenharmony_ci//! } 2372d8ae3abSopenharmony_ci//! ``` 2382d8ae3abSopenharmony_ci//! 2392d8ae3abSopenharmony_ci//! # Compile time filters 2402d8ae3abSopenharmony_ci//! 2412d8ae3abSopenharmony_ci//! Log levels can be statically disabled at compile time via Cargo features. Log invocations at 2422d8ae3abSopenharmony_ci//! disabled levels will be skipped and will not even be present in the resulting binary. 2432d8ae3abSopenharmony_ci//! This level is configured separately for release and debug builds. The features are: 2442d8ae3abSopenharmony_ci//! 2452d8ae3abSopenharmony_ci//! * `max_level_off` 2462d8ae3abSopenharmony_ci//! * `max_level_error` 2472d8ae3abSopenharmony_ci//! * `max_level_warn` 2482d8ae3abSopenharmony_ci//! * `max_level_info` 2492d8ae3abSopenharmony_ci//! * `max_level_debug` 2502d8ae3abSopenharmony_ci//! * `max_level_trace` 2512d8ae3abSopenharmony_ci//! * `release_max_level_off` 2522d8ae3abSopenharmony_ci//! * `release_max_level_error` 2532d8ae3abSopenharmony_ci//! * `release_max_level_warn` 2542d8ae3abSopenharmony_ci//! * `release_max_level_info` 2552d8ae3abSopenharmony_ci//! * `release_max_level_debug` 2562d8ae3abSopenharmony_ci//! * `release_max_level_trace` 2572d8ae3abSopenharmony_ci//! 2582d8ae3abSopenharmony_ci//! These features control the value of the `STATIC_MAX_LEVEL` constant. The logging macros check 2592d8ae3abSopenharmony_ci//! this value before logging a message. By default, no levels are disabled. 2602d8ae3abSopenharmony_ci//! 2612d8ae3abSopenharmony_ci//! Libraries should avoid using the max level features because they're global and can't be changed 2622d8ae3abSopenharmony_ci//! once they're set. 2632d8ae3abSopenharmony_ci//! 2642d8ae3abSopenharmony_ci//! For example, a crate can disable trace level logs in debug builds and trace, debug, and info 2652d8ae3abSopenharmony_ci//! level logs in release builds with the following configuration: 2662d8ae3abSopenharmony_ci//! 2672d8ae3abSopenharmony_ci//! ```toml 2682d8ae3abSopenharmony_ci//! [dependencies] 2692d8ae3abSopenharmony_ci//! log = { version = "0.4", features = ["max_level_debug", "release_max_level_warn"] } 2702d8ae3abSopenharmony_ci//! ``` 2712d8ae3abSopenharmony_ci//! # Crate Feature Flags 2722d8ae3abSopenharmony_ci//! 2732d8ae3abSopenharmony_ci//! The following crate feature flags are available in addition to the filters. They are 2742d8ae3abSopenharmony_ci//! configured in your `Cargo.toml`. 2752d8ae3abSopenharmony_ci//! 2762d8ae3abSopenharmony_ci//! * `std` allows use of `std` crate instead of the default `core`. Enables using `std::error` and 2772d8ae3abSopenharmony_ci//! `set_boxed_logger` functionality. 2782d8ae3abSopenharmony_ci//! * `serde` enables support for serialization and deserialization of `Level` and `LevelFilter`. 2792d8ae3abSopenharmony_ci//! 2802d8ae3abSopenharmony_ci//! ```toml 2812d8ae3abSopenharmony_ci//! [dependencies] 2822d8ae3abSopenharmony_ci//! log = { version = "0.4", features = ["std", "serde"] } 2832d8ae3abSopenharmony_ci//! ``` 2842d8ae3abSopenharmony_ci//! 2852d8ae3abSopenharmony_ci//! # Version compatibility 2862d8ae3abSopenharmony_ci//! 2872d8ae3abSopenharmony_ci//! The 0.3 and 0.4 versions of the `log` crate are almost entirely compatible. Log messages 2882d8ae3abSopenharmony_ci//! made using `log` 0.3 will forward transparently to a logger implementation using `log` 0.4. Log 2892d8ae3abSopenharmony_ci//! messages made using `log` 0.4 will forward to a logger implementation using `log` 0.3, but the 2902d8ae3abSopenharmony_ci//! module path and file name information associated with the message will unfortunately be lost. 2912d8ae3abSopenharmony_ci//! 2922d8ae3abSopenharmony_ci//! [`Log`]: trait.Log.html 2932d8ae3abSopenharmony_ci//! [level_link]: enum.Level.html 2942d8ae3abSopenharmony_ci//! [filter_link]: enum.LevelFilter.html 2952d8ae3abSopenharmony_ci//! [`set_logger`]: fn.set_logger.html 2962d8ae3abSopenharmony_ci//! [`set_max_level`]: fn.set_max_level.html 2972d8ae3abSopenharmony_ci//! [`try_set_logger_raw`]: fn.try_set_logger_raw.html 2982d8ae3abSopenharmony_ci//! [`shutdown_logger_raw`]: fn.shutdown_logger_raw.html 2992d8ae3abSopenharmony_ci//! [env_logger]: https://docs.rs/env_logger/*/env_logger/ 3002d8ae3abSopenharmony_ci//! [simple_logger]: https://github.com/borntyping/rust-simple_logger 3012d8ae3abSopenharmony_ci//! [simplelog]: https://github.com/drakulix/simplelog.rs 3022d8ae3abSopenharmony_ci//! [pretty_env_logger]: https://docs.rs/pretty_env_logger/*/pretty_env_logger/ 3032d8ae3abSopenharmony_ci//! [stderrlog]: https://docs.rs/stderrlog/*/stderrlog/ 3042d8ae3abSopenharmony_ci//! [flexi_logger]: https://docs.rs/flexi_logger/*/flexi_logger/ 3052d8ae3abSopenharmony_ci//! [syslog]: https://docs.rs/syslog/*/syslog/ 3062d8ae3abSopenharmony_ci//! [slog-stdlog]: https://docs.rs/slog-stdlog/*/slog_stdlog/ 3072d8ae3abSopenharmony_ci//! [log4rs]: https://docs.rs/log4rs/*/log4rs/ 3082d8ae3abSopenharmony_ci//! [fern]: https://docs.rs/fern/*/fern/ 3092d8ae3abSopenharmony_ci//! [systemd-journal-logger]: https://docs.rs/systemd-journal-logger/*/systemd_journal_logger/ 3102d8ae3abSopenharmony_ci//! [android_log]: https://docs.rs/android_log/*/android_log/ 3112d8ae3abSopenharmony_ci//! [win_dbg_logger]: https://docs.rs/win_dbg_logger/*/win_dbg_logger/ 3122d8ae3abSopenharmony_ci//! [console_log]: https://docs.rs/console_log/*/console_log/ 3132d8ae3abSopenharmony_ci 3142d8ae3abSopenharmony_ci#![doc( 3152d8ae3abSopenharmony_ci html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", 3162d8ae3abSopenharmony_ci html_favicon_url = "https://www.rust-lang.org/favicon.ico", 3172d8ae3abSopenharmony_ci html_root_url = "https://docs.rs/log/0.4.17" 3182d8ae3abSopenharmony_ci)] 3192d8ae3abSopenharmony_ci#![allow(clippy::derive_hash_xor_eq)] 3202d8ae3abSopenharmony_ci#![warn(missing_docs)] 3212d8ae3abSopenharmony_ci#![deny(missing_debug_implementations, unconditional_recursion)] 3222d8ae3abSopenharmony_ci#![cfg_attr(all(not(feature = "std"), not(test)), no_std)] 3232d8ae3abSopenharmony_ci// When compiled for the rustc compiler itself we want to make sure that this is 3242d8ae3abSopenharmony_ci// an unstable crate 3252d8ae3abSopenharmony_ci#![cfg_attr(rustbuild, feature(staged_api, rustc_private))] 3262d8ae3abSopenharmony_ci#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))] 3272d8ae3abSopenharmony_ci 3282d8ae3abSopenharmony_ci#[cfg(all(not(feature = "std"), not(test)))] 3292d8ae3abSopenharmony_ciextern crate core as std; 3302d8ae3abSopenharmony_ci 3312d8ae3abSopenharmony_ci#[macro_use] 3322d8ae3abSopenharmony_ciextern crate cfg_if; 3332d8ae3abSopenharmony_ci 3342d8ae3abSopenharmony_ciuse std::cmp; 3352d8ae3abSopenharmony_ci#[cfg(feature = "std")] 3362d8ae3abSopenharmony_ciuse std::error; 3372d8ae3abSopenharmony_ciuse std::fmt; 3382d8ae3abSopenharmony_ciuse std::mem; 3392d8ae3abSopenharmony_ciuse std::str::FromStr; 3402d8ae3abSopenharmony_ci 3412d8ae3abSopenharmony_ci#[macro_use] 3422d8ae3abSopenharmony_cimod macros; 3432d8ae3abSopenharmony_cimod serde; 3442d8ae3abSopenharmony_ci 3452d8ae3abSopenharmony_ci#[cfg(feature = "kv_unstable")] 3462d8ae3abSopenharmony_cipub mod kv; 3472d8ae3abSopenharmony_ci 3482d8ae3abSopenharmony_ci#[cfg(has_atomics)] 3492d8ae3abSopenharmony_ciuse std::sync::atomic::{AtomicUsize, Ordering}; 3502d8ae3abSopenharmony_ci 3512d8ae3abSopenharmony_ci#[cfg(not(has_atomics))] 3522d8ae3abSopenharmony_ciuse std::cell::Cell; 3532d8ae3abSopenharmony_ci#[cfg(not(has_atomics))] 3542d8ae3abSopenharmony_ciuse std::sync::atomic::Ordering; 3552d8ae3abSopenharmony_ci 3562d8ae3abSopenharmony_ci#[cfg(not(has_atomics))] 3572d8ae3abSopenharmony_cistruct AtomicUsize { 3582d8ae3abSopenharmony_ci v: Cell<usize>, 3592d8ae3abSopenharmony_ci} 3602d8ae3abSopenharmony_ci 3612d8ae3abSopenharmony_ci#[cfg(not(has_atomics))] 3622d8ae3abSopenharmony_ciimpl AtomicUsize { 3632d8ae3abSopenharmony_ci const fn new(v: usize) -> AtomicUsize { 3642d8ae3abSopenharmony_ci AtomicUsize { v: Cell::new(v) } 3652d8ae3abSopenharmony_ci } 3662d8ae3abSopenharmony_ci 3672d8ae3abSopenharmony_ci fn load(&self, _order: Ordering) -> usize { 3682d8ae3abSopenharmony_ci self.v.get() 3692d8ae3abSopenharmony_ci } 3702d8ae3abSopenharmony_ci 3712d8ae3abSopenharmony_ci fn store(&self, val: usize, _order: Ordering) { 3722d8ae3abSopenharmony_ci self.v.set(val) 3732d8ae3abSopenharmony_ci } 3742d8ae3abSopenharmony_ci 3752d8ae3abSopenharmony_ci #[cfg(atomic_cas)] 3762d8ae3abSopenharmony_ci fn compare_exchange( 3772d8ae3abSopenharmony_ci &self, 3782d8ae3abSopenharmony_ci current: usize, 3792d8ae3abSopenharmony_ci new: usize, 3802d8ae3abSopenharmony_ci _success: Ordering, 3812d8ae3abSopenharmony_ci _failure: Ordering, 3822d8ae3abSopenharmony_ci ) -> Result<usize, usize> { 3832d8ae3abSopenharmony_ci let prev = self.v.get(); 3842d8ae3abSopenharmony_ci if current == prev { 3852d8ae3abSopenharmony_ci self.v.set(new); 3862d8ae3abSopenharmony_ci } 3872d8ae3abSopenharmony_ci Ok(prev) 3882d8ae3abSopenharmony_ci } 3892d8ae3abSopenharmony_ci} 3902d8ae3abSopenharmony_ci 3912d8ae3abSopenharmony_ci// Any platform without atomics is unlikely to have multiple cores, so 3922d8ae3abSopenharmony_ci// writing via Cell will not be a race condition. 3932d8ae3abSopenharmony_ci#[cfg(not(has_atomics))] 3942d8ae3abSopenharmony_ciunsafe impl Sync for AtomicUsize {} 3952d8ae3abSopenharmony_ci 3962d8ae3abSopenharmony_ci// The LOGGER static holds a pointer to the global logger. It is protected by 3972d8ae3abSopenharmony_ci// the STATE static which determines whether LOGGER has been initialized yet. 3982d8ae3abSopenharmony_cistatic mut LOGGER: &dyn Log = &NopLogger; 3992d8ae3abSopenharmony_ci 4002d8ae3abSopenharmony_cistatic STATE: AtomicUsize = AtomicUsize::new(0); 4012d8ae3abSopenharmony_ci 4022d8ae3abSopenharmony_ci// There are three different states that we care about: the logger's 4032d8ae3abSopenharmony_ci// uninitialized, the logger's initializing (set_logger's been called but 4042d8ae3abSopenharmony_ci// LOGGER hasn't actually been set yet), or the logger's active. 4052d8ae3abSopenharmony_ciconst UNINITIALIZED: usize = 0; 4062d8ae3abSopenharmony_ciconst INITIALIZING: usize = 1; 4072d8ae3abSopenharmony_ciconst INITIALIZED: usize = 2; 4082d8ae3abSopenharmony_ci 4092d8ae3abSopenharmony_cistatic MAX_LOG_LEVEL_FILTER: AtomicUsize = AtomicUsize::new(0); 4102d8ae3abSopenharmony_ci 4112d8ae3abSopenharmony_cistatic LOG_LEVEL_NAMES: [&str; 6] = ["OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"]; 4122d8ae3abSopenharmony_ci 4132d8ae3abSopenharmony_cistatic SET_LOGGER_ERROR: &str = "attempted to set a logger after the logging system \ 4142d8ae3abSopenharmony_ci was already initialized"; 4152d8ae3abSopenharmony_cistatic LEVEL_PARSE_ERROR: &str = 4162d8ae3abSopenharmony_ci "attempted to convert a string that doesn't match an existing log level"; 4172d8ae3abSopenharmony_ci 4182d8ae3abSopenharmony_ci/// An enum representing the available verbosity levels of the logger. 4192d8ae3abSopenharmony_ci/// 4202d8ae3abSopenharmony_ci/// Typical usage includes: checking if a certain `Level` is enabled with 4212d8ae3abSopenharmony_ci/// [`log_enabled!`](macro.log_enabled.html), specifying the `Level` of 4222d8ae3abSopenharmony_ci/// [`log!`](macro.log.html), and comparing a `Level` directly to a 4232d8ae3abSopenharmony_ci/// [`LevelFilter`](enum.LevelFilter.html). 4242d8ae3abSopenharmony_ci#[repr(usize)] 4252d8ae3abSopenharmony_ci#[derive(Copy, Eq, Debug, Hash)] 4262d8ae3abSopenharmony_cipub enum Level { 4272d8ae3abSopenharmony_ci /// The "error" level. 4282d8ae3abSopenharmony_ci /// 4292d8ae3abSopenharmony_ci /// Designates very serious errors. 4302d8ae3abSopenharmony_ci // This way these line up with the discriminants for LevelFilter below 4312d8ae3abSopenharmony_ci // This works because Rust treats field-less enums the same way as C does: 4322d8ae3abSopenharmony_ci // https://doc.rust-lang.org/reference/items/enumerations.html#custom-discriminant-values-for-field-less-enumerations 4332d8ae3abSopenharmony_ci Error = 1, 4342d8ae3abSopenharmony_ci /// The "warn" level. 4352d8ae3abSopenharmony_ci /// 4362d8ae3abSopenharmony_ci /// Designates hazardous situations. 4372d8ae3abSopenharmony_ci Warn, 4382d8ae3abSopenharmony_ci /// The "info" level. 4392d8ae3abSopenharmony_ci /// 4402d8ae3abSopenharmony_ci /// Designates useful information. 4412d8ae3abSopenharmony_ci Info, 4422d8ae3abSopenharmony_ci /// The "debug" level. 4432d8ae3abSopenharmony_ci /// 4442d8ae3abSopenharmony_ci /// Designates lower priority information. 4452d8ae3abSopenharmony_ci Debug, 4462d8ae3abSopenharmony_ci /// The "trace" level. 4472d8ae3abSopenharmony_ci /// 4482d8ae3abSopenharmony_ci /// Designates very low priority, often extremely verbose, information. 4492d8ae3abSopenharmony_ci Trace, 4502d8ae3abSopenharmony_ci} 4512d8ae3abSopenharmony_ci 4522d8ae3abSopenharmony_ciimpl Clone for Level { 4532d8ae3abSopenharmony_ci #[inline] 4542d8ae3abSopenharmony_ci fn clone(&self) -> Level { 4552d8ae3abSopenharmony_ci *self 4562d8ae3abSopenharmony_ci } 4572d8ae3abSopenharmony_ci} 4582d8ae3abSopenharmony_ci 4592d8ae3abSopenharmony_ciimpl PartialEq for Level { 4602d8ae3abSopenharmony_ci #[inline] 4612d8ae3abSopenharmony_ci fn eq(&self, other: &Level) -> bool { 4622d8ae3abSopenharmony_ci *self as usize == *other as usize 4632d8ae3abSopenharmony_ci } 4642d8ae3abSopenharmony_ci} 4652d8ae3abSopenharmony_ci 4662d8ae3abSopenharmony_ciimpl PartialEq<LevelFilter> for Level { 4672d8ae3abSopenharmony_ci #[inline] 4682d8ae3abSopenharmony_ci fn eq(&self, other: &LevelFilter) -> bool { 4692d8ae3abSopenharmony_ci *self as usize == *other as usize 4702d8ae3abSopenharmony_ci } 4712d8ae3abSopenharmony_ci} 4722d8ae3abSopenharmony_ci 4732d8ae3abSopenharmony_ciimpl PartialOrd for Level { 4742d8ae3abSopenharmony_ci #[inline] 4752d8ae3abSopenharmony_ci fn partial_cmp(&self, other: &Level) -> Option<cmp::Ordering> { 4762d8ae3abSopenharmony_ci Some(self.cmp(other)) 4772d8ae3abSopenharmony_ci } 4782d8ae3abSopenharmony_ci 4792d8ae3abSopenharmony_ci #[inline] 4802d8ae3abSopenharmony_ci fn lt(&self, other: &Level) -> bool { 4812d8ae3abSopenharmony_ci (*self as usize) < *other as usize 4822d8ae3abSopenharmony_ci } 4832d8ae3abSopenharmony_ci 4842d8ae3abSopenharmony_ci #[inline] 4852d8ae3abSopenharmony_ci fn le(&self, other: &Level) -> bool { 4862d8ae3abSopenharmony_ci *self as usize <= *other as usize 4872d8ae3abSopenharmony_ci } 4882d8ae3abSopenharmony_ci 4892d8ae3abSopenharmony_ci #[inline] 4902d8ae3abSopenharmony_ci fn gt(&self, other: &Level) -> bool { 4912d8ae3abSopenharmony_ci *self as usize > *other as usize 4922d8ae3abSopenharmony_ci } 4932d8ae3abSopenharmony_ci 4942d8ae3abSopenharmony_ci #[inline] 4952d8ae3abSopenharmony_ci fn ge(&self, other: &Level) -> bool { 4962d8ae3abSopenharmony_ci *self as usize >= *other as usize 4972d8ae3abSopenharmony_ci } 4982d8ae3abSopenharmony_ci} 4992d8ae3abSopenharmony_ci 5002d8ae3abSopenharmony_ciimpl PartialOrd<LevelFilter> for Level { 5012d8ae3abSopenharmony_ci #[inline] 5022d8ae3abSopenharmony_ci fn partial_cmp(&self, other: &LevelFilter) -> Option<cmp::Ordering> { 5032d8ae3abSopenharmony_ci Some((*self as usize).cmp(&(*other as usize))) 5042d8ae3abSopenharmony_ci } 5052d8ae3abSopenharmony_ci 5062d8ae3abSopenharmony_ci #[inline] 5072d8ae3abSopenharmony_ci fn lt(&self, other: &LevelFilter) -> bool { 5082d8ae3abSopenharmony_ci (*self as usize) < *other as usize 5092d8ae3abSopenharmony_ci } 5102d8ae3abSopenharmony_ci 5112d8ae3abSopenharmony_ci #[inline] 5122d8ae3abSopenharmony_ci fn le(&self, other: &LevelFilter) -> bool { 5132d8ae3abSopenharmony_ci *self as usize <= *other as usize 5142d8ae3abSopenharmony_ci } 5152d8ae3abSopenharmony_ci 5162d8ae3abSopenharmony_ci #[inline] 5172d8ae3abSopenharmony_ci fn gt(&self, other: &LevelFilter) -> bool { 5182d8ae3abSopenharmony_ci *self as usize > *other as usize 5192d8ae3abSopenharmony_ci } 5202d8ae3abSopenharmony_ci 5212d8ae3abSopenharmony_ci #[inline] 5222d8ae3abSopenharmony_ci fn ge(&self, other: &LevelFilter) -> bool { 5232d8ae3abSopenharmony_ci *self as usize >= *other as usize 5242d8ae3abSopenharmony_ci } 5252d8ae3abSopenharmony_ci} 5262d8ae3abSopenharmony_ci 5272d8ae3abSopenharmony_ciimpl Ord for Level { 5282d8ae3abSopenharmony_ci #[inline] 5292d8ae3abSopenharmony_ci fn cmp(&self, other: &Level) -> cmp::Ordering { 5302d8ae3abSopenharmony_ci (*self as usize).cmp(&(*other as usize)) 5312d8ae3abSopenharmony_ci } 5322d8ae3abSopenharmony_ci} 5332d8ae3abSopenharmony_ci 5342d8ae3abSopenharmony_cifn ok_or<T, E>(t: Option<T>, e: E) -> Result<T, E> { 5352d8ae3abSopenharmony_ci match t { 5362d8ae3abSopenharmony_ci Some(t) => Ok(t), 5372d8ae3abSopenharmony_ci None => Err(e), 5382d8ae3abSopenharmony_ci } 5392d8ae3abSopenharmony_ci} 5402d8ae3abSopenharmony_ci 5412d8ae3abSopenharmony_ci// Reimplemented here because std::ascii is not available in libcore 5422d8ae3abSopenharmony_cifn eq_ignore_ascii_case(a: &str, b: &str) -> bool { 5432d8ae3abSopenharmony_ci fn to_ascii_uppercase(c: u8) -> u8 { 5442d8ae3abSopenharmony_ci if c >= b'a' && c <= b'z' { 5452d8ae3abSopenharmony_ci c - b'a' + b'A' 5462d8ae3abSopenharmony_ci } else { 5472d8ae3abSopenharmony_ci c 5482d8ae3abSopenharmony_ci } 5492d8ae3abSopenharmony_ci } 5502d8ae3abSopenharmony_ci 5512d8ae3abSopenharmony_ci if a.len() == b.len() { 5522d8ae3abSopenharmony_ci a.bytes() 5532d8ae3abSopenharmony_ci .zip(b.bytes()) 5542d8ae3abSopenharmony_ci .all(|(a, b)| to_ascii_uppercase(a) == to_ascii_uppercase(b)) 5552d8ae3abSopenharmony_ci } else { 5562d8ae3abSopenharmony_ci false 5572d8ae3abSopenharmony_ci } 5582d8ae3abSopenharmony_ci} 5592d8ae3abSopenharmony_ci 5602d8ae3abSopenharmony_ciimpl FromStr for Level { 5612d8ae3abSopenharmony_ci type Err = ParseLevelError; 5622d8ae3abSopenharmony_ci fn from_str(level: &str) -> Result<Level, Self::Err> { 5632d8ae3abSopenharmony_ci ok_or( 5642d8ae3abSopenharmony_ci LOG_LEVEL_NAMES 5652d8ae3abSopenharmony_ci .iter() 5662d8ae3abSopenharmony_ci .position(|&name| eq_ignore_ascii_case(name, level)) 5672d8ae3abSopenharmony_ci .into_iter() 5682d8ae3abSopenharmony_ci .filter(|&idx| idx != 0) 5692d8ae3abSopenharmony_ci .map(|idx| Level::from_usize(idx).unwrap()) 5702d8ae3abSopenharmony_ci .next(), 5712d8ae3abSopenharmony_ci ParseLevelError(()), 5722d8ae3abSopenharmony_ci ) 5732d8ae3abSopenharmony_ci } 5742d8ae3abSopenharmony_ci} 5752d8ae3abSopenharmony_ci 5762d8ae3abSopenharmony_ciimpl fmt::Display for Level { 5772d8ae3abSopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 5782d8ae3abSopenharmony_ci fmt.pad(self.as_str()) 5792d8ae3abSopenharmony_ci } 5802d8ae3abSopenharmony_ci} 5812d8ae3abSopenharmony_ci 5822d8ae3abSopenharmony_ciimpl Level { 5832d8ae3abSopenharmony_ci fn from_usize(u: usize) -> Option<Level> { 5842d8ae3abSopenharmony_ci match u { 5852d8ae3abSopenharmony_ci 1 => Some(Level::Error), 5862d8ae3abSopenharmony_ci 2 => Some(Level::Warn), 5872d8ae3abSopenharmony_ci 3 => Some(Level::Info), 5882d8ae3abSopenharmony_ci 4 => Some(Level::Debug), 5892d8ae3abSopenharmony_ci 5 => Some(Level::Trace), 5902d8ae3abSopenharmony_ci _ => None, 5912d8ae3abSopenharmony_ci } 5922d8ae3abSopenharmony_ci } 5932d8ae3abSopenharmony_ci 5942d8ae3abSopenharmony_ci /// Returns the most verbose logging level. 5952d8ae3abSopenharmony_ci #[inline] 5962d8ae3abSopenharmony_ci pub fn max() -> Level { 5972d8ae3abSopenharmony_ci Level::Trace 5982d8ae3abSopenharmony_ci } 5992d8ae3abSopenharmony_ci 6002d8ae3abSopenharmony_ci /// Converts the `Level` to the equivalent `LevelFilter`. 6012d8ae3abSopenharmony_ci #[inline] 6022d8ae3abSopenharmony_ci pub fn to_level_filter(&self) -> LevelFilter { 6032d8ae3abSopenharmony_ci LevelFilter::from_usize(*self as usize).unwrap() 6042d8ae3abSopenharmony_ci } 6052d8ae3abSopenharmony_ci 6062d8ae3abSopenharmony_ci /// Returns the string representation of the `Level`. 6072d8ae3abSopenharmony_ci /// 6082d8ae3abSopenharmony_ci /// This returns the same string as the `fmt::Display` implementation. 6092d8ae3abSopenharmony_ci pub fn as_str(&self) -> &'static str { 6102d8ae3abSopenharmony_ci LOG_LEVEL_NAMES[*self as usize] 6112d8ae3abSopenharmony_ci } 6122d8ae3abSopenharmony_ci 6132d8ae3abSopenharmony_ci /// Iterate through all supported logging levels. 6142d8ae3abSopenharmony_ci /// 6152d8ae3abSopenharmony_ci /// The order of iteration is from more severe to less severe log messages. 6162d8ae3abSopenharmony_ci /// 6172d8ae3abSopenharmony_ci /// # Examples 6182d8ae3abSopenharmony_ci /// 6192d8ae3abSopenharmony_ci /// ``` 6202d8ae3abSopenharmony_ci /// use log::Level; 6212d8ae3abSopenharmony_ci /// 6222d8ae3abSopenharmony_ci /// let mut levels = Level::iter(); 6232d8ae3abSopenharmony_ci /// 6242d8ae3abSopenharmony_ci /// assert_eq!(Some(Level::Error), levels.next()); 6252d8ae3abSopenharmony_ci /// assert_eq!(Some(Level::Trace), levels.last()); 6262d8ae3abSopenharmony_ci /// ``` 6272d8ae3abSopenharmony_ci pub fn iter() -> impl Iterator<Item = Self> { 6282d8ae3abSopenharmony_ci (1..6).map(|i| Self::from_usize(i).unwrap()) 6292d8ae3abSopenharmony_ci } 6302d8ae3abSopenharmony_ci} 6312d8ae3abSopenharmony_ci 6322d8ae3abSopenharmony_ci/// An enum representing the available verbosity level filters of the logger. 6332d8ae3abSopenharmony_ci/// 6342d8ae3abSopenharmony_ci/// A `LevelFilter` may be compared directly to a [`Level`]. Use this type 6352d8ae3abSopenharmony_ci/// to get and set the maximum log level with [`max_level()`] and [`set_max_level`]. 6362d8ae3abSopenharmony_ci/// 6372d8ae3abSopenharmony_ci/// [`Level`]: enum.Level.html 6382d8ae3abSopenharmony_ci/// [`max_level()`]: fn.max_level.html 6392d8ae3abSopenharmony_ci/// [`set_max_level`]: fn.set_max_level.html 6402d8ae3abSopenharmony_ci#[repr(usize)] 6412d8ae3abSopenharmony_ci#[derive(Copy, Eq, Debug, Hash)] 6422d8ae3abSopenharmony_cipub enum LevelFilter { 6432d8ae3abSopenharmony_ci /// A level lower than all log levels. 6442d8ae3abSopenharmony_ci Off, 6452d8ae3abSopenharmony_ci /// Corresponds to the `Error` log level. 6462d8ae3abSopenharmony_ci Error, 6472d8ae3abSopenharmony_ci /// Corresponds to the `Warn` log level. 6482d8ae3abSopenharmony_ci Warn, 6492d8ae3abSopenharmony_ci /// Corresponds to the `Info` log level. 6502d8ae3abSopenharmony_ci Info, 6512d8ae3abSopenharmony_ci /// Corresponds to the `Debug` log level. 6522d8ae3abSopenharmony_ci Debug, 6532d8ae3abSopenharmony_ci /// Corresponds to the `Trace` log level. 6542d8ae3abSopenharmony_ci Trace, 6552d8ae3abSopenharmony_ci} 6562d8ae3abSopenharmony_ci 6572d8ae3abSopenharmony_ci// Deriving generates terrible impls of these traits 6582d8ae3abSopenharmony_ci 6592d8ae3abSopenharmony_ciimpl Clone for LevelFilter { 6602d8ae3abSopenharmony_ci #[inline] 6612d8ae3abSopenharmony_ci fn clone(&self) -> LevelFilter { 6622d8ae3abSopenharmony_ci *self 6632d8ae3abSopenharmony_ci } 6642d8ae3abSopenharmony_ci} 6652d8ae3abSopenharmony_ci 6662d8ae3abSopenharmony_ciimpl PartialEq for LevelFilter { 6672d8ae3abSopenharmony_ci #[inline] 6682d8ae3abSopenharmony_ci fn eq(&self, other: &LevelFilter) -> bool { 6692d8ae3abSopenharmony_ci *self as usize == *other as usize 6702d8ae3abSopenharmony_ci } 6712d8ae3abSopenharmony_ci} 6722d8ae3abSopenharmony_ci 6732d8ae3abSopenharmony_ciimpl PartialEq<Level> for LevelFilter { 6742d8ae3abSopenharmony_ci #[inline] 6752d8ae3abSopenharmony_ci fn eq(&self, other: &Level) -> bool { 6762d8ae3abSopenharmony_ci other.eq(self) 6772d8ae3abSopenharmony_ci } 6782d8ae3abSopenharmony_ci} 6792d8ae3abSopenharmony_ci 6802d8ae3abSopenharmony_ciimpl PartialOrd for LevelFilter { 6812d8ae3abSopenharmony_ci #[inline] 6822d8ae3abSopenharmony_ci fn partial_cmp(&self, other: &LevelFilter) -> Option<cmp::Ordering> { 6832d8ae3abSopenharmony_ci Some(self.cmp(other)) 6842d8ae3abSopenharmony_ci } 6852d8ae3abSopenharmony_ci 6862d8ae3abSopenharmony_ci #[inline] 6872d8ae3abSopenharmony_ci fn lt(&self, other: &LevelFilter) -> bool { 6882d8ae3abSopenharmony_ci (*self as usize) < *other as usize 6892d8ae3abSopenharmony_ci } 6902d8ae3abSopenharmony_ci 6912d8ae3abSopenharmony_ci #[inline] 6922d8ae3abSopenharmony_ci fn le(&self, other: &LevelFilter) -> bool { 6932d8ae3abSopenharmony_ci *self as usize <= *other as usize 6942d8ae3abSopenharmony_ci } 6952d8ae3abSopenharmony_ci 6962d8ae3abSopenharmony_ci #[inline] 6972d8ae3abSopenharmony_ci fn gt(&self, other: &LevelFilter) -> bool { 6982d8ae3abSopenharmony_ci *self as usize > *other as usize 6992d8ae3abSopenharmony_ci } 7002d8ae3abSopenharmony_ci 7012d8ae3abSopenharmony_ci #[inline] 7022d8ae3abSopenharmony_ci fn ge(&self, other: &LevelFilter) -> bool { 7032d8ae3abSopenharmony_ci *self as usize >= *other as usize 7042d8ae3abSopenharmony_ci } 7052d8ae3abSopenharmony_ci} 7062d8ae3abSopenharmony_ci 7072d8ae3abSopenharmony_ciimpl PartialOrd<Level> for LevelFilter { 7082d8ae3abSopenharmony_ci #[inline] 7092d8ae3abSopenharmony_ci fn partial_cmp(&self, other: &Level) -> Option<cmp::Ordering> { 7102d8ae3abSopenharmony_ci Some((*self as usize).cmp(&(*other as usize))) 7112d8ae3abSopenharmony_ci } 7122d8ae3abSopenharmony_ci 7132d8ae3abSopenharmony_ci #[inline] 7142d8ae3abSopenharmony_ci fn lt(&self, other: &Level) -> bool { 7152d8ae3abSopenharmony_ci (*self as usize) < *other as usize 7162d8ae3abSopenharmony_ci } 7172d8ae3abSopenharmony_ci 7182d8ae3abSopenharmony_ci #[inline] 7192d8ae3abSopenharmony_ci fn le(&self, other: &Level) -> bool { 7202d8ae3abSopenharmony_ci *self as usize <= *other as usize 7212d8ae3abSopenharmony_ci } 7222d8ae3abSopenharmony_ci 7232d8ae3abSopenharmony_ci #[inline] 7242d8ae3abSopenharmony_ci fn gt(&self, other: &Level) -> bool { 7252d8ae3abSopenharmony_ci *self as usize > *other as usize 7262d8ae3abSopenharmony_ci } 7272d8ae3abSopenharmony_ci 7282d8ae3abSopenharmony_ci #[inline] 7292d8ae3abSopenharmony_ci fn ge(&self, other: &Level) -> bool { 7302d8ae3abSopenharmony_ci *self as usize >= *other as usize 7312d8ae3abSopenharmony_ci } 7322d8ae3abSopenharmony_ci} 7332d8ae3abSopenharmony_ci 7342d8ae3abSopenharmony_ciimpl Ord for LevelFilter { 7352d8ae3abSopenharmony_ci #[inline] 7362d8ae3abSopenharmony_ci fn cmp(&self, other: &LevelFilter) -> cmp::Ordering { 7372d8ae3abSopenharmony_ci (*self as usize).cmp(&(*other as usize)) 7382d8ae3abSopenharmony_ci } 7392d8ae3abSopenharmony_ci} 7402d8ae3abSopenharmony_ci 7412d8ae3abSopenharmony_ciimpl FromStr for LevelFilter { 7422d8ae3abSopenharmony_ci type Err = ParseLevelError; 7432d8ae3abSopenharmony_ci fn from_str(level: &str) -> Result<LevelFilter, Self::Err> { 7442d8ae3abSopenharmony_ci ok_or( 7452d8ae3abSopenharmony_ci LOG_LEVEL_NAMES 7462d8ae3abSopenharmony_ci .iter() 7472d8ae3abSopenharmony_ci .position(|&name| eq_ignore_ascii_case(name, level)) 7482d8ae3abSopenharmony_ci .map(|p| LevelFilter::from_usize(p).unwrap()), 7492d8ae3abSopenharmony_ci ParseLevelError(()), 7502d8ae3abSopenharmony_ci ) 7512d8ae3abSopenharmony_ci } 7522d8ae3abSopenharmony_ci} 7532d8ae3abSopenharmony_ci 7542d8ae3abSopenharmony_ciimpl fmt::Display for LevelFilter { 7552d8ae3abSopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 7562d8ae3abSopenharmony_ci fmt.pad(self.as_str()) 7572d8ae3abSopenharmony_ci } 7582d8ae3abSopenharmony_ci} 7592d8ae3abSopenharmony_ci 7602d8ae3abSopenharmony_ciimpl LevelFilter { 7612d8ae3abSopenharmony_ci fn from_usize(u: usize) -> Option<LevelFilter> { 7622d8ae3abSopenharmony_ci match u { 7632d8ae3abSopenharmony_ci 0 => Some(LevelFilter::Off), 7642d8ae3abSopenharmony_ci 1 => Some(LevelFilter::Error), 7652d8ae3abSopenharmony_ci 2 => Some(LevelFilter::Warn), 7662d8ae3abSopenharmony_ci 3 => Some(LevelFilter::Info), 7672d8ae3abSopenharmony_ci 4 => Some(LevelFilter::Debug), 7682d8ae3abSopenharmony_ci 5 => Some(LevelFilter::Trace), 7692d8ae3abSopenharmony_ci _ => None, 7702d8ae3abSopenharmony_ci } 7712d8ae3abSopenharmony_ci } 7722d8ae3abSopenharmony_ci 7732d8ae3abSopenharmony_ci /// Returns the most verbose logging level filter. 7742d8ae3abSopenharmony_ci #[inline] 7752d8ae3abSopenharmony_ci pub fn max() -> LevelFilter { 7762d8ae3abSopenharmony_ci LevelFilter::Trace 7772d8ae3abSopenharmony_ci } 7782d8ae3abSopenharmony_ci 7792d8ae3abSopenharmony_ci /// Converts `self` to the equivalent `Level`. 7802d8ae3abSopenharmony_ci /// 7812d8ae3abSopenharmony_ci /// Returns `None` if `self` is `LevelFilter::Off`. 7822d8ae3abSopenharmony_ci #[inline] 7832d8ae3abSopenharmony_ci pub fn to_level(&self) -> Option<Level> { 7842d8ae3abSopenharmony_ci Level::from_usize(*self as usize) 7852d8ae3abSopenharmony_ci } 7862d8ae3abSopenharmony_ci 7872d8ae3abSopenharmony_ci /// Returns the string representation of the `LevelFilter`. 7882d8ae3abSopenharmony_ci /// 7892d8ae3abSopenharmony_ci /// This returns the same string as the `fmt::Display` implementation. 7902d8ae3abSopenharmony_ci pub fn as_str(&self) -> &'static str { 7912d8ae3abSopenharmony_ci LOG_LEVEL_NAMES[*self as usize] 7922d8ae3abSopenharmony_ci } 7932d8ae3abSopenharmony_ci 7942d8ae3abSopenharmony_ci /// Iterate through all supported filtering levels. 7952d8ae3abSopenharmony_ci /// 7962d8ae3abSopenharmony_ci /// The order of iteration is from less to more verbose filtering. 7972d8ae3abSopenharmony_ci /// 7982d8ae3abSopenharmony_ci /// # Examples 7992d8ae3abSopenharmony_ci /// 8002d8ae3abSopenharmony_ci /// ``` 8012d8ae3abSopenharmony_ci /// use log::LevelFilter; 8022d8ae3abSopenharmony_ci /// 8032d8ae3abSopenharmony_ci /// let mut levels = LevelFilter::iter(); 8042d8ae3abSopenharmony_ci /// 8052d8ae3abSopenharmony_ci /// assert_eq!(Some(LevelFilter::Off), levels.next()); 8062d8ae3abSopenharmony_ci /// assert_eq!(Some(LevelFilter::Trace), levels.last()); 8072d8ae3abSopenharmony_ci /// ``` 8082d8ae3abSopenharmony_ci pub fn iter() -> impl Iterator<Item = Self> { 8092d8ae3abSopenharmony_ci (0..6).map(|i| Self::from_usize(i).unwrap()) 8102d8ae3abSopenharmony_ci } 8112d8ae3abSopenharmony_ci} 8122d8ae3abSopenharmony_ci 8132d8ae3abSopenharmony_ci#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] 8142d8ae3abSopenharmony_cienum MaybeStaticStr<'a> { 8152d8ae3abSopenharmony_ci Static(&'static str), 8162d8ae3abSopenharmony_ci Borrowed(&'a str), 8172d8ae3abSopenharmony_ci} 8182d8ae3abSopenharmony_ci 8192d8ae3abSopenharmony_ciimpl<'a> MaybeStaticStr<'a> { 8202d8ae3abSopenharmony_ci #[inline] 8212d8ae3abSopenharmony_ci fn get(&self) -> &'a str { 8222d8ae3abSopenharmony_ci match *self { 8232d8ae3abSopenharmony_ci MaybeStaticStr::Static(s) => s, 8242d8ae3abSopenharmony_ci MaybeStaticStr::Borrowed(s) => s, 8252d8ae3abSopenharmony_ci } 8262d8ae3abSopenharmony_ci } 8272d8ae3abSopenharmony_ci} 8282d8ae3abSopenharmony_ci 8292d8ae3abSopenharmony_ci/// The "payload" of a log message. 8302d8ae3abSopenharmony_ci/// 8312d8ae3abSopenharmony_ci/// # Use 8322d8ae3abSopenharmony_ci/// 8332d8ae3abSopenharmony_ci/// `Record` structures are passed as parameters to the [`log`][method.log] 8342d8ae3abSopenharmony_ci/// method of the [`Log`] trait. Logger implementors manipulate these 8352d8ae3abSopenharmony_ci/// structures in order to display log messages. `Record`s are automatically 8362d8ae3abSopenharmony_ci/// created by the [`log!`] macro and so are not seen by log users. 8372d8ae3abSopenharmony_ci/// 8382d8ae3abSopenharmony_ci/// Note that the [`level()`] and [`target()`] accessors are equivalent to 8392d8ae3abSopenharmony_ci/// `self.metadata().level()` and `self.metadata().target()` respectively. 8402d8ae3abSopenharmony_ci/// These methods are provided as a convenience for users of this structure. 8412d8ae3abSopenharmony_ci/// 8422d8ae3abSopenharmony_ci/// # Example 8432d8ae3abSopenharmony_ci/// 8442d8ae3abSopenharmony_ci/// The following example shows a simple logger that displays the level, 8452d8ae3abSopenharmony_ci/// module path, and message of any `Record` that is passed to it. 8462d8ae3abSopenharmony_ci/// 8472d8ae3abSopenharmony_ci/// ```edition2018 8482d8ae3abSopenharmony_ci/// struct SimpleLogger; 8492d8ae3abSopenharmony_ci/// 8502d8ae3abSopenharmony_ci/// impl log::Log for SimpleLogger { 8512d8ae3abSopenharmony_ci/// fn enabled(&self, metadata: &log::Metadata) -> bool { 8522d8ae3abSopenharmony_ci/// true 8532d8ae3abSopenharmony_ci/// } 8542d8ae3abSopenharmony_ci/// 8552d8ae3abSopenharmony_ci/// fn log(&self, record: &log::Record) { 8562d8ae3abSopenharmony_ci/// if !self.enabled(record.metadata()) { 8572d8ae3abSopenharmony_ci/// return; 8582d8ae3abSopenharmony_ci/// } 8592d8ae3abSopenharmony_ci/// 8602d8ae3abSopenharmony_ci/// println!("{}:{} -- {}", 8612d8ae3abSopenharmony_ci/// record.level(), 8622d8ae3abSopenharmony_ci/// record.target(), 8632d8ae3abSopenharmony_ci/// record.args()); 8642d8ae3abSopenharmony_ci/// } 8652d8ae3abSopenharmony_ci/// fn flush(&self) {} 8662d8ae3abSopenharmony_ci/// } 8672d8ae3abSopenharmony_ci/// ``` 8682d8ae3abSopenharmony_ci/// 8692d8ae3abSopenharmony_ci/// [method.log]: trait.Log.html#tymethod.log 8702d8ae3abSopenharmony_ci/// [`Log`]: trait.Log.html 8712d8ae3abSopenharmony_ci/// [`log!`]: macro.log.html 8722d8ae3abSopenharmony_ci/// [`level()`]: struct.Record.html#method.level 8732d8ae3abSopenharmony_ci/// [`target()`]: struct.Record.html#method.target 8742d8ae3abSopenharmony_ci#[derive(Clone, Debug)] 8752d8ae3abSopenharmony_cipub struct Record<'a> { 8762d8ae3abSopenharmony_ci metadata: Metadata<'a>, 8772d8ae3abSopenharmony_ci args: fmt::Arguments<'a>, 8782d8ae3abSopenharmony_ci module_path: Option<MaybeStaticStr<'a>>, 8792d8ae3abSopenharmony_ci file: Option<MaybeStaticStr<'a>>, 8802d8ae3abSopenharmony_ci line: Option<u32>, 8812d8ae3abSopenharmony_ci #[cfg(feature = "kv_unstable")] 8822d8ae3abSopenharmony_ci key_values: KeyValues<'a>, 8832d8ae3abSopenharmony_ci} 8842d8ae3abSopenharmony_ci 8852d8ae3abSopenharmony_ci// This wrapper type is only needed so we can 8862d8ae3abSopenharmony_ci// `#[derive(Debug)]` on `Record`. It also 8872d8ae3abSopenharmony_ci// provides a useful `Debug` implementation for 8882d8ae3abSopenharmony_ci// the underlying `Source`. 8892d8ae3abSopenharmony_ci#[cfg(feature = "kv_unstable")] 8902d8ae3abSopenharmony_ci#[derive(Clone)] 8912d8ae3abSopenharmony_cistruct KeyValues<'a>(&'a dyn kv::Source); 8922d8ae3abSopenharmony_ci 8932d8ae3abSopenharmony_ci#[cfg(feature = "kv_unstable")] 8942d8ae3abSopenharmony_ciimpl<'a> fmt::Debug for KeyValues<'a> { 8952d8ae3abSopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 8962d8ae3abSopenharmony_ci let mut visitor = f.debug_map(); 8972d8ae3abSopenharmony_ci self.0.visit(&mut visitor).map_err(|_| fmt::Error)?; 8982d8ae3abSopenharmony_ci visitor.finish() 8992d8ae3abSopenharmony_ci } 9002d8ae3abSopenharmony_ci} 9012d8ae3abSopenharmony_ci 9022d8ae3abSopenharmony_ciimpl<'a> Record<'a> { 9032d8ae3abSopenharmony_ci /// Returns a new builder. 9042d8ae3abSopenharmony_ci #[inline] 9052d8ae3abSopenharmony_ci pub fn builder() -> RecordBuilder<'a> { 9062d8ae3abSopenharmony_ci RecordBuilder::new() 9072d8ae3abSopenharmony_ci } 9082d8ae3abSopenharmony_ci 9092d8ae3abSopenharmony_ci /// The message body. 9102d8ae3abSopenharmony_ci #[inline] 9112d8ae3abSopenharmony_ci pub fn args(&self) -> &fmt::Arguments<'a> { 9122d8ae3abSopenharmony_ci &self.args 9132d8ae3abSopenharmony_ci } 9142d8ae3abSopenharmony_ci 9152d8ae3abSopenharmony_ci /// Metadata about the log directive. 9162d8ae3abSopenharmony_ci #[inline] 9172d8ae3abSopenharmony_ci pub fn metadata(&self) -> &Metadata<'a> { 9182d8ae3abSopenharmony_ci &self.metadata 9192d8ae3abSopenharmony_ci } 9202d8ae3abSopenharmony_ci 9212d8ae3abSopenharmony_ci /// The verbosity level of the message. 9222d8ae3abSopenharmony_ci #[inline] 9232d8ae3abSopenharmony_ci pub fn level(&self) -> Level { 9242d8ae3abSopenharmony_ci self.metadata.level() 9252d8ae3abSopenharmony_ci } 9262d8ae3abSopenharmony_ci 9272d8ae3abSopenharmony_ci /// The name of the target of the directive. 9282d8ae3abSopenharmony_ci #[inline] 9292d8ae3abSopenharmony_ci pub fn target(&self) -> &'a str { 9302d8ae3abSopenharmony_ci self.metadata.target() 9312d8ae3abSopenharmony_ci } 9322d8ae3abSopenharmony_ci 9332d8ae3abSopenharmony_ci /// The module path of the message. 9342d8ae3abSopenharmony_ci #[inline] 9352d8ae3abSopenharmony_ci pub fn module_path(&self) -> Option<&'a str> { 9362d8ae3abSopenharmony_ci self.module_path.map(|s| s.get()) 9372d8ae3abSopenharmony_ci } 9382d8ae3abSopenharmony_ci 9392d8ae3abSopenharmony_ci /// The module path of the message, if it is a `'static` string. 9402d8ae3abSopenharmony_ci #[inline] 9412d8ae3abSopenharmony_ci pub fn module_path_static(&self) -> Option<&'static str> { 9422d8ae3abSopenharmony_ci match self.module_path { 9432d8ae3abSopenharmony_ci Some(MaybeStaticStr::Static(s)) => Some(s), 9442d8ae3abSopenharmony_ci _ => None, 9452d8ae3abSopenharmony_ci } 9462d8ae3abSopenharmony_ci } 9472d8ae3abSopenharmony_ci 9482d8ae3abSopenharmony_ci /// The source file containing the message. 9492d8ae3abSopenharmony_ci #[inline] 9502d8ae3abSopenharmony_ci pub fn file(&self) -> Option<&'a str> { 9512d8ae3abSopenharmony_ci self.file.map(|s| s.get()) 9522d8ae3abSopenharmony_ci } 9532d8ae3abSopenharmony_ci 9542d8ae3abSopenharmony_ci /// The module path of the message, if it is a `'static` string. 9552d8ae3abSopenharmony_ci #[inline] 9562d8ae3abSopenharmony_ci pub fn file_static(&self) -> Option<&'static str> { 9572d8ae3abSopenharmony_ci match self.file { 9582d8ae3abSopenharmony_ci Some(MaybeStaticStr::Static(s)) => Some(s), 9592d8ae3abSopenharmony_ci _ => None, 9602d8ae3abSopenharmony_ci } 9612d8ae3abSopenharmony_ci } 9622d8ae3abSopenharmony_ci 9632d8ae3abSopenharmony_ci /// The line containing the message. 9642d8ae3abSopenharmony_ci #[inline] 9652d8ae3abSopenharmony_ci pub fn line(&self) -> Option<u32> { 9662d8ae3abSopenharmony_ci self.line 9672d8ae3abSopenharmony_ci } 9682d8ae3abSopenharmony_ci 9692d8ae3abSopenharmony_ci /// The structured key-value pairs associated with the message. 9702d8ae3abSopenharmony_ci #[cfg(feature = "kv_unstable")] 9712d8ae3abSopenharmony_ci #[inline] 9722d8ae3abSopenharmony_ci pub fn key_values(&self) -> &dyn kv::Source { 9732d8ae3abSopenharmony_ci self.key_values.0 9742d8ae3abSopenharmony_ci } 9752d8ae3abSopenharmony_ci 9762d8ae3abSopenharmony_ci /// Create a new [`RecordBuilder`](struct.RecordBuilder.html) based on this record. 9772d8ae3abSopenharmony_ci #[cfg(feature = "kv_unstable")] 9782d8ae3abSopenharmony_ci #[inline] 9792d8ae3abSopenharmony_ci pub fn to_builder(&self) -> RecordBuilder { 9802d8ae3abSopenharmony_ci RecordBuilder { 9812d8ae3abSopenharmony_ci record: Record { 9822d8ae3abSopenharmony_ci metadata: Metadata { 9832d8ae3abSopenharmony_ci level: self.metadata.level, 9842d8ae3abSopenharmony_ci target: self.metadata.target, 9852d8ae3abSopenharmony_ci }, 9862d8ae3abSopenharmony_ci args: self.args, 9872d8ae3abSopenharmony_ci module_path: self.module_path, 9882d8ae3abSopenharmony_ci file: self.file, 9892d8ae3abSopenharmony_ci line: self.line, 9902d8ae3abSopenharmony_ci key_values: self.key_values.clone(), 9912d8ae3abSopenharmony_ci }, 9922d8ae3abSopenharmony_ci } 9932d8ae3abSopenharmony_ci } 9942d8ae3abSopenharmony_ci} 9952d8ae3abSopenharmony_ci 9962d8ae3abSopenharmony_ci/// Builder for [`Record`](struct.Record.html). 9972d8ae3abSopenharmony_ci/// 9982d8ae3abSopenharmony_ci/// Typically should only be used by log library creators or for testing and "shim loggers". 9992d8ae3abSopenharmony_ci/// The `RecordBuilder` can set the different parameters of `Record` object, and returns 10002d8ae3abSopenharmony_ci/// the created object when `build` is called. 10012d8ae3abSopenharmony_ci/// 10022d8ae3abSopenharmony_ci/// # Examples 10032d8ae3abSopenharmony_ci/// 10042d8ae3abSopenharmony_ci/// ```edition2018 10052d8ae3abSopenharmony_ci/// use log::{Level, Record}; 10062d8ae3abSopenharmony_ci/// 10072d8ae3abSopenharmony_ci/// let record = Record::builder() 10082d8ae3abSopenharmony_ci/// .args(format_args!("Error!")) 10092d8ae3abSopenharmony_ci/// .level(Level::Error) 10102d8ae3abSopenharmony_ci/// .target("myApp") 10112d8ae3abSopenharmony_ci/// .file(Some("server.rs")) 10122d8ae3abSopenharmony_ci/// .line(Some(144)) 10132d8ae3abSopenharmony_ci/// .module_path(Some("server")) 10142d8ae3abSopenharmony_ci/// .build(); 10152d8ae3abSopenharmony_ci/// ``` 10162d8ae3abSopenharmony_ci/// 10172d8ae3abSopenharmony_ci/// Alternatively, use [`MetadataBuilder`](struct.MetadataBuilder.html): 10182d8ae3abSopenharmony_ci/// 10192d8ae3abSopenharmony_ci/// ```edition2018 10202d8ae3abSopenharmony_ci/// use log::{Record, Level, MetadataBuilder}; 10212d8ae3abSopenharmony_ci/// 10222d8ae3abSopenharmony_ci/// let error_metadata = MetadataBuilder::new() 10232d8ae3abSopenharmony_ci/// .target("myApp") 10242d8ae3abSopenharmony_ci/// .level(Level::Error) 10252d8ae3abSopenharmony_ci/// .build(); 10262d8ae3abSopenharmony_ci/// 10272d8ae3abSopenharmony_ci/// let record = Record::builder() 10282d8ae3abSopenharmony_ci/// .metadata(error_metadata) 10292d8ae3abSopenharmony_ci/// .args(format_args!("Error!")) 10302d8ae3abSopenharmony_ci/// .line(Some(433)) 10312d8ae3abSopenharmony_ci/// .file(Some("app.rs")) 10322d8ae3abSopenharmony_ci/// .module_path(Some("server")) 10332d8ae3abSopenharmony_ci/// .build(); 10342d8ae3abSopenharmony_ci/// ``` 10352d8ae3abSopenharmony_ci#[derive(Debug)] 10362d8ae3abSopenharmony_cipub struct RecordBuilder<'a> { 10372d8ae3abSopenharmony_ci record: Record<'a>, 10382d8ae3abSopenharmony_ci} 10392d8ae3abSopenharmony_ci 10402d8ae3abSopenharmony_ciimpl<'a> RecordBuilder<'a> { 10412d8ae3abSopenharmony_ci /// Construct new `RecordBuilder`. 10422d8ae3abSopenharmony_ci /// 10432d8ae3abSopenharmony_ci /// The default options are: 10442d8ae3abSopenharmony_ci /// 10452d8ae3abSopenharmony_ci /// - `args`: [`format_args!("")`] 10462d8ae3abSopenharmony_ci /// - `metadata`: [`Metadata::builder().build()`] 10472d8ae3abSopenharmony_ci /// - `module_path`: `None` 10482d8ae3abSopenharmony_ci /// - `file`: `None` 10492d8ae3abSopenharmony_ci /// - `line`: `None` 10502d8ae3abSopenharmony_ci /// 10512d8ae3abSopenharmony_ci /// [`format_args!("")`]: https://doc.rust-lang.org/std/macro.format_args.html 10522d8ae3abSopenharmony_ci /// [`Metadata::builder().build()`]: struct.MetadataBuilder.html#method.build 10532d8ae3abSopenharmony_ci #[inline] 10542d8ae3abSopenharmony_ci pub fn new() -> RecordBuilder<'a> { 10552d8ae3abSopenharmony_ci RecordBuilder { 10562d8ae3abSopenharmony_ci record: Record { 10572d8ae3abSopenharmony_ci args: format_args!(""), 10582d8ae3abSopenharmony_ci metadata: Metadata::builder().build(), 10592d8ae3abSopenharmony_ci module_path: None, 10602d8ae3abSopenharmony_ci file: None, 10612d8ae3abSopenharmony_ci line: None, 10622d8ae3abSopenharmony_ci #[cfg(feature = "kv_unstable")] 10632d8ae3abSopenharmony_ci key_values: KeyValues(&Option::None::<(kv::Key, kv::Value)>), 10642d8ae3abSopenharmony_ci }, 10652d8ae3abSopenharmony_ci } 10662d8ae3abSopenharmony_ci } 10672d8ae3abSopenharmony_ci 10682d8ae3abSopenharmony_ci /// Set [`args`](struct.Record.html#method.args). 10692d8ae3abSopenharmony_ci #[inline] 10702d8ae3abSopenharmony_ci pub fn args(&mut self, args: fmt::Arguments<'a>) -> &mut RecordBuilder<'a> { 10712d8ae3abSopenharmony_ci self.record.args = args; 10722d8ae3abSopenharmony_ci self 10732d8ae3abSopenharmony_ci } 10742d8ae3abSopenharmony_ci 10752d8ae3abSopenharmony_ci /// Set [`metadata`](struct.Record.html#method.metadata). Construct a `Metadata` object with [`MetadataBuilder`](struct.MetadataBuilder.html). 10762d8ae3abSopenharmony_ci #[inline] 10772d8ae3abSopenharmony_ci pub fn metadata(&mut self, metadata: Metadata<'a>) -> &mut RecordBuilder<'a> { 10782d8ae3abSopenharmony_ci self.record.metadata = metadata; 10792d8ae3abSopenharmony_ci self 10802d8ae3abSopenharmony_ci } 10812d8ae3abSopenharmony_ci 10822d8ae3abSopenharmony_ci /// Set [`Metadata::level`](struct.Metadata.html#method.level). 10832d8ae3abSopenharmony_ci #[inline] 10842d8ae3abSopenharmony_ci pub fn level(&mut self, level: Level) -> &mut RecordBuilder<'a> { 10852d8ae3abSopenharmony_ci self.record.metadata.level = level; 10862d8ae3abSopenharmony_ci self 10872d8ae3abSopenharmony_ci } 10882d8ae3abSopenharmony_ci 10892d8ae3abSopenharmony_ci /// Set [`Metadata::target`](struct.Metadata.html#method.target) 10902d8ae3abSopenharmony_ci #[inline] 10912d8ae3abSopenharmony_ci pub fn target(&mut self, target: &'a str) -> &mut RecordBuilder<'a> { 10922d8ae3abSopenharmony_ci self.record.metadata.target = target; 10932d8ae3abSopenharmony_ci self 10942d8ae3abSopenharmony_ci } 10952d8ae3abSopenharmony_ci 10962d8ae3abSopenharmony_ci /// Set [`module_path`](struct.Record.html#method.module_path) 10972d8ae3abSopenharmony_ci #[inline] 10982d8ae3abSopenharmony_ci pub fn module_path(&mut self, path: Option<&'a str>) -> &mut RecordBuilder<'a> { 10992d8ae3abSopenharmony_ci self.record.module_path = path.map(MaybeStaticStr::Borrowed); 11002d8ae3abSopenharmony_ci self 11012d8ae3abSopenharmony_ci } 11022d8ae3abSopenharmony_ci 11032d8ae3abSopenharmony_ci /// Set [`module_path`](struct.Record.html#method.module_path) to a `'static` string 11042d8ae3abSopenharmony_ci #[inline] 11052d8ae3abSopenharmony_ci pub fn module_path_static(&mut self, path: Option<&'static str>) -> &mut RecordBuilder<'a> { 11062d8ae3abSopenharmony_ci self.record.module_path = path.map(MaybeStaticStr::Static); 11072d8ae3abSopenharmony_ci self 11082d8ae3abSopenharmony_ci } 11092d8ae3abSopenharmony_ci 11102d8ae3abSopenharmony_ci /// Set [`file`](struct.Record.html#method.file) 11112d8ae3abSopenharmony_ci #[inline] 11122d8ae3abSopenharmony_ci pub fn file(&mut self, file: Option<&'a str>) -> &mut RecordBuilder<'a> { 11132d8ae3abSopenharmony_ci self.record.file = file.map(MaybeStaticStr::Borrowed); 11142d8ae3abSopenharmony_ci self 11152d8ae3abSopenharmony_ci } 11162d8ae3abSopenharmony_ci 11172d8ae3abSopenharmony_ci /// Set [`file`](struct.Record.html#method.file) to a `'static` string. 11182d8ae3abSopenharmony_ci #[inline] 11192d8ae3abSopenharmony_ci pub fn file_static(&mut self, file: Option<&'static str>) -> &mut RecordBuilder<'a> { 11202d8ae3abSopenharmony_ci self.record.file = file.map(MaybeStaticStr::Static); 11212d8ae3abSopenharmony_ci self 11222d8ae3abSopenharmony_ci } 11232d8ae3abSopenharmony_ci 11242d8ae3abSopenharmony_ci /// Set [`line`](struct.Record.html#method.line) 11252d8ae3abSopenharmony_ci #[inline] 11262d8ae3abSopenharmony_ci pub fn line(&mut self, line: Option<u32>) -> &mut RecordBuilder<'a> { 11272d8ae3abSopenharmony_ci self.record.line = line; 11282d8ae3abSopenharmony_ci self 11292d8ae3abSopenharmony_ci } 11302d8ae3abSopenharmony_ci 11312d8ae3abSopenharmony_ci /// Set [`key_values`](struct.Record.html#method.key_values) 11322d8ae3abSopenharmony_ci #[cfg(feature = "kv_unstable")] 11332d8ae3abSopenharmony_ci #[inline] 11342d8ae3abSopenharmony_ci pub fn key_values(&mut self, kvs: &'a dyn kv::Source) -> &mut RecordBuilder<'a> { 11352d8ae3abSopenharmony_ci self.record.key_values = KeyValues(kvs); 11362d8ae3abSopenharmony_ci self 11372d8ae3abSopenharmony_ci } 11382d8ae3abSopenharmony_ci 11392d8ae3abSopenharmony_ci /// Invoke the builder and return a `Record` 11402d8ae3abSopenharmony_ci #[inline] 11412d8ae3abSopenharmony_ci pub fn build(&self) -> Record<'a> { 11422d8ae3abSopenharmony_ci self.record.clone() 11432d8ae3abSopenharmony_ci } 11442d8ae3abSopenharmony_ci} 11452d8ae3abSopenharmony_ci 11462d8ae3abSopenharmony_ci/// Metadata about a log message. 11472d8ae3abSopenharmony_ci/// 11482d8ae3abSopenharmony_ci/// # Use 11492d8ae3abSopenharmony_ci/// 11502d8ae3abSopenharmony_ci/// `Metadata` structs are created when users of the library use 11512d8ae3abSopenharmony_ci/// logging macros. 11522d8ae3abSopenharmony_ci/// 11532d8ae3abSopenharmony_ci/// They are consumed by implementations of the `Log` trait in the 11542d8ae3abSopenharmony_ci/// `enabled` method. 11552d8ae3abSopenharmony_ci/// 11562d8ae3abSopenharmony_ci/// `Record`s use `Metadata` to determine the log message's severity 11572d8ae3abSopenharmony_ci/// and target. 11582d8ae3abSopenharmony_ci/// 11592d8ae3abSopenharmony_ci/// Users should use the `log_enabled!` macro in their code to avoid 11602d8ae3abSopenharmony_ci/// constructing expensive log messages. 11612d8ae3abSopenharmony_ci/// 11622d8ae3abSopenharmony_ci/// # Examples 11632d8ae3abSopenharmony_ci/// 11642d8ae3abSopenharmony_ci/// ```edition2018 11652d8ae3abSopenharmony_ci/// use log::{Record, Level, Metadata}; 11662d8ae3abSopenharmony_ci/// 11672d8ae3abSopenharmony_ci/// struct MyLogger; 11682d8ae3abSopenharmony_ci/// 11692d8ae3abSopenharmony_ci/// impl log::Log for MyLogger { 11702d8ae3abSopenharmony_ci/// fn enabled(&self, metadata: &Metadata) -> bool { 11712d8ae3abSopenharmony_ci/// metadata.level() <= Level::Info 11722d8ae3abSopenharmony_ci/// } 11732d8ae3abSopenharmony_ci/// 11742d8ae3abSopenharmony_ci/// fn log(&self, record: &Record) { 11752d8ae3abSopenharmony_ci/// if self.enabled(record.metadata()) { 11762d8ae3abSopenharmony_ci/// println!("{} - {}", record.level(), record.args()); 11772d8ae3abSopenharmony_ci/// } 11782d8ae3abSopenharmony_ci/// } 11792d8ae3abSopenharmony_ci/// fn flush(&self) {} 11802d8ae3abSopenharmony_ci/// } 11812d8ae3abSopenharmony_ci/// 11822d8ae3abSopenharmony_ci/// # fn main(){} 11832d8ae3abSopenharmony_ci/// ``` 11842d8ae3abSopenharmony_ci#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] 11852d8ae3abSopenharmony_cipub struct Metadata<'a> { 11862d8ae3abSopenharmony_ci level: Level, 11872d8ae3abSopenharmony_ci target: &'a str, 11882d8ae3abSopenharmony_ci} 11892d8ae3abSopenharmony_ci 11902d8ae3abSopenharmony_ciimpl<'a> Metadata<'a> { 11912d8ae3abSopenharmony_ci /// Returns a new builder. 11922d8ae3abSopenharmony_ci #[inline] 11932d8ae3abSopenharmony_ci pub fn builder() -> MetadataBuilder<'a> { 11942d8ae3abSopenharmony_ci MetadataBuilder::new() 11952d8ae3abSopenharmony_ci } 11962d8ae3abSopenharmony_ci 11972d8ae3abSopenharmony_ci /// The verbosity level of the message. 11982d8ae3abSopenharmony_ci #[inline] 11992d8ae3abSopenharmony_ci pub fn level(&self) -> Level { 12002d8ae3abSopenharmony_ci self.level 12012d8ae3abSopenharmony_ci } 12022d8ae3abSopenharmony_ci 12032d8ae3abSopenharmony_ci /// The name of the target of the directive. 12042d8ae3abSopenharmony_ci #[inline] 12052d8ae3abSopenharmony_ci pub fn target(&self) -> &'a str { 12062d8ae3abSopenharmony_ci self.target 12072d8ae3abSopenharmony_ci } 12082d8ae3abSopenharmony_ci} 12092d8ae3abSopenharmony_ci 12102d8ae3abSopenharmony_ci/// Builder for [`Metadata`](struct.Metadata.html). 12112d8ae3abSopenharmony_ci/// 12122d8ae3abSopenharmony_ci/// Typically should only be used by log library creators or for testing and "shim loggers". 12132d8ae3abSopenharmony_ci/// The `MetadataBuilder` can set the different parameters of a `Metadata` object, and returns 12142d8ae3abSopenharmony_ci/// the created object when `build` is called. 12152d8ae3abSopenharmony_ci/// 12162d8ae3abSopenharmony_ci/// # Example 12172d8ae3abSopenharmony_ci/// 12182d8ae3abSopenharmony_ci/// ```edition2018 12192d8ae3abSopenharmony_ci/// let target = "myApp"; 12202d8ae3abSopenharmony_ci/// use log::{Level, MetadataBuilder}; 12212d8ae3abSopenharmony_ci/// let metadata = MetadataBuilder::new() 12222d8ae3abSopenharmony_ci/// .level(Level::Debug) 12232d8ae3abSopenharmony_ci/// .target(target) 12242d8ae3abSopenharmony_ci/// .build(); 12252d8ae3abSopenharmony_ci/// ``` 12262d8ae3abSopenharmony_ci#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] 12272d8ae3abSopenharmony_cipub struct MetadataBuilder<'a> { 12282d8ae3abSopenharmony_ci metadata: Metadata<'a>, 12292d8ae3abSopenharmony_ci} 12302d8ae3abSopenharmony_ci 12312d8ae3abSopenharmony_ciimpl<'a> MetadataBuilder<'a> { 12322d8ae3abSopenharmony_ci /// Construct a new `MetadataBuilder`. 12332d8ae3abSopenharmony_ci /// 12342d8ae3abSopenharmony_ci /// The default options are: 12352d8ae3abSopenharmony_ci /// 12362d8ae3abSopenharmony_ci /// - `level`: `Level::Info` 12372d8ae3abSopenharmony_ci /// - `target`: `""` 12382d8ae3abSopenharmony_ci #[inline] 12392d8ae3abSopenharmony_ci pub fn new() -> MetadataBuilder<'a> { 12402d8ae3abSopenharmony_ci MetadataBuilder { 12412d8ae3abSopenharmony_ci metadata: Metadata { 12422d8ae3abSopenharmony_ci level: Level::Info, 12432d8ae3abSopenharmony_ci target: "", 12442d8ae3abSopenharmony_ci }, 12452d8ae3abSopenharmony_ci } 12462d8ae3abSopenharmony_ci } 12472d8ae3abSopenharmony_ci 12482d8ae3abSopenharmony_ci /// Setter for [`level`](struct.Metadata.html#method.level). 12492d8ae3abSopenharmony_ci #[inline] 12502d8ae3abSopenharmony_ci pub fn level(&mut self, arg: Level) -> &mut MetadataBuilder<'a> { 12512d8ae3abSopenharmony_ci self.metadata.level = arg; 12522d8ae3abSopenharmony_ci self 12532d8ae3abSopenharmony_ci } 12542d8ae3abSopenharmony_ci 12552d8ae3abSopenharmony_ci /// Setter for [`target`](struct.Metadata.html#method.target). 12562d8ae3abSopenharmony_ci #[inline] 12572d8ae3abSopenharmony_ci pub fn target(&mut self, target: &'a str) -> &mut MetadataBuilder<'a> { 12582d8ae3abSopenharmony_ci self.metadata.target = target; 12592d8ae3abSopenharmony_ci self 12602d8ae3abSopenharmony_ci } 12612d8ae3abSopenharmony_ci 12622d8ae3abSopenharmony_ci /// Returns a `Metadata` object. 12632d8ae3abSopenharmony_ci #[inline] 12642d8ae3abSopenharmony_ci pub fn build(&self) -> Metadata<'a> { 12652d8ae3abSopenharmony_ci self.metadata.clone() 12662d8ae3abSopenharmony_ci } 12672d8ae3abSopenharmony_ci} 12682d8ae3abSopenharmony_ci 12692d8ae3abSopenharmony_ci/// A trait encapsulating the operations required of a logger. 12702d8ae3abSopenharmony_cipub trait Log: Sync + Send { 12712d8ae3abSopenharmony_ci /// Determines if a log message with the specified metadata would be 12722d8ae3abSopenharmony_ci /// logged. 12732d8ae3abSopenharmony_ci /// 12742d8ae3abSopenharmony_ci /// This is used by the `log_enabled!` macro to allow callers to avoid 12752d8ae3abSopenharmony_ci /// expensive computation of log message arguments if the message would be 12762d8ae3abSopenharmony_ci /// discarded anyway. 12772d8ae3abSopenharmony_ci /// 12782d8ae3abSopenharmony_ci /// # For implementors 12792d8ae3abSopenharmony_ci /// 12802d8ae3abSopenharmony_ci /// This method isn't called automatically by the `log!` macros. 12812d8ae3abSopenharmony_ci /// It's up to an implementation of the `Log` trait to call `enabled` in its own 12822d8ae3abSopenharmony_ci /// `log` method implementation to guarantee that filtering is applied. 12832d8ae3abSopenharmony_ci fn enabled(&self, metadata: &Metadata) -> bool; 12842d8ae3abSopenharmony_ci 12852d8ae3abSopenharmony_ci /// Logs the `Record`. 12862d8ae3abSopenharmony_ci /// 12872d8ae3abSopenharmony_ci /// # For implementors 12882d8ae3abSopenharmony_ci /// 12892d8ae3abSopenharmony_ci /// Note that `enabled` is *not* necessarily called before this method. 12902d8ae3abSopenharmony_ci /// Implementations of `log` should perform all necessary filtering 12912d8ae3abSopenharmony_ci /// internally. 12922d8ae3abSopenharmony_ci fn log(&self, record: &Record); 12932d8ae3abSopenharmony_ci 12942d8ae3abSopenharmony_ci /// Flushes any buffered records. 12952d8ae3abSopenharmony_ci fn flush(&self); 12962d8ae3abSopenharmony_ci} 12972d8ae3abSopenharmony_ci 12982d8ae3abSopenharmony_ci// Just used as a dummy initial value for LOGGER 12992d8ae3abSopenharmony_cistruct NopLogger; 13002d8ae3abSopenharmony_ci 13012d8ae3abSopenharmony_ciimpl Log for NopLogger { 13022d8ae3abSopenharmony_ci fn enabled(&self, _: &Metadata) -> bool { 13032d8ae3abSopenharmony_ci false 13042d8ae3abSopenharmony_ci } 13052d8ae3abSopenharmony_ci 13062d8ae3abSopenharmony_ci fn log(&self, _: &Record) {} 13072d8ae3abSopenharmony_ci fn flush(&self) {} 13082d8ae3abSopenharmony_ci} 13092d8ae3abSopenharmony_ci 13102d8ae3abSopenharmony_ciimpl<T> Log for &'_ T 13112d8ae3abSopenharmony_ciwhere 13122d8ae3abSopenharmony_ci T: ?Sized + Log, 13132d8ae3abSopenharmony_ci{ 13142d8ae3abSopenharmony_ci fn enabled(&self, metadata: &Metadata) -> bool { 13152d8ae3abSopenharmony_ci (**self).enabled(metadata) 13162d8ae3abSopenharmony_ci } 13172d8ae3abSopenharmony_ci 13182d8ae3abSopenharmony_ci fn log(&self, record: &Record) { 13192d8ae3abSopenharmony_ci (**self).log(record) 13202d8ae3abSopenharmony_ci } 13212d8ae3abSopenharmony_ci fn flush(&self) { 13222d8ae3abSopenharmony_ci (**self).flush() 13232d8ae3abSopenharmony_ci } 13242d8ae3abSopenharmony_ci} 13252d8ae3abSopenharmony_ci 13262d8ae3abSopenharmony_ci#[cfg(feature = "std")] 13272d8ae3abSopenharmony_ciimpl<T> Log for std::boxed::Box<T> 13282d8ae3abSopenharmony_ciwhere 13292d8ae3abSopenharmony_ci T: ?Sized + Log, 13302d8ae3abSopenharmony_ci{ 13312d8ae3abSopenharmony_ci fn enabled(&self, metadata: &Metadata) -> bool { 13322d8ae3abSopenharmony_ci self.as_ref().enabled(metadata) 13332d8ae3abSopenharmony_ci } 13342d8ae3abSopenharmony_ci 13352d8ae3abSopenharmony_ci fn log(&self, record: &Record) { 13362d8ae3abSopenharmony_ci self.as_ref().log(record) 13372d8ae3abSopenharmony_ci } 13382d8ae3abSopenharmony_ci fn flush(&self) { 13392d8ae3abSopenharmony_ci self.as_ref().flush() 13402d8ae3abSopenharmony_ci } 13412d8ae3abSopenharmony_ci} 13422d8ae3abSopenharmony_ci 13432d8ae3abSopenharmony_ci#[cfg(feature = "std")] 13442d8ae3abSopenharmony_ciimpl<T> Log for std::sync::Arc<T> 13452d8ae3abSopenharmony_ciwhere 13462d8ae3abSopenharmony_ci T: ?Sized + Log, 13472d8ae3abSopenharmony_ci{ 13482d8ae3abSopenharmony_ci fn enabled(&self, metadata: &Metadata) -> bool { 13492d8ae3abSopenharmony_ci self.as_ref().enabled(metadata) 13502d8ae3abSopenharmony_ci } 13512d8ae3abSopenharmony_ci 13522d8ae3abSopenharmony_ci fn log(&self, record: &Record) { 13532d8ae3abSopenharmony_ci self.as_ref().log(record) 13542d8ae3abSopenharmony_ci } 13552d8ae3abSopenharmony_ci fn flush(&self) { 13562d8ae3abSopenharmony_ci self.as_ref().flush() 13572d8ae3abSopenharmony_ci } 13582d8ae3abSopenharmony_ci} 13592d8ae3abSopenharmony_ci 13602d8ae3abSopenharmony_ci/// Sets the global maximum log level. 13612d8ae3abSopenharmony_ci/// 13622d8ae3abSopenharmony_ci/// Generally, this should only be called by the active logging implementation. 13632d8ae3abSopenharmony_ci/// 13642d8ae3abSopenharmony_ci/// Note that `Trace` is the maximum level, because it provides the maximum amount of detail in the emitted logs. 13652d8ae3abSopenharmony_ci#[inline] 13662d8ae3abSopenharmony_cipub fn set_max_level(level: LevelFilter) { 13672d8ae3abSopenharmony_ci MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed) 13682d8ae3abSopenharmony_ci} 13692d8ae3abSopenharmony_ci 13702d8ae3abSopenharmony_ci/// Returns the current maximum log level. 13712d8ae3abSopenharmony_ci/// 13722d8ae3abSopenharmony_ci/// The [`log!`], [`error!`], [`warn!`], [`info!`], [`debug!`], and [`trace!`] macros check 13732d8ae3abSopenharmony_ci/// this value and discard any message logged at a higher level. The maximum 13742d8ae3abSopenharmony_ci/// log level is set by the [`set_max_level`] function. 13752d8ae3abSopenharmony_ci/// 13762d8ae3abSopenharmony_ci/// [`log!`]: macro.log.html 13772d8ae3abSopenharmony_ci/// [`error!`]: macro.error.html 13782d8ae3abSopenharmony_ci/// [`warn!`]: macro.warn.html 13792d8ae3abSopenharmony_ci/// [`info!`]: macro.info.html 13802d8ae3abSopenharmony_ci/// [`debug!`]: macro.debug.html 13812d8ae3abSopenharmony_ci/// [`trace!`]: macro.trace.html 13822d8ae3abSopenharmony_ci/// [`set_max_level`]: fn.set_max_level.html 13832d8ae3abSopenharmony_ci#[inline(always)] 13842d8ae3abSopenharmony_cipub fn max_level() -> LevelFilter { 13852d8ae3abSopenharmony_ci // Since `LevelFilter` is `repr(usize)`, 13862d8ae3abSopenharmony_ci // this transmute is sound if and only if `MAX_LOG_LEVEL_FILTER` 13872d8ae3abSopenharmony_ci // is set to a usize that is a valid discriminant for `LevelFilter`. 13882d8ae3abSopenharmony_ci // Since `MAX_LOG_LEVEL_FILTER` is private, the only time it's set 13892d8ae3abSopenharmony_ci // is by `set_max_level` above, i.e. by casting a `LevelFilter` to `usize`. 13902d8ae3abSopenharmony_ci // So any usize stored in `MAX_LOG_LEVEL_FILTER` is a valid discriminant. 13912d8ae3abSopenharmony_ci unsafe { mem::transmute(MAX_LOG_LEVEL_FILTER.load(Ordering::Relaxed)) } 13922d8ae3abSopenharmony_ci} 13932d8ae3abSopenharmony_ci 13942d8ae3abSopenharmony_ci/// Sets the global logger to a `Box<Log>`. 13952d8ae3abSopenharmony_ci/// 13962d8ae3abSopenharmony_ci/// This is a simple convenience wrapper over `set_logger`, which takes a 13972d8ae3abSopenharmony_ci/// `Box<Log>` rather than a `&'static Log`. See the documentation for 13982d8ae3abSopenharmony_ci/// [`set_logger`] for more details. 13992d8ae3abSopenharmony_ci/// 14002d8ae3abSopenharmony_ci/// Requires the `std` feature. 14012d8ae3abSopenharmony_ci/// 14022d8ae3abSopenharmony_ci/// # Errors 14032d8ae3abSopenharmony_ci/// 14042d8ae3abSopenharmony_ci/// An error is returned if a logger has already been set. 14052d8ae3abSopenharmony_ci/// 14062d8ae3abSopenharmony_ci/// [`set_logger`]: fn.set_logger.html 14072d8ae3abSopenharmony_ci#[cfg(all(feature = "std", atomic_cas))] 14082d8ae3abSopenharmony_cipub fn set_boxed_logger(logger: Box<dyn Log>) -> Result<(), SetLoggerError> { 14092d8ae3abSopenharmony_ci set_logger_inner(|| Box::leak(logger)) 14102d8ae3abSopenharmony_ci} 14112d8ae3abSopenharmony_ci 14122d8ae3abSopenharmony_ci/// Sets the global logger to a `&'static Log`. 14132d8ae3abSopenharmony_ci/// 14142d8ae3abSopenharmony_ci/// This function may only be called once in the lifetime of a program. Any log 14152d8ae3abSopenharmony_ci/// events that occur before the call to `set_logger` completes will be ignored. 14162d8ae3abSopenharmony_ci/// 14172d8ae3abSopenharmony_ci/// This function does not typically need to be called manually. Logger 14182d8ae3abSopenharmony_ci/// implementations should provide an initialization method that installs the 14192d8ae3abSopenharmony_ci/// logger internally. 14202d8ae3abSopenharmony_ci/// 14212d8ae3abSopenharmony_ci/// # Availability 14222d8ae3abSopenharmony_ci/// 14232d8ae3abSopenharmony_ci/// This method is available even when the `std` feature is disabled. However, 14242d8ae3abSopenharmony_ci/// it is currently unavailable on `thumbv6` targets, which lack support for 14252d8ae3abSopenharmony_ci/// some atomic operations which are used by this function. Even on those 14262d8ae3abSopenharmony_ci/// targets, [`set_logger_racy`] will be available. 14272d8ae3abSopenharmony_ci/// 14282d8ae3abSopenharmony_ci/// # Errors 14292d8ae3abSopenharmony_ci/// 14302d8ae3abSopenharmony_ci/// An error is returned if a logger has already been set. 14312d8ae3abSopenharmony_ci/// 14322d8ae3abSopenharmony_ci/// # Examples 14332d8ae3abSopenharmony_ci/// 14342d8ae3abSopenharmony_ci/// ```edition2018 14352d8ae3abSopenharmony_ci/// use log::{error, info, warn, Record, Level, Metadata, LevelFilter}; 14362d8ae3abSopenharmony_ci/// 14372d8ae3abSopenharmony_ci/// static MY_LOGGER: MyLogger = MyLogger; 14382d8ae3abSopenharmony_ci/// 14392d8ae3abSopenharmony_ci/// struct MyLogger; 14402d8ae3abSopenharmony_ci/// 14412d8ae3abSopenharmony_ci/// impl log::Log for MyLogger { 14422d8ae3abSopenharmony_ci/// fn enabled(&self, metadata: &Metadata) -> bool { 14432d8ae3abSopenharmony_ci/// metadata.level() <= Level::Info 14442d8ae3abSopenharmony_ci/// } 14452d8ae3abSopenharmony_ci/// 14462d8ae3abSopenharmony_ci/// fn log(&self, record: &Record) { 14472d8ae3abSopenharmony_ci/// if self.enabled(record.metadata()) { 14482d8ae3abSopenharmony_ci/// println!("{} - {}", record.level(), record.args()); 14492d8ae3abSopenharmony_ci/// } 14502d8ae3abSopenharmony_ci/// } 14512d8ae3abSopenharmony_ci/// fn flush(&self) {} 14522d8ae3abSopenharmony_ci/// } 14532d8ae3abSopenharmony_ci/// 14542d8ae3abSopenharmony_ci/// # fn main(){ 14552d8ae3abSopenharmony_ci/// log::set_logger(&MY_LOGGER).unwrap(); 14562d8ae3abSopenharmony_ci/// log::set_max_level(LevelFilter::Info); 14572d8ae3abSopenharmony_ci/// 14582d8ae3abSopenharmony_ci/// info!("hello log"); 14592d8ae3abSopenharmony_ci/// warn!("warning"); 14602d8ae3abSopenharmony_ci/// error!("oops"); 14612d8ae3abSopenharmony_ci/// # } 14622d8ae3abSopenharmony_ci/// ``` 14632d8ae3abSopenharmony_ci/// 14642d8ae3abSopenharmony_ci/// [`set_logger_racy`]: fn.set_logger_racy.html 14652d8ae3abSopenharmony_ci#[cfg(atomic_cas)] 14662d8ae3abSopenharmony_cipub fn set_logger(logger: &'static dyn Log) -> Result<(), SetLoggerError> { 14672d8ae3abSopenharmony_ci set_logger_inner(|| logger) 14682d8ae3abSopenharmony_ci} 14692d8ae3abSopenharmony_ci 14702d8ae3abSopenharmony_ci#[cfg(atomic_cas)] 14712d8ae3abSopenharmony_cifn set_logger_inner<F>(make_logger: F) -> Result<(), SetLoggerError> 14722d8ae3abSopenharmony_ciwhere 14732d8ae3abSopenharmony_ci F: FnOnce() -> &'static dyn Log, 14742d8ae3abSopenharmony_ci{ 14752d8ae3abSopenharmony_ci let old_state = match STATE.compare_exchange( 14762d8ae3abSopenharmony_ci UNINITIALIZED, 14772d8ae3abSopenharmony_ci INITIALIZING, 14782d8ae3abSopenharmony_ci Ordering::SeqCst, 14792d8ae3abSopenharmony_ci Ordering::SeqCst, 14802d8ae3abSopenharmony_ci ) { 14812d8ae3abSopenharmony_ci Ok(s) | Err(s) => s, 14822d8ae3abSopenharmony_ci }; 14832d8ae3abSopenharmony_ci match old_state { 14842d8ae3abSopenharmony_ci UNINITIALIZED => { 14852d8ae3abSopenharmony_ci unsafe { 14862d8ae3abSopenharmony_ci LOGGER = make_logger(); 14872d8ae3abSopenharmony_ci } 14882d8ae3abSopenharmony_ci STATE.store(INITIALIZED, Ordering::SeqCst); 14892d8ae3abSopenharmony_ci Ok(()) 14902d8ae3abSopenharmony_ci } 14912d8ae3abSopenharmony_ci INITIALIZING => { 14922d8ae3abSopenharmony_ci while STATE.load(Ordering::SeqCst) == INITIALIZING { 14932d8ae3abSopenharmony_ci // TODO: replace with `hint::spin_loop` once MSRV is 1.49.0. 14942d8ae3abSopenharmony_ci #[allow(deprecated)] 14952d8ae3abSopenharmony_ci std::sync::atomic::spin_loop_hint(); 14962d8ae3abSopenharmony_ci } 14972d8ae3abSopenharmony_ci Err(SetLoggerError(())) 14982d8ae3abSopenharmony_ci } 14992d8ae3abSopenharmony_ci _ => Err(SetLoggerError(())), 15002d8ae3abSopenharmony_ci } 15012d8ae3abSopenharmony_ci} 15022d8ae3abSopenharmony_ci 15032d8ae3abSopenharmony_ci/// A thread-unsafe version of [`set_logger`]. 15042d8ae3abSopenharmony_ci/// 15052d8ae3abSopenharmony_ci/// This function is available on all platforms, even those that do not have 15062d8ae3abSopenharmony_ci/// support for atomics that is needed by [`set_logger`]. 15072d8ae3abSopenharmony_ci/// 15082d8ae3abSopenharmony_ci/// In almost all cases, [`set_logger`] should be preferred. 15092d8ae3abSopenharmony_ci/// 15102d8ae3abSopenharmony_ci/// # Safety 15112d8ae3abSopenharmony_ci/// 15122d8ae3abSopenharmony_ci/// This function is only safe to call when no other logger initialization 15132d8ae3abSopenharmony_ci/// function is called while this function still executes. 15142d8ae3abSopenharmony_ci/// 15152d8ae3abSopenharmony_ci/// This can be upheld by (for example) making sure that **there are no other 15162d8ae3abSopenharmony_ci/// threads**, and (on embedded) that **interrupts are disabled**. 15172d8ae3abSopenharmony_ci/// 15182d8ae3abSopenharmony_ci/// It is safe to use other logging functions while this function runs 15192d8ae3abSopenharmony_ci/// (including all logging macros). 15202d8ae3abSopenharmony_ci/// 15212d8ae3abSopenharmony_ci/// [`set_logger`]: fn.set_logger.html 15222d8ae3abSopenharmony_cipub unsafe fn set_logger_racy(logger: &'static dyn Log) -> Result<(), SetLoggerError> { 15232d8ae3abSopenharmony_ci match STATE.load(Ordering::SeqCst) { 15242d8ae3abSopenharmony_ci UNINITIALIZED => { 15252d8ae3abSopenharmony_ci LOGGER = logger; 15262d8ae3abSopenharmony_ci STATE.store(INITIALIZED, Ordering::SeqCst); 15272d8ae3abSopenharmony_ci Ok(()) 15282d8ae3abSopenharmony_ci } 15292d8ae3abSopenharmony_ci INITIALIZING => { 15302d8ae3abSopenharmony_ci // This is just plain UB, since we were racing another initialization function 15312d8ae3abSopenharmony_ci unreachable!("set_logger_racy must not be used with other initialization functions") 15322d8ae3abSopenharmony_ci } 15332d8ae3abSopenharmony_ci _ => Err(SetLoggerError(())), 15342d8ae3abSopenharmony_ci } 15352d8ae3abSopenharmony_ci} 15362d8ae3abSopenharmony_ci 15372d8ae3abSopenharmony_ci/// The type returned by [`set_logger`] if [`set_logger`] has already been called. 15382d8ae3abSopenharmony_ci/// 15392d8ae3abSopenharmony_ci/// [`set_logger`]: fn.set_logger.html 15402d8ae3abSopenharmony_ci#[allow(missing_copy_implementations)] 15412d8ae3abSopenharmony_ci#[derive(Debug)] 15422d8ae3abSopenharmony_cipub struct SetLoggerError(()); 15432d8ae3abSopenharmony_ci 15442d8ae3abSopenharmony_ciimpl fmt::Display for SetLoggerError { 15452d8ae3abSopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 15462d8ae3abSopenharmony_ci fmt.write_str(SET_LOGGER_ERROR) 15472d8ae3abSopenharmony_ci } 15482d8ae3abSopenharmony_ci} 15492d8ae3abSopenharmony_ci 15502d8ae3abSopenharmony_ci// The Error trait is not available in libcore 15512d8ae3abSopenharmony_ci#[cfg(feature = "std")] 15522d8ae3abSopenharmony_ciimpl error::Error for SetLoggerError {} 15532d8ae3abSopenharmony_ci 15542d8ae3abSopenharmony_ci/// The type returned by [`from_str`] when the string doesn't match any of the log levels. 15552d8ae3abSopenharmony_ci/// 15562d8ae3abSopenharmony_ci/// [`from_str`]: https://doc.rust-lang.org/std/str/trait.FromStr.html#tymethod.from_str 15572d8ae3abSopenharmony_ci#[allow(missing_copy_implementations)] 15582d8ae3abSopenharmony_ci#[derive(Debug, PartialEq)] 15592d8ae3abSopenharmony_cipub struct ParseLevelError(()); 15602d8ae3abSopenharmony_ci 15612d8ae3abSopenharmony_ciimpl fmt::Display for ParseLevelError { 15622d8ae3abSopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 15632d8ae3abSopenharmony_ci fmt.write_str(LEVEL_PARSE_ERROR) 15642d8ae3abSopenharmony_ci } 15652d8ae3abSopenharmony_ci} 15662d8ae3abSopenharmony_ci 15672d8ae3abSopenharmony_ci// The Error trait is not available in libcore 15682d8ae3abSopenharmony_ci#[cfg(feature = "std")] 15692d8ae3abSopenharmony_ciimpl error::Error for ParseLevelError {} 15702d8ae3abSopenharmony_ci 15712d8ae3abSopenharmony_ci/// Returns a reference to the logger. 15722d8ae3abSopenharmony_ci/// 15732d8ae3abSopenharmony_ci/// If a logger has not been set, a no-op implementation is returned. 15742d8ae3abSopenharmony_cipub fn logger() -> &'static dyn Log { 15752d8ae3abSopenharmony_ci if STATE.load(Ordering::SeqCst) != INITIALIZED { 15762d8ae3abSopenharmony_ci static NOP: NopLogger = NopLogger; 15772d8ae3abSopenharmony_ci &NOP 15782d8ae3abSopenharmony_ci } else { 15792d8ae3abSopenharmony_ci unsafe { LOGGER } 15802d8ae3abSopenharmony_ci } 15812d8ae3abSopenharmony_ci} 15822d8ae3abSopenharmony_ci 15832d8ae3abSopenharmony_ci// WARNING: this is not part of the crate's public API and is subject to change at any time 15842d8ae3abSopenharmony_ci#[doc(hidden)] 15852d8ae3abSopenharmony_ci#[cfg(not(feature = "kv_unstable"))] 15862d8ae3abSopenharmony_cipub fn __private_api_log( 15872d8ae3abSopenharmony_ci args: fmt::Arguments, 15882d8ae3abSopenharmony_ci level: Level, 15892d8ae3abSopenharmony_ci &(target, module_path, file, line): &(&str, &'static str, &'static str, u32), 15902d8ae3abSopenharmony_ci kvs: Option<&[(&str, &str)]>, 15912d8ae3abSopenharmony_ci) { 15922d8ae3abSopenharmony_ci if kvs.is_some() { 15932d8ae3abSopenharmony_ci panic!( 15942d8ae3abSopenharmony_ci "key-value support is experimental and must be enabled using the `kv_unstable` feature" 15952d8ae3abSopenharmony_ci ) 15962d8ae3abSopenharmony_ci } 15972d8ae3abSopenharmony_ci 15982d8ae3abSopenharmony_ci logger().log( 15992d8ae3abSopenharmony_ci &Record::builder() 16002d8ae3abSopenharmony_ci .args(args) 16012d8ae3abSopenharmony_ci .level(level) 16022d8ae3abSopenharmony_ci .target(target) 16032d8ae3abSopenharmony_ci .module_path_static(Some(module_path)) 16042d8ae3abSopenharmony_ci .file_static(Some(file)) 16052d8ae3abSopenharmony_ci .line(Some(line)) 16062d8ae3abSopenharmony_ci .build(), 16072d8ae3abSopenharmony_ci ); 16082d8ae3abSopenharmony_ci} 16092d8ae3abSopenharmony_ci 16102d8ae3abSopenharmony_ci// WARNING: this is not part of the crate's public API and is subject to change at any time 16112d8ae3abSopenharmony_ci#[doc(hidden)] 16122d8ae3abSopenharmony_ci#[cfg(feature = "kv_unstable")] 16132d8ae3abSopenharmony_cipub fn __private_api_log( 16142d8ae3abSopenharmony_ci args: fmt::Arguments, 16152d8ae3abSopenharmony_ci level: Level, 16162d8ae3abSopenharmony_ci &(target, module_path, file, line): &(&str, &'static str, &'static str, u32), 16172d8ae3abSopenharmony_ci kvs: Option<&[(&str, &dyn kv::ToValue)]>, 16182d8ae3abSopenharmony_ci) { 16192d8ae3abSopenharmony_ci logger().log( 16202d8ae3abSopenharmony_ci &Record::builder() 16212d8ae3abSopenharmony_ci .args(args) 16222d8ae3abSopenharmony_ci .level(level) 16232d8ae3abSopenharmony_ci .target(target) 16242d8ae3abSopenharmony_ci .module_path_static(Some(module_path)) 16252d8ae3abSopenharmony_ci .file_static(Some(file)) 16262d8ae3abSopenharmony_ci .line(Some(line)) 16272d8ae3abSopenharmony_ci .key_values(&kvs) 16282d8ae3abSopenharmony_ci .build(), 16292d8ae3abSopenharmony_ci ); 16302d8ae3abSopenharmony_ci} 16312d8ae3abSopenharmony_ci 16322d8ae3abSopenharmony_ci// WARNING: this is not part of the crate's public API and is subject to change at any time 16332d8ae3abSopenharmony_ci#[doc(hidden)] 16342d8ae3abSopenharmony_cipub fn __private_api_enabled(level: Level, target: &str) -> bool { 16352d8ae3abSopenharmony_ci logger().enabled(&Metadata::builder().level(level).target(target).build()) 16362d8ae3abSopenharmony_ci} 16372d8ae3abSopenharmony_ci 16382d8ae3abSopenharmony_ci// WARNING: this is not part of the crate's public API and is subject to change at any time 16392d8ae3abSopenharmony_ci#[doc(hidden)] 16402d8ae3abSopenharmony_cipub mod __private_api { 16412d8ae3abSopenharmony_ci pub use std::option::Option; 16422d8ae3abSopenharmony_ci} 16432d8ae3abSopenharmony_ci 16442d8ae3abSopenharmony_ci/// The statically resolved maximum log level. 16452d8ae3abSopenharmony_ci/// 16462d8ae3abSopenharmony_ci/// See the crate level documentation for information on how to configure this. 16472d8ae3abSopenharmony_ci/// 16482d8ae3abSopenharmony_ci/// This value is checked by the log macros, but not by the `Log`ger returned by 16492d8ae3abSopenharmony_ci/// the [`logger`] function. Code that manually calls functions on that value 16502d8ae3abSopenharmony_ci/// should compare the level against this value. 16512d8ae3abSopenharmony_ci/// 16522d8ae3abSopenharmony_ci/// [`logger`]: fn.logger.html 16532d8ae3abSopenharmony_cipub const STATIC_MAX_LEVEL: LevelFilter = MAX_LEVEL_INNER; 16542d8ae3abSopenharmony_ci 16552d8ae3abSopenharmony_cicfg_if! { 16562d8ae3abSopenharmony_ci if #[cfg(all(not(debug_assertions), feature = "release_max_level_off"))] { 16572d8ae3abSopenharmony_ci const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Off; 16582d8ae3abSopenharmony_ci } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_error"))] { 16592d8ae3abSopenharmony_ci const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Error; 16602d8ae3abSopenharmony_ci } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_warn"))] { 16612d8ae3abSopenharmony_ci const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Warn; 16622d8ae3abSopenharmony_ci } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_info"))] { 16632d8ae3abSopenharmony_ci const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Info; 16642d8ae3abSopenharmony_ci } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_debug"))] { 16652d8ae3abSopenharmony_ci const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Debug; 16662d8ae3abSopenharmony_ci } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_trace"))] { 16672d8ae3abSopenharmony_ci const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Trace; 16682d8ae3abSopenharmony_ci } else if #[cfg(feature = "max_level_off")] { 16692d8ae3abSopenharmony_ci const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Off; 16702d8ae3abSopenharmony_ci } else if #[cfg(feature = "max_level_error")] { 16712d8ae3abSopenharmony_ci const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Error; 16722d8ae3abSopenharmony_ci } else if #[cfg(feature = "max_level_warn")] { 16732d8ae3abSopenharmony_ci const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Warn; 16742d8ae3abSopenharmony_ci } else if #[cfg(feature = "max_level_info")] { 16752d8ae3abSopenharmony_ci const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Info; 16762d8ae3abSopenharmony_ci } else if #[cfg(feature = "max_level_debug")] { 16772d8ae3abSopenharmony_ci const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Debug; 16782d8ae3abSopenharmony_ci } else { 16792d8ae3abSopenharmony_ci const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Trace; 16802d8ae3abSopenharmony_ci } 16812d8ae3abSopenharmony_ci} 16822d8ae3abSopenharmony_ci 16832d8ae3abSopenharmony_ci#[cfg(test)] 16842d8ae3abSopenharmony_cimod tests { 16852d8ae3abSopenharmony_ci extern crate std; 16862d8ae3abSopenharmony_ci use super::{Level, LevelFilter, ParseLevelError}; 16872d8ae3abSopenharmony_ci use tests::std::string::ToString; 16882d8ae3abSopenharmony_ci 16892d8ae3abSopenharmony_ci #[test] 16902d8ae3abSopenharmony_ci fn test_levelfilter_from_str() { 16912d8ae3abSopenharmony_ci let tests = [ 16922d8ae3abSopenharmony_ci ("off", Ok(LevelFilter::Off)), 16932d8ae3abSopenharmony_ci ("error", Ok(LevelFilter::Error)), 16942d8ae3abSopenharmony_ci ("warn", Ok(LevelFilter::Warn)), 16952d8ae3abSopenharmony_ci ("info", Ok(LevelFilter::Info)), 16962d8ae3abSopenharmony_ci ("debug", Ok(LevelFilter::Debug)), 16972d8ae3abSopenharmony_ci ("trace", Ok(LevelFilter::Trace)), 16982d8ae3abSopenharmony_ci ("OFF", Ok(LevelFilter::Off)), 16992d8ae3abSopenharmony_ci ("ERROR", Ok(LevelFilter::Error)), 17002d8ae3abSopenharmony_ci ("WARN", Ok(LevelFilter::Warn)), 17012d8ae3abSopenharmony_ci ("INFO", Ok(LevelFilter::Info)), 17022d8ae3abSopenharmony_ci ("DEBUG", Ok(LevelFilter::Debug)), 17032d8ae3abSopenharmony_ci ("TRACE", Ok(LevelFilter::Trace)), 17042d8ae3abSopenharmony_ci ("asdf", Err(ParseLevelError(()))), 17052d8ae3abSopenharmony_ci ]; 17062d8ae3abSopenharmony_ci for &(s, ref expected) in &tests { 17072d8ae3abSopenharmony_ci assert_eq!(expected, &s.parse()); 17082d8ae3abSopenharmony_ci } 17092d8ae3abSopenharmony_ci } 17102d8ae3abSopenharmony_ci 17112d8ae3abSopenharmony_ci #[test] 17122d8ae3abSopenharmony_ci fn test_level_from_str() { 17132d8ae3abSopenharmony_ci let tests = [ 17142d8ae3abSopenharmony_ci ("OFF", Err(ParseLevelError(()))), 17152d8ae3abSopenharmony_ci ("error", Ok(Level::Error)), 17162d8ae3abSopenharmony_ci ("warn", Ok(Level::Warn)), 17172d8ae3abSopenharmony_ci ("info", Ok(Level::Info)), 17182d8ae3abSopenharmony_ci ("debug", Ok(Level::Debug)), 17192d8ae3abSopenharmony_ci ("trace", Ok(Level::Trace)), 17202d8ae3abSopenharmony_ci ("ERROR", Ok(Level::Error)), 17212d8ae3abSopenharmony_ci ("WARN", Ok(Level::Warn)), 17222d8ae3abSopenharmony_ci ("INFO", Ok(Level::Info)), 17232d8ae3abSopenharmony_ci ("DEBUG", Ok(Level::Debug)), 17242d8ae3abSopenharmony_ci ("TRACE", Ok(Level::Trace)), 17252d8ae3abSopenharmony_ci ("asdf", Err(ParseLevelError(()))), 17262d8ae3abSopenharmony_ci ]; 17272d8ae3abSopenharmony_ci for &(s, ref expected) in &tests { 17282d8ae3abSopenharmony_ci assert_eq!(expected, &s.parse()); 17292d8ae3abSopenharmony_ci } 17302d8ae3abSopenharmony_ci } 17312d8ae3abSopenharmony_ci 17322d8ae3abSopenharmony_ci #[test] 17332d8ae3abSopenharmony_ci fn test_level_as_str() { 17342d8ae3abSopenharmony_ci let tests = &[ 17352d8ae3abSopenharmony_ci (Level::Error, "ERROR"), 17362d8ae3abSopenharmony_ci (Level::Warn, "WARN"), 17372d8ae3abSopenharmony_ci (Level::Info, "INFO"), 17382d8ae3abSopenharmony_ci (Level::Debug, "DEBUG"), 17392d8ae3abSopenharmony_ci (Level::Trace, "TRACE"), 17402d8ae3abSopenharmony_ci ]; 17412d8ae3abSopenharmony_ci for (input, expected) in tests { 17422d8ae3abSopenharmony_ci assert_eq!(*expected, input.as_str()); 17432d8ae3abSopenharmony_ci } 17442d8ae3abSopenharmony_ci } 17452d8ae3abSopenharmony_ci 17462d8ae3abSopenharmony_ci #[test] 17472d8ae3abSopenharmony_ci fn test_level_show() { 17482d8ae3abSopenharmony_ci assert_eq!("INFO", Level::Info.to_string()); 17492d8ae3abSopenharmony_ci assert_eq!("ERROR", Level::Error.to_string()); 17502d8ae3abSopenharmony_ci } 17512d8ae3abSopenharmony_ci 17522d8ae3abSopenharmony_ci #[test] 17532d8ae3abSopenharmony_ci fn test_levelfilter_show() { 17542d8ae3abSopenharmony_ci assert_eq!("OFF", LevelFilter::Off.to_string()); 17552d8ae3abSopenharmony_ci assert_eq!("ERROR", LevelFilter::Error.to_string()); 17562d8ae3abSopenharmony_ci } 17572d8ae3abSopenharmony_ci 17582d8ae3abSopenharmony_ci #[test] 17592d8ae3abSopenharmony_ci fn test_cross_cmp() { 17602d8ae3abSopenharmony_ci assert!(Level::Debug > LevelFilter::Error); 17612d8ae3abSopenharmony_ci assert!(LevelFilter::Warn < Level::Trace); 17622d8ae3abSopenharmony_ci assert!(LevelFilter::Off < Level::Error); 17632d8ae3abSopenharmony_ci } 17642d8ae3abSopenharmony_ci 17652d8ae3abSopenharmony_ci #[test] 17662d8ae3abSopenharmony_ci fn test_cross_eq() { 17672d8ae3abSopenharmony_ci assert!(Level::Error == LevelFilter::Error); 17682d8ae3abSopenharmony_ci assert!(LevelFilter::Off != Level::Error); 17692d8ae3abSopenharmony_ci assert!(Level::Trace == LevelFilter::Trace); 17702d8ae3abSopenharmony_ci } 17712d8ae3abSopenharmony_ci 17722d8ae3abSopenharmony_ci #[test] 17732d8ae3abSopenharmony_ci fn test_to_level() { 17742d8ae3abSopenharmony_ci assert_eq!(Some(Level::Error), LevelFilter::Error.to_level()); 17752d8ae3abSopenharmony_ci assert_eq!(None, LevelFilter::Off.to_level()); 17762d8ae3abSopenharmony_ci assert_eq!(Some(Level::Debug), LevelFilter::Debug.to_level()); 17772d8ae3abSopenharmony_ci } 17782d8ae3abSopenharmony_ci 17792d8ae3abSopenharmony_ci #[test] 17802d8ae3abSopenharmony_ci fn test_to_level_filter() { 17812d8ae3abSopenharmony_ci assert_eq!(LevelFilter::Error, Level::Error.to_level_filter()); 17822d8ae3abSopenharmony_ci assert_eq!(LevelFilter::Trace, Level::Trace.to_level_filter()); 17832d8ae3abSopenharmony_ci } 17842d8ae3abSopenharmony_ci 17852d8ae3abSopenharmony_ci #[test] 17862d8ae3abSopenharmony_ci fn test_level_filter_as_str() { 17872d8ae3abSopenharmony_ci let tests = &[ 17882d8ae3abSopenharmony_ci (LevelFilter::Off, "OFF"), 17892d8ae3abSopenharmony_ci (LevelFilter::Error, "ERROR"), 17902d8ae3abSopenharmony_ci (LevelFilter::Warn, "WARN"), 17912d8ae3abSopenharmony_ci (LevelFilter::Info, "INFO"), 17922d8ae3abSopenharmony_ci (LevelFilter::Debug, "DEBUG"), 17932d8ae3abSopenharmony_ci (LevelFilter::Trace, "TRACE"), 17942d8ae3abSopenharmony_ci ]; 17952d8ae3abSopenharmony_ci for (input, expected) in tests { 17962d8ae3abSopenharmony_ci assert_eq!(*expected, input.as_str()); 17972d8ae3abSopenharmony_ci } 17982d8ae3abSopenharmony_ci } 17992d8ae3abSopenharmony_ci 18002d8ae3abSopenharmony_ci #[test] 18012d8ae3abSopenharmony_ci #[cfg(feature = "std")] 18022d8ae3abSopenharmony_ci fn test_error_trait() { 18032d8ae3abSopenharmony_ci use super::SetLoggerError; 18042d8ae3abSopenharmony_ci let e = SetLoggerError(()); 18052d8ae3abSopenharmony_ci assert_eq!( 18062d8ae3abSopenharmony_ci &e.to_string(), 18072d8ae3abSopenharmony_ci "attempted to set a logger after the logging system \ 18082d8ae3abSopenharmony_ci was already initialized" 18092d8ae3abSopenharmony_ci ); 18102d8ae3abSopenharmony_ci } 18112d8ae3abSopenharmony_ci 18122d8ae3abSopenharmony_ci #[test] 18132d8ae3abSopenharmony_ci fn test_metadata_builder() { 18142d8ae3abSopenharmony_ci use super::MetadataBuilder; 18152d8ae3abSopenharmony_ci let target = "myApp"; 18162d8ae3abSopenharmony_ci let metadata_test = MetadataBuilder::new() 18172d8ae3abSopenharmony_ci .level(Level::Debug) 18182d8ae3abSopenharmony_ci .target(target) 18192d8ae3abSopenharmony_ci .build(); 18202d8ae3abSopenharmony_ci assert_eq!(metadata_test.level(), Level::Debug); 18212d8ae3abSopenharmony_ci assert_eq!(metadata_test.target(), "myApp"); 18222d8ae3abSopenharmony_ci } 18232d8ae3abSopenharmony_ci 18242d8ae3abSopenharmony_ci #[test] 18252d8ae3abSopenharmony_ci fn test_metadata_convenience_builder() { 18262d8ae3abSopenharmony_ci use super::Metadata; 18272d8ae3abSopenharmony_ci let target = "myApp"; 18282d8ae3abSopenharmony_ci let metadata_test = Metadata::builder() 18292d8ae3abSopenharmony_ci .level(Level::Debug) 18302d8ae3abSopenharmony_ci .target(target) 18312d8ae3abSopenharmony_ci .build(); 18322d8ae3abSopenharmony_ci assert_eq!(metadata_test.level(), Level::Debug); 18332d8ae3abSopenharmony_ci assert_eq!(metadata_test.target(), "myApp"); 18342d8ae3abSopenharmony_ci } 18352d8ae3abSopenharmony_ci 18362d8ae3abSopenharmony_ci #[test] 18372d8ae3abSopenharmony_ci fn test_record_builder() { 18382d8ae3abSopenharmony_ci use super::{MetadataBuilder, RecordBuilder}; 18392d8ae3abSopenharmony_ci let target = "myApp"; 18402d8ae3abSopenharmony_ci let metadata = MetadataBuilder::new().target(target).build(); 18412d8ae3abSopenharmony_ci let fmt_args = format_args!("hello"); 18422d8ae3abSopenharmony_ci let record_test = RecordBuilder::new() 18432d8ae3abSopenharmony_ci .args(fmt_args) 18442d8ae3abSopenharmony_ci .metadata(metadata) 18452d8ae3abSopenharmony_ci .module_path(Some("foo")) 18462d8ae3abSopenharmony_ci .file(Some("bar")) 18472d8ae3abSopenharmony_ci .line(Some(30)) 18482d8ae3abSopenharmony_ci .build(); 18492d8ae3abSopenharmony_ci assert_eq!(record_test.metadata().target(), "myApp"); 18502d8ae3abSopenharmony_ci assert_eq!(record_test.module_path(), Some("foo")); 18512d8ae3abSopenharmony_ci assert_eq!(record_test.file(), Some("bar")); 18522d8ae3abSopenharmony_ci assert_eq!(record_test.line(), Some(30)); 18532d8ae3abSopenharmony_ci } 18542d8ae3abSopenharmony_ci 18552d8ae3abSopenharmony_ci #[test] 18562d8ae3abSopenharmony_ci fn test_record_convenience_builder() { 18572d8ae3abSopenharmony_ci use super::{Metadata, Record}; 18582d8ae3abSopenharmony_ci let target = "myApp"; 18592d8ae3abSopenharmony_ci let metadata = Metadata::builder().target(target).build(); 18602d8ae3abSopenharmony_ci let fmt_args = format_args!("hello"); 18612d8ae3abSopenharmony_ci let record_test = Record::builder() 18622d8ae3abSopenharmony_ci .args(fmt_args) 18632d8ae3abSopenharmony_ci .metadata(metadata) 18642d8ae3abSopenharmony_ci .module_path(Some("foo")) 18652d8ae3abSopenharmony_ci .file(Some("bar")) 18662d8ae3abSopenharmony_ci .line(Some(30)) 18672d8ae3abSopenharmony_ci .build(); 18682d8ae3abSopenharmony_ci assert_eq!(record_test.target(), "myApp"); 18692d8ae3abSopenharmony_ci assert_eq!(record_test.module_path(), Some("foo")); 18702d8ae3abSopenharmony_ci assert_eq!(record_test.file(), Some("bar")); 18712d8ae3abSopenharmony_ci assert_eq!(record_test.line(), Some(30)); 18722d8ae3abSopenharmony_ci } 18732d8ae3abSopenharmony_ci 18742d8ae3abSopenharmony_ci #[test] 18752d8ae3abSopenharmony_ci fn test_record_complete_builder() { 18762d8ae3abSopenharmony_ci use super::{Level, Record}; 18772d8ae3abSopenharmony_ci let target = "myApp"; 18782d8ae3abSopenharmony_ci let record_test = Record::builder() 18792d8ae3abSopenharmony_ci .module_path(Some("foo")) 18802d8ae3abSopenharmony_ci .file(Some("bar")) 18812d8ae3abSopenharmony_ci .line(Some(30)) 18822d8ae3abSopenharmony_ci .target(target) 18832d8ae3abSopenharmony_ci .level(Level::Error) 18842d8ae3abSopenharmony_ci .build(); 18852d8ae3abSopenharmony_ci assert_eq!(record_test.target(), "myApp"); 18862d8ae3abSopenharmony_ci assert_eq!(record_test.level(), Level::Error); 18872d8ae3abSopenharmony_ci assert_eq!(record_test.module_path(), Some("foo")); 18882d8ae3abSopenharmony_ci assert_eq!(record_test.file(), Some("bar")); 18892d8ae3abSopenharmony_ci assert_eq!(record_test.line(), Some(30)); 18902d8ae3abSopenharmony_ci } 18912d8ae3abSopenharmony_ci 18922d8ae3abSopenharmony_ci #[test] 18932d8ae3abSopenharmony_ci #[cfg(feature = "kv_unstable")] 18942d8ae3abSopenharmony_ci fn test_record_key_values_builder() { 18952d8ae3abSopenharmony_ci use super::Record; 18962d8ae3abSopenharmony_ci use kv::{self, Visitor}; 18972d8ae3abSopenharmony_ci 18982d8ae3abSopenharmony_ci struct TestVisitor { 18992d8ae3abSopenharmony_ci seen_pairs: usize, 19002d8ae3abSopenharmony_ci } 19012d8ae3abSopenharmony_ci 19022d8ae3abSopenharmony_ci impl<'kvs> Visitor<'kvs> for TestVisitor { 19032d8ae3abSopenharmony_ci fn visit_pair( 19042d8ae3abSopenharmony_ci &mut self, 19052d8ae3abSopenharmony_ci _: kv::Key<'kvs>, 19062d8ae3abSopenharmony_ci _: kv::Value<'kvs>, 19072d8ae3abSopenharmony_ci ) -> Result<(), kv::Error> { 19082d8ae3abSopenharmony_ci self.seen_pairs += 1; 19092d8ae3abSopenharmony_ci Ok(()) 19102d8ae3abSopenharmony_ci } 19112d8ae3abSopenharmony_ci } 19122d8ae3abSopenharmony_ci 19132d8ae3abSopenharmony_ci let kvs: &[(&str, i32)] = &[("a", 1), ("b", 2)]; 19142d8ae3abSopenharmony_ci let record_test = Record::builder().key_values(&kvs).build(); 19152d8ae3abSopenharmony_ci 19162d8ae3abSopenharmony_ci let mut visitor = TestVisitor { seen_pairs: 0 }; 19172d8ae3abSopenharmony_ci 19182d8ae3abSopenharmony_ci record_test.key_values().visit(&mut visitor).unwrap(); 19192d8ae3abSopenharmony_ci 19202d8ae3abSopenharmony_ci assert_eq!(2, visitor.seen_pairs); 19212d8ae3abSopenharmony_ci } 19222d8ae3abSopenharmony_ci 19232d8ae3abSopenharmony_ci #[test] 19242d8ae3abSopenharmony_ci #[cfg(feature = "kv_unstable")] 19252d8ae3abSopenharmony_ci fn test_record_key_values_get_coerce() { 19262d8ae3abSopenharmony_ci use super::Record; 19272d8ae3abSopenharmony_ci 19282d8ae3abSopenharmony_ci let kvs: &[(&str, &str)] = &[("a", "1"), ("b", "2")]; 19292d8ae3abSopenharmony_ci let record = Record::builder().key_values(&kvs).build(); 19302d8ae3abSopenharmony_ci 19312d8ae3abSopenharmony_ci assert_eq!( 19322d8ae3abSopenharmony_ci "2", 19332d8ae3abSopenharmony_ci record 19342d8ae3abSopenharmony_ci .key_values() 19352d8ae3abSopenharmony_ci .get("b".into()) 19362d8ae3abSopenharmony_ci .expect("missing key") 19372d8ae3abSopenharmony_ci .to_borrowed_str() 19382d8ae3abSopenharmony_ci .expect("invalid value") 19392d8ae3abSopenharmony_ci ); 19402d8ae3abSopenharmony_ci } 19412d8ae3abSopenharmony_ci 19422d8ae3abSopenharmony_ci // Test that the `impl Log for Foo` blocks work 19432d8ae3abSopenharmony_ci // This test mostly operates on a type level, so failures will be compile errors 19442d8ae3abSopenharmony_ci #[test] 19452d8ae3abSopenharmony_ci fn test_foreign_impl() { 19462d8ae3abSopenharmony_ci use super::Log; 19472d8ae3abSopenharmony_ci #[cfg(feature = "std")] 19482d8ae3abSopenharmony_ci use std::sync::Arc; 19492d8ae3abSopenharmony_ci 19502d8ae3abSopenharmony_ci fn assert_is_log<T: Log + ?Sized>() {} 19512d8ae3abSopenharmony_ci 19522d8ae3abSopenharmony_ci assert_is_log::<&dyn Log>(); 19532d8ae3abSopenharmony_ci 19542d8ae3abSopenharmony_ci #[cfg(feature = "std")] 19552d8ae3abSopenharmony_ci assert_is_log::<Box<dyn Log>>(); 19562d8ae3abSopenharmony_ci 19572d8ae3abSopenharmony_ci #[cfg(feature = "std")] 19582d8ae3abSopenharmony_ci assert_is_log::<Arc<dyn Log>>(); 19592d8ae3abSopenharmony_ci 19602d8ae3abSopenharmony_ci // Assert these statements for all T: Log + ?Sized 19612d8ae3abSopenharmony_ci #[allow(unused)] 19622d8ae3abSopenharmony_ci fn forall<T: Log + ?Sized>() { 19632d8ae3abSopenharmony_ci #[cfg(feature = "std")] 19642d8ae3abSopenharmony_ci assert_is_log::<Box<T>>(); 19652d8ae3abSopenharmony_ci 19662d8ae3abSopenharmony_ci assert_is_log::<&T>(); 19672d8ae3abSopenharmony_ci 19682d8ae3abSopenharmony_ci #[cfg(feature = "std")] 19692d8ae3abSopenharmony_ci assert_is_log::<Arc<T>>(); 19702d8ae3abSopenharmony_ci } 19712d8ae3abSopenharmony_ci } 19722d8ae3abSopenharmony_ci} 1973