log/
lib.rs

1// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! A lightweight logging facade.
12//!
13//! The `log` crate provides a single logging API that abstracts over the
14//! actual logging implementation. Libraries can use the logging API provided
15//! by this crate, and the consumer of those libraries can choose the logging
16//! implementation that is most suitable for its use case.
17//!
18//! If no logging implementation is selected, the facade falls back to a "noop"
19//! implementation that ignores all log messages. The overhead in this case
20//! is very small - just an integer load, comparison and jump.
21//!
22//! A log request consists of a _target_, a _level_, and a _body_. A target is a
23//! string which defaults to the module path of the location of the log request,
24//! though that default may be overridden. Logger implementations typically use
25//! the target to filter requests based on some user configuration.
26//!
27//! # Use
28//!
29//! The basic use of the log crate is through the five logging macros: [`error!`],
30//! [`warn!`], [`info!`], [`debug!`] and [`trace!`]
31//! where `error!` represents the highest-priority log messages
32//! and `trace!` the lowest. The log messages are filtered by configuring
33//! the log level to exclude messages with a lower priority.
34//! Each of these macros accept format strings similarly to [`println!`].
35//!
36//!
37//! [`error!`]: ./macro.error.html
38//! [`warn!`]: ./macro.warn.html
39//! [`info!`]: ./macro.info.html
40//! [`debug!`]: ./macro.debug.html
41//! [`trace!`]: ./macro.trace.html
42//! [`println!`]: https://doc.rust-lang.org/stable/std/macro.println.html
43//!
44//! ## In libraries
45//!
46//! Libraries should link only to the `log` crate, and use the provided
47//! macros to log whatever information will be useful to downstream consumers.
48//!
49//! ### Examples
50//!
51//! ```edition2018
52//! # #[derive(Debug)] pub struct Yak(String);
53//! # impl Yak { fn shave(&mut self, _: u32) {} }
54//! # fn find_a_razor() -> Result<u32, u32> { Ok(1) }
55//! use log::{info, warn};
56//!
57//! pub fn shave_the_yak(yak: &mut Yak) {
58//!     info!(target: "yak_events", "Commencing yak shaving for {:?}", yak);
59//!
60//!     loop {
61//!         match find_a_razor() {
62//!             Ok(razor) => {
63//!                 info!("Razor located: {}", razor);
64//!                 yak.shave(razor);
65//!                 break;
66//!             }
67//!             Err(err) => {
68//!                 warn!("Unable to locate a razor: {}, retrying", err);
69//!             }
70//!         }
71//!     }
72//! }
73//! # fn main() {}
74//! ```
75//!
76//! ## In executables
77//!
78//! Executables should choose a logging implementation and initialize it early in the
79//! runtime of the program. Logging implementations will typically include a
80//! function to do this. Any log messages generated before
81//! the implementation is initialized will be ignored.
82//!
83//! The executable itself may use the `log` crate to log as well.
84//!
85//! ### Warning
86//!
87//! The logging system may only be initialized once.
88//!
89//! # Available logging implementations
90//!
91//! In order to produce log output executables have to use
92//! a logger implementation compatible with the facade.
93//! There are many available implementations to choose from,
94//! here are some of the most popular ones:
95//!
96//! * Simple minimal loggers:
97//!     * [env_logger]
98//!     * [simple_logger]
99//!     * [simplelog]
100//!     * [pretty_env_logger]
101//!     * [stderrlog]
102//!     * [flexi_logger]
103//! * Complex configurable frameworks:
104//!     * [log4rs]
105//!     * [fern]
106//! * Adaptors for other facilities:
107//!     * [syslog]
108//!     * [slog-stdlog]
109//!
110//! # Implementing a Logger
111//!
112//! Loggers implement the [`Log`] trait. Here's a very basic example that simply
113//! logs all messages at the [`Error`][level_link], [`Warn`][level_link] or
114//! [`Info`][level_link] levels to stdout:
115//!
116//! ```edition2018
117//! use log::{Record, Level, Metadata};
118//!
119//! struct SimpleLogger;
120//!
121//! impl log::Log for SimpleLogger {
122//!     fn enabled(&self, metadata: &Metadata) -> bool {
123//!         metadata.level() <= Level::Info
124//!     }
125//!
126//!     fn log(&self, record: &Record) {
127//!         if self.enabled(record.metadata()) {
128//!             println!("{} - {}", record.level(), record.args());
129//!         }
130//!     }
131//!
132//!     fn flush(&self) {}
133//! }
134//!
135//! # fn main() {}
136//! ```
137//!
138//! Loggers are installed by calling the [`set_logger`] function. The maximum
139//! log level also needs to be adjusted via the [`set_max_level`] function. The
140//! logging facade uses this as an optimization to improve performance of log
141//! messages at levels that are disabled. It's important to set it, as it
142//! defaults to [`Off`][filter_link], so no log messages will ever be captured!
143//! In the case of our example logger, we'll want to set the maximum log level
144//! to [`Info`][filter_link], since we ignore any [`Debug`][level_link] or
145//! [`Trace`][level_link] level log messages. A logging implementation should
146//! provide a function that wraps a call to [`set_logger`] and
147//! [`set_max_level`], handling initialization of the logger:
148//!
149//! ```edition2018
150//! # use log::{Level, Metadata};
151//! # struct SimpleLogger;
152//! # impl log::Log for SimpleLogger {
153//! #   fn enabled(&self, _: &Metadata) -> bool { false }
154//! #   fn log(&self, _: &log::Record) {}
155//! #   fn flush(&self) {}
156//! # }
157//! # fn main() {}
158//! use log::{SetLoggerError, LevelFilter};
159//!
160//! static LOGGER: SimpleLogger = SimpleLogger;
161//!
162//! pub fn init() -> Result<(), SetLoggerError> {
163//!     log::set_logger(&LOGGER)
164//!         .map(|()| log::set_max_level(LevelFilter::Info))
165//! }
166//! ```
167//!
168//! Implementations that adjust their configurations at runtime should take care
169//! to adjust the maximum log level as well.
170//!
171//! # Use with `std`
172//!
173//! `set_logger` requires you to provide a `&'static Log`, which can be hard to
174//! obtain if your logger depends on some runtime configuration. The
175//! `set_boxed_logger` function is available with the `std` Cargo feature. It is
176//! identical to `set_logger` except that it takes a `Box<Log>` rather than a
177//! `&'static Log`:
178//!
179//! ```edition2018
180//! # use log::{Level, LevelFilter, Log, SetLoggerError, Metadata};
181//! # struct SimpleLogger;
182//! # impl log::Log for SimpleLogger {
183//! #   fn enabled(&self, _: &Metadata) -> bool { false }
184//! #   fn log(&self, _: &log::Record) {}
185//! #   fn flush(&self) {}
186//! # }
187//! # fn main() {}
188//! # #[cfg(feature = "std")]
189//! pub fn init() -> Result<(), SetLoggerError> {
190//!     log::set_boxed_logger(Box::new(SimpleLogger))
191//!         .map(|()| log::set_max_level(LevelFilter::Info))
192//! }
193//! ```
194//!
195//! # Compile time filters
196//!
197//! Log levels can be statically disabled at compile time via Cargo features. Log invocations at
198//! disabled levels will be skipped and will not even be present in the resulting binary unless the
199//! log level is specified dynamically. This level is configured separately for release and debug
200//! builds. The features are:
201//!
202//! * `max_level_off`
203//! * `max_level_error`
204//! * `max_level_warn`
205//! * `max_level_info`
206//! * `max_level_debug`
207//! * `max_level_trace`
208//! * `release_max_level_off`
209//! * `release_max_level_error`
210//! * `release_max_level_warn`
211//! * `release_max_level_info`
212//! * `release_max_level_debug`
213//! * `release_max_level_trace`
214//!
215//! These features control the value of the `STATIC_MAX_LEVEL` constant. The logging macros check
216//! this value before logging a message. By default, no levels are disabled.
217//!
218//! Libraries should avoid using the max level features because they're global and can't be changed
219//! once they're set.
220//!
221//! For example, a crate can disable trace level logs in debug builds and trace, debug, and info
222//! level logs in release builds with the following configuration:
223//!
224//! ```toml
225//! [dependencies]
226//! log = { version = "0.4", features = ["max_level_debug", "release_max_level_warn"] }
227//! ```
228//! # Crate Feature Flags
229//!
230//! The following crate feature flags are avaliable in addition to the filters. They are
231//! configured in your `Cargo.toml`.
232//!
233//! * `std` allows use of `std` crate instead of the default `core`. Enables using `std::error` and
234//! `set_boxed_logger` functionality.
235//! * `serde` enables support for serialization and deserialization of `Level` and `LevelFilter`.
236//!
237//! ```toml
238//! [dependencies]
239//! log = { version = "0.4", features = ["std", "serde"] }
240//! ```
241//!
242//! # Version compatibility
243//!
244//! The 0.3 and 0.4 versions of the `log` crate are almost entirely compatible. Log messages
245//! made using `log` 0.3 will forward transparently to a logger implementation using `log` 0.4. Log
246//! messages made using `log` 0.4 will forward to a logger implementation using `log` 0.3, but the
247//! module path and file name information associated with the message will unfortunately be lost.
248//!
249//! [`Log`]: trait.Log.html
250//! [level_link]: enum.Level.html
251//! [filter_link]: enum.LevelFilter.html
252//! [`set_logger`]: fn.set_logger.html
253//! [`set_max_level`]: fn.set_max_level.html
254//! [`try_set_logger_raw`]: fn.try_set_logger_raw.html
255//! [`shutdown_logger_raw`]: fn.shutdown_logger_raw.html
256//! [env_logger]: https://docs.rs/env_logger/*/env_logger/
257//! [simple_logger]: https://github.com/borntyping/rust-simple_logger
258//! [simplelog]: https://github.com/drakulix/simplelog.rs
259//! [pretty_env_logger]: https://docs.rs/pretty_env_logger/*/pretty_env_logger/
260//! [stderrlog]: https://docs.rs/stderrlog/*/stderrlog/
261//! [flexi_logger]: https://docs.rs/flexi_logger/*/flexi_logger/
262//! [syslog]: https://docs.rs/syslog/*/syslog/
263//! [slog-stdlog]: https://docs.rs/slog-stdlog/*/slog_stdlog/
264//! [log4rs]: https://docs.rs/log4rs/*/log4rs/
265//! [fern]: https://docs.rs/fern/*/fern/
266
267#![doc(
268    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
269    html_favicon_url = "https://www.rust-lang.org/favicon.ico",
270    html_root_url = "https://docs.rs/log/0.4.8"
271)]
272#![warn(missing_docs)]
273#![deny(missing_debug_implementations)]
274#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
275// When compiled for the rustc compiler itself we want to make sure that this is
276// an unstable crate
277#![cfg_attr(rustbuild, feature(staged_api, rustc_private))]
278#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))]
279
280#[cfg(all(not(feature = "std"), not(test)))]
281extern crate core as std;
282
283#[macro_use]
284extern crate cfg_if;
285
286use std::cmp;
287#[cfg(feature = "std")]
288use std::error;
289use std::fmt;
290use std::mem;
291use std::str::FromStr;
292use std::sync::atomic::{AtomicUsize, Ordering};
293
294// FIXME: ATOMIC_USIZE_INIT was deprecated in rust 1.34. Silence the
295// deprecation warning until our MSRV >= 1.24, where we can use the
296// replacement const fn `AtomicUsize::new`
297#[allow(deprecated)]
298use std::sync::atomic::ATOMIC_USIZE_INIT;
299
300#[macro_use]
301mod macros;
302mod serde;
303
304#[cfg(feature = "kv_unstable")]
305pub mod kv;
306
307// The LOGGER static holds a pointer to the global logger. It is protected by
308// the STATE static which determines whether LOGGER has been initialized yet.
309static mut LOGGER: &'static Log = &NopLogger;
310
311#[allow(deprecated)]
312static STATE: AtomicUsize = ATOMIC_USIZE_INIT;
313
314// There are three different states that we care about: the logger's
315// uninitialized, the logger's initializing (set_logger's been called but
316// LOGGER hasn't actually been set yet), or the logger's active.
317const UNINITIALIZED: usize = 0;
318const INITIALIZING: usize = 1;
319const INITIALIZED: usize = 2;
320
321#[allow(deprecated)]
322static MAX_LOG_LEVEL_FILTER: AtomicUsize = ATOMIC_USIZE_INIT;
323
324static LOG_LEVEL_NAMES: [&'static str; 6] = ["OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"];
325
326static SET_LOGGER_ERROR: &'static str = "attempted to set a logger after the logging system \
327                                         was already initialized";
328static LEVEL_PARSE_ERROR: &'static str =
329    "attempted to convert a string that doesn't match an existing log level";
330
331/// An enum representing the available verbosity levels of the logger.
332///
333/// Typical usage includes: checking if a certain `Level` is enabled with
334/// [`log_enabled!`](macro.log_enabled.html), specifying the `Level` of
335/// [`log!`](macro.log.html), and comparing a `Level` directly to a
336/// [`LevelFilter`](enum.LevelFilter.html).
337#[repr(usize)]
338#[derive(Copy, Eq, Debug, Hash)]
339pub enum Level {
340    /// The "error" level.
341    ///
342    /// Designates very serious errors.
343    Error = 1, // This way these line up with the discriminants for LevelFilter below
344    /// The "warn" level.
345    ///
346    /// Designates hazardous situations.
347    Warn,
348    /// The "info" level.
349    ///
350    /// Designates useful information.
351    Info,
352    /// The "debug" level.
353    ///
354    /// Designates lower priority information.
355    Debug,
356    /// The "trace" level.
357    ///
358    /// Designates very low priority, often extremely verbose, information.
359    Trace,
360}
361
362impl Clone for Level {
363    #[inline]
364    fn clone(&self) -> Level {
365        *self
366    }
367}
368
369impl PartialEq for Level {
370    #[inline]
371    fn eq(&self, other: &Level) -> bool {
372        *self as usize == *other as usize
373    }
374}
375
376impl PartialEq<LevelFilter> for Level {
377    #[inline]
378    fn eq(&self, other: &LevelFilter) -> bool {
379        *self as usize == *other as usize
380    }
381}
382
383impl PartialOrd for Level {
384    #[inline]
385    fn partial_cmp(&self, other: &Level) -> Option<cmp::Ordering> {
386        Some(self.cmp(other))
387    }
388
389    #[inline]
390    fn lt(&self, other: &Level) -> bool {
391        (*self as usize) < *other as usize
392    }
393
394    #[inline]
395    fn le(&self, other: &Level) -> bool {
396        *self as usize <= *other as usize
397    }
398
399    #[inline]
400    fn gt(&self, other: &Level) -> bool {
401        *self as usize > *other as usize
402    }
403
404    #[inline]
405    fn ge(&self, other: &Level) -> bool {
406        *self as usize >= *other as usize
407    }
408}
409
410impl PartialOrd<LevelFilter> for Level {
411    #[inline]
412    fn partial_cmp(&self, other: &LevelFilter) -> Option<cmp::Ordering> {
413        Some((*self as usize).cmp(&(*other as usize)))
414    }
415
416    #[inline]
417    fn lt(&self, other: &LevelFilter) -> bool {
418        (*self as usize) < *other as usize
419    }
420
421    #[inline]
422    fn le(&self, other: &LevelFilter) -> bool {
423        *self as usize <= *other as usize
424    }
425
426    #[inline]
427    fn gt(&self, other: &LevelFilter) -> bool {
428        *self as usize > *other as usize
429    }
430
431    #[inline]
432    fn ge(&self, other: &LevelFilter) -> bool {
433        *self as usize >= *other as usize
434    }
435}
436
437impl Ord for Level {
438    #[inline]
439    fn cmp(&self, other: &Level) -> cmp::Ordering {
440        (*self as usize).cmp(&(*other as usize))
441    }
442}
443
444fn ok_or<T, E>(t: Option<T>, e: E) -> Result<T, E> {
445    match t {
446        Some(t) => Ok(t),
447        None => Err(e),
448    }
449}
450
451// Reimplemented here because std::ascii is not available in libcore
452fn eq_ignore_ascii_case(a: &str, b: &str) -> bool {
453    fn to_ascii_uppercase(c: u8) -> u8 {
454        if c >= b'a' && c <= b'z' {
455            c - b'a' + b'A'
456        } else {
457            c
458        }
459    }
460
461    if a.len() == b.len() {
462        a.bytes()
463            .zip(b.bytes())
464            .all(|(a, b)| to_ascii_uppercase(a) == to_ascii_uppercase(b))
465    } else {
466        false
467    }
468}
469
470impl FromStr for Level {
471    type Err = ParseLevelError;
472    fn from_str(level: &str) -> Result<Level, Self::Err> {
473        ok_or(
474            LOG_LEVEL_NAMES
475                .iter()
476                .position(|&name| eq_ignore_ascii_case(name, level))
477                .into_iter()
478                .filter(|&idx| idx != 0)
479                .map(|idx| Level::from_usize(idx).unwrap())
480                .next(),
481            ParseLevelError(()),
482        )
483    }
484}
485
486impl fmt::Display for Level {
487    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
488        fmt.pad(LOG_LEVEL_NAMES[*self as usize])
489    }
490}
491
492impl Level {
493    fn from_usize(u: usize) -> Option<Level> {
494        match u {
495            1 => Some(Level::Error),
496            2 => Some(Level::Warn),
497            3 => Some(Level::Info),
498            4 => Some(Level::Debug),
499            5 => Some(Level::Trace),
500            _ => None,
501        }
502    }
503
504    /// Returns the most verbose logging level.
505    #[inline]
506    pub fn max() -> Level {
507        Level::Trace
508    }
509
510    /// Converts the `Level` to the equivalent `LevelFilter`.
511    #[inline]
512    pub fn to_level_filter(&self) -> LevelFilter {
513        LevelFilter::from_usize(*self as usize).unwrap()
514    }
515}
516
517/// An enum representing the available verbosity level filters of the logger.
518///
519/// A `LevelFilter` may be compared directly to a [`Level`]. Use this type
520/// to get and set the maximum log level with [`max_level()`] and [`set_max_level`].
521///
522/// [`Level`]: enum.Level.html
523/// [`max_level()`]: fn.max_level.html
524/// [`set_max_level`]: fn.set_max_level.html
525#[repr(usize)]
526#[derive(Copy, Eq, Debug, Hash)]
527pub enum LevelFilter {
528    /// A level lower than all log levels.
529    Off,
530    /// Corresponds to the `Error` log level.
531    Error,
532    /// Corresponds to the `Warn` log level.
533    Warn,
534    /// Corresponds to the `Info` log level.
535    Info,
536    /// Corresponds to the `Debug` log level.
537    Debug,
538    /// Corresponds to the `Trace` log level.
539    Trace,
540}
541
542// Deriving generates terrible impls of these traits
543
544impl Clone for LevelFilter {
545    #[inline]
546    fn clone(&self) -> LevelFilter {
547        *self
548    }
549}
550
551impl PartialEq for LevelFilter {
552    #[inline]
553    fn eq(&self, other: &LevelFilter) -> bool {
554        *self as usize == *other as usize
555    }
556}
557
558impl PartialEq<Level> for LevelFilter {
559    #[inline]
560    fn eq(&self, other: &Level) -> bool {
561        other.eq(self)
562    }
563}
564
565impl PartialOrd for LevelFilter {
566    #[inline]
567    fn partial_cmp(&self, other: &LevelFilter) -> Option<cmp::Ordering> {
568        Some(self.cmp(other))
569    }
570
571    #[inline]
572    fn lt(&self, other: &LevelFilter) -> bool {
573        (*self as usize) < *other as usize
574    }
575
576    #[inline]
577    fn le(&self, other: &LevelFilter) -> bool {
578        *self as usize <= *other as usize
579    }
580
581    #[inline]
582    fn gt(&self, other: &LevelFilter) -> bool {
583        *self as usize > *other as usize
584    }
585
586    #[inline]
587    fn ge(&self, other: &LevelFilter) -> bool {
588        *self as usize >= *other as usize
589    }
590}
591
592impl PartialOrd<Level> for LevelFilter {
593    #[inline]
594    fn partial_cmp(&self, other: &Level) -> Option<cmp::Ordering> {
595        Some((*self as usize).cmp(&(*other as usize)))
596    }
597
598    #[inline]
599    fn lt(&self, other: &Level) -> bool {
600        (*self as usize) < *other as usize
601    }
602
603    #[inline]
604    fn le(&self, other: &Level) -> bool {
605        *self as usize <= *other as usize
606    }
607
608    #[inline]
609    fn gt(&self, other: &Level) -> bool {
610        *self as usize > *other as usize
611    }
612
613    #[inline]
614    fn ge(&self, other: &Level) -> bool {
615        *self as usize >= *other as usize
616    }
617}
618
619impl Ord for LevelFilter {
620    #[inline]
621    fn cmp(&self, other: &LevelFilter) -> cmp::Ordering {
622        (*self as usize).cmp(&(*other as usize))
623    }
624}
625
626impl FromStr for LevelFilter {
627    type Err = ParseLevelError;
628    fn from_str(level: &str) -> Result<LevelFilter, Self::Err> {
629        ok_or(
630            LOG_LEVEL_NAMES
631                .iter()
632                .position(|&name| eq_ignore_ascii_case(name, level))
633                .map(|p| LevelFilter::from_usize(p).unwrap()),
634            ParseLevelError(()),
635        )
636    }
637}
638
639impl fmt::Display for LevelFilter {
640    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
641        fmt.pad(LOG_LEVEL_NAMES[*self as usize])
642    }
643}
644
645impl LevelFilter {
646    fn from_usize(u: usize) -> Option<LevelFilter> {
647        match u {
648            0 => Some(LevelFilter::Off),
649            1 => Some(LevelFilter::Error),
650            2 => Some(LevelFilter::Warn),
651            3 => Some(LevelFilter::Info),
652            4 => Some(LevelFilter::Debug),
653            5 => Some(LevelFilter::Trace),
654            _ => None,
655        }
656    }
657    /// Returns the most verbose logging level filter.
658    #[inline]
659    pub fn max() -> LevelFilter {
660        LevelFilter::Trace
661    }
662
663    /// Converts `self` to the equivalent `Level`.
664    ///
665    /// Returns `None` if `self` is `LevelFilter::Off`.
666    #[inline]
667    pub fn to_level(&self) -> Option<Level> {
668        Level::from_usize(*self as usize)
669    }
670}
671
672#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
673enum MaybeStaticStr<'a> {
674    Static(&'static str),
675    Borrowed(&'a str),
676}
677
678impl<'a> MaybeStaticStr<'a> {
679    #[inline]
680    fn get(&self) -> &'a str {
681        match *self {
682            MaybeStaticStr::Static(s) => s,
683            MaybeStaticStr::Borrowed(s) => s,
684        }
685    }
686}
687
688/// The "payload" of a log message.
689///
690/// # Use
691///
692/// `Record` structures are passed as parameters to the [`log`][method.log]
693/// method of the [`Log`] trait. Logger implementors manipulate these
694/// structures in order to display log messages. `Record`s are automatically
695/// created by the [`log!`] macro and so are not seen by log users.
696///
697/// Note that the [`level()`] and [`target()`] accessors are equivalent to
698/// `self.metadata().level()` and `self.metadata().target()` respectively.
699/// These methods are provided as a convenience for users of this structure.
700///
701/// # Example
702///
703/// The following example shows a simple logger that displays the level,
704/// module path, and message of any `Record` that is passed to it.
705///
706/// ```edition2018
707/// struct SimpleLogger;
708///
709/// impl log::Log for SimpleLogger {
710///    fn enabled(&self, metadata: &log::Metadata) -> bool {
711///        true
712///    }
713///
714///    fn log(&self, record: &log::Record) {
715///        if !self.enabled(record.metadata()) {
716///            return;
717///        }
718///
719///        println!("{}:{} -- {}",
720///                 record.level(),
721///                 record.target(),
722///                 record.args());
723///    }
724///    fn flush(&self) {}
725/// }
726/// ```
727///
728/// [method.log]: trait.Log.html#tymethod.log
729/// [`Log`]: trait.Log.html
730/// [`log!`]: macro.log.html
731/// [`level()`]: struct.Record.html#method.level
732/// [`target()`]: struct.Record.html#method.target
733#[derive(Clone, Debug)]
734pub struct Record<'a> {
735    metadata: Metadata<'a>,
736    args: fmt::Arguments<'a>,
737    module_path: Option<MaybeStaticStr<'a>>,
738    file: Option<MaybeStaticStr<'a>>,
739    line: Option<u32>,
740    #[cfg(feature = "kv_unstable")]
741    key_values: KeyValues<'a>,
742}
743
744// This wrapper type is only needed so we can
745// `#[derive(Debug)]` on `Record`. It also
746// provides a useful `Debug` implementation for
747// the underlying `Source`.
748#[cfg(feature = "kv_unstable")]
749#[derive(Clone)]
750struct KeyValues<'a>(&'a kv::Source);
751
752#[cfg(feature = "kv_unstable")]
753impl<'a> fmt::Debug for KeyValues<'a> {
754    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
755        let mut visitor = f.debug_map();
756        self.0.visit(&mut visitor)?;
757        visitor.finish()
758    }
759}
760
761impl<'a> Record<'a> {
762    /// Returns a new builder.
763    #[inline]
764    pub fn builder() -> RecordBuilder<'a> {
765        RecordBuilder::new()
766    }
767
768    /// The message body.
769    #[inline]
770    pub fn args(&self) -> &fmt::Arguments<'a> {
771        &self.args
772    }
773
774    /// Metadata about the log directive.
775    #[inline]
776    pub fn metadata(&self) -> &Metadata<'a> {
777        &self.metadata
778    }
779
780    /// The verbosity level of the message.
781    #[inline]
782    pub fn level(&self) -> Level {
783        self.metadata.level()
784    }
785
786    /// The name of the target of the directive.
787    #[inline]
788    pub fn target(&self) -> &'a str {
789        self.metadata.target()
790    }
791
792    /// The module path of the message.
793    #[inline]
794    pub fn module_path(&self) -> Option<&'a str> {
795        self.module_path.map(|s| s.get())
796    }
797
798    /// The module path of the message, if it is a `'static` string.
799    #[inline]
800    pub fn module_path_static(&self) -> Option<&'static str> {
801        match self.module_path {
802            Some(MaybeStaticStr::Static(s)) => Some(s),
803            _ => None,
804        }
805    }
806
807    /// The source file containing the message.
808    #[inline]
809    pub fn file(&self) -> Option<&'a str> {
810        self.file.map(|s| s.get())
811    }
812
813    /// The module path of the message, if it is a `'static` string.
814    #[inline]
815    pub fn file_static(&self) -> Option<&'static str> {
816        match self.file {
817            Some(MaybeStaticStr::Static(s)) => Some(s),
818            _ => None,
819        }
820    }
821
822    /// The line containing the message.
823    #[inline]
824    pub fn line(&self) -> Option<u32> {
825        self.line
826    }
827
828    /// The structued key-value pairs associated with the message.
829    #[cfg(feature = "kv_unstable")]
830    #[inline]
831    pub fn key_values(&self) -> &kv::Source {
832        self.key_values.0
833    }
834
835    /// Create a new [`Builder`](struct.Builder.html) based on this record.
836    #[cfg(feature = "kv_unstable")]
837    #[inline]
838    pub fn to_builder(&self) -> RecordBuilder {
839        RecordBuilder {
840            record: Record {
841                metadata: Metadata {
842                    level: self.metadata.level,
843                    target: self.metadata.target,
844                },
845                args: self.args,
846                module_path: self.module_path,
847                file: self.file,
848                line: self.line,
849                key_values: self.key_values.clone(),
850            }
851        }
852    }
853}
854
855/// Builder for [`Record`](struct.Record.html).
856///
857/// Typically should only be used by log library creators or for testing and "shim loggers".
858/// The `RecordBuilder` can set the different parameters of `Record` object, and returns
859/// the created object when `build` is called.
860///
861/// # Examples
862///
863///
864/// ```edition2018
865/// use log::{Level, Record};
866///
867/// let record = Record::builder()
868///                 .args(format_args!("Error!"))
869///                 .level(Level::Error)
870///                 .target("myApp")
871///                 .file(Some("server.rs"))
872///                 .line(Some(144))
873///                 .module_path(Some("server"))
874///                 .build();
875/// ```
876///
877/// Alternatively, use [`MetadataBuilder`](struct.MetadataBuilder.html):
878///
879/// ```edition2018
880/// use log::{Record, Level, MetadataBuilder};
881///
882/// let error_metadata = MetadataBuilder::new()
883///                         .target("myApp")
884///                         .level(Level::Error)
885///                         .build();
886///
887/// let record = Record::builder()
888///                 .metadata(error_metadata)
889///                 .args(format_args!("Error!"))
890///                 .line(Some(433))
891///                 .file(Some("app.rs"))
892///                 .module_path(Some("server"))
893///                 .build();
894/// ```
895#[derive(Debug)]
896pub struct RecordBuilder<'a> {
897    record: Record<'a>,
898}
899
900impl<'a> RecordBuilder<'a> {
901    /// Construct new `RecordBuilder`.
902    ///
903    /// The default options are:
904    ///
905    /// - `args`: [`format_args!("")`]
906    /// - `metadata`: [`Metadata::builder().build()`]
907    /// - `module_path`: `None`
908    /// - `file`: `None`
909    /// - `line`: `None`
910    ///
911    /// [`format_args!("")`]: https://doc.rust-lang.org/std/macro.format_args.html
912    /// [`Metadata::builder().build()`]: struct.MetadataBuilder.html#method.build
913    #[inline]
914    pub fn new() -> RecordBuilder<'a> {
915        #[cfg(feature = "kv_unstable")]
916        return RecordBuilder {
917            record: Record {
918                args: format_args!(""),
919                metadata: Metadata::builder().build(),
920                module_path: None,
921                file: None,
922                line: None,
923                key_values: KeyValues(&Option::None::<(kv::Key, kv::Value)>),
924            },
925        };
926
927        #[cfg(not(feature = "kv_unstable"))]
928        return RecordBuilder {
929            record: Record {
930                args: format_args!(""),
931                metadata: Metadata::builder().build(),
932                module_path: None,
933                file: None,
934                line: None,
935            },
936        };
937    }
938
939    /// Set [`args`](struct.Record.html#method.args).
940    #[inline]
941    pub fn args(&mut self, args: fmt::Arguments<'a>) -> &mut RecordBuilder<'a> {
942        self.record.args = args;
943        self
944    }
945
946    /// Set [`metadata`](struct.Record.html#method.metadata). Construct a `Metadata` object with [`MetadataBuilder`](struct.MetadataBuilder.html).
947    #[inline]
948    pub fn metadata(&mut self, metadata: Metadata<'a>) -> &mut RecordBuilder<'a> {
949        self.record.metadata = metadata;
950        self
951    }
952
953    /// Set [`Metadata::level`](struct.Metadata.html#method.level).
954    #[inline]
955    pub fn level(&mut self, level: Level) -> &mut RecordBuilder<'a> {
956        self.record.metadata.level = level;
957        self
958    }
959
960    /// Set [`Metadata::target`](struct.Metadata.html#method.target)
961    #[inline]
962    pub fn target(&mut self, target: &'a str) -> &mut RecordBuilder<'a> {
963        self.record.metadata.target = target;
964        self
965    }
966
967    /// Set [`module_path`](struct.Record.html#method.module_path)
968    #[inline]
969    pub fn module_path(&mut self, path: Option<&'a str>) -> &mut RecordBuilder<'a> {
970        self.record.module_path = path.map(MaybeStaticStr::Borrowed);
971        self
972    }
973
974    /// Set [`module_path`](struct.Record.html#method.module_path) to a `'static` string
975    #[inline]
976    pub fn module_path_static(&mut self, path: Option<&'static str>) -> &mut RecordBuilder<'a> {
977        self.record.module_path = path.map(MaybeStaticStr::Static);
978        self
979    }
980
981    /// Set [`file`](struct.Record.html#method.file)
982    #[inline]
983    pub fn file(&mut self, file: Option<&'a str>) -> &mut RecordBuilder<'a> {
984        self.record.file = file.map(MaybeStaticStr::Borrowed);
985        self
986    }
987
988    /// Set [`file`](struct.Record.html#method.file) to a `'static` string.
989    #[inline]
990    pub fn file_static(&mut self, file: Option<&'static str>) -> &mut RecordBuilder<'a> {
991        self.record.file = file.map(MaybeStaticStr::Static);
992        self
993    }
994
995    /// Set [`line`](struct.Record.html#method.line)
996    #[inline]
997    pub fn line(&mut self, line: Option<u32>) -> &mut RecordBuilder<'a> {
998        self.record.line = line;
999        self
1000    }
1001
1002    /// Set [`key_values`](struct.Record.html#method.key_values)
1003    #[cfg(feature = "kv_unstable")]
1004    #[inline]
1005    pub fn key_values(&mut self, kvs: &'a kv::Source) -> &mut RecordBuilder<'a> {
1006        self.record.key_values = KeyValues(kvs);
1007        self
1008    }
1009
1010    /// Invoke the builder and return a `Record`
1011    #[inline]
1012    pub fn build(&self) -> Record<'a> {
1013        self.record.clone()
1014    }
1015}
1016
1017/// Metadata about a log message.
1018///
1019/// # Use
1020///
1021/// `Metadata` structs are created when users of the library use
1022/// logging macros.
1023///
1024/// They are consumed by implementations of the `Log` trait in the
1025/// `enabled` method.
1026///
1027/// `Record`s use `Metadata` to determine the log message's severity
1028/// and target.
1029///
1030/// Users should use the `log_enabled!` macro in their code to avoid
1031/// constructing expensive log messages.
1032///
1033/// # Examples
1034///
1035/// ```edition2018
1036/// use log::{Record, Level, Metadata};
1037///
1038/// struct MyLogger;
1039///
1040/// impl log::Log for MyLogger {
1041///     fn enabled(&self, metadata: &Metadata) -> bool {
1042///         metadata.level() <= Level::Info
1043///     }
1044///
1045///     fn log(&self, record: &Record) {
1046///         if self.enabled(record.metadata()) {
1047///             println!("{} - {}", record.level(), record.args());
1048///         }
1049///     }
1050///     fn flush(&self) {}
1051/// }
1052///
1053/// # fn main(){}
1054/// ```
1055#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
1056pub struct Metadata<'a> {
1057    level: Level,
1058    target: &'a str,
1059}
1060
1061impl<'a> Metadata<'a> {
1062    /// Returns a new builder.
1063    #[inline]
1064    pub fn builder() -> MetadataBuilder<'a> {
1065        MetadataBuilder::new()
1066    }
1067
1068    /// The verbosity level of the message.
1069    #[inline]
1070    pub fn level(&self) -> Level {
1071        self.level
1072    }
1073
1074    /// The name of the target of the directive.
1075    #[inline]
1076    pub fn target(&self) -> &'a str {
1077        self.target
1078    }
1079}
1080
1081/// Builder for [`Metadata`](struct.Metadata.html).
1082///
1083/// Typically should only be used by log library creators or for testing and "shim loggers".
1084/// The `MetadataBuilder` can set the different parameters of a `Metadata` object, and returns
1085/// the created object when `build` is called.
1086///
1087/// # Example
1088///
1089/// ```edition2018
1090/// let target = "myApp";
1091/// use log::{Level, MetadataBuilder};
1092/// let metadata = MetadataBuilder::new()
1093///                     .level(Level::Debug)
1094///                     .target(target)
1095///                     .build();
1096/// ```
1097#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
1098pub struct MetadataBuilder<'a> {
1099    metadata: Metadata<'a>,
1100}
1101
1102impl<'a> MetadataBuilder<'a> {
1103    /// Construct a new `MetadataBuilder`.
1104    ///
1105    /// The default options are:
1106    ///
1107    /// - `level`: `Level::Info`
1108    /// - `target`: `""`
1109    #[inline]
1110    pub fn new() -> MetadataBuilder<'a> {
1111        MetadataBuilder {
1112            metadata: Metadata {
1113                level: Level::Info,
1114                target: "",
1115            },
1116        }
1117    }
1118
1119    /// Setter for [`level`](struct.Metadata.html#method.level).
1120    #[inline]
1121    pub fn level(&mut self, arg: Level) -> &mut MetadataBuilder<'a> {
1122        self.metadata.level = arg;
1123        self
1124    }
1125
1126    /// Setter for [`target`](struct.Metadata.html#method.target).
1127    #[inline]
1128    pub fn target(&mut self, target: &'a str) -> &mut MetadataBuilder<'a> {
1129        self.metadata.target = target;
1130        self
1131    }
1132
1133    /// Returns a `Metadata` object.
1134    #[inline]
1135    pub fn build(&self) -> Metadata<'a> {
1136        self.metadata.clone()
1137    }
1138}
1139
1140/// A trait encapsulating the operations required of a logger.
1141pub trait Log: Sync + Send {
1142    /// Determines if a log message with the specified metadata would be
1143    /// logged.
1144    ///
1145    /// This is used by the `log_enabled!` macro to allow callers to avoid
1146    /// expensive computation of log message arguments if the message would be
1147    /// discarded anyway.
1148    fn enabled(&self, metadata: &Metadata) -> bool;
1149
1150    /// Logs the `Record`.
1151    ///
1152    /// Note that `enabled` is *not* necessarily called before this method.
1153    /// Implementations of `log` should perform all necessary filtering
1154    /// internally.
1155    fn log(&self, record: &Record);
1156
1157    /// Flushes any buffered records.
1158    fn flush(&self);
1159}
1160
1161// Just used as a dummy initial value for LOGGER
1162struct NopLogger;
1163
1164impl Log for NopLogger {
1165    fn enabled(&self, _: &Metadata) -> bool {
1166        false
1167    }
1168
1169    fn log(&self, _: &Record) {}
1170    fn flush(&self) {}
1171}
1172
1173/// Sets the global maximum log level.
1174///
1175/// Generally, this should only be called by the active logging implementation.
1176#[inline]
1177pub fn set_max_level(level: LevelFilter) {
1178    MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::SeqCst)
1179}
1180
1181/// Returns the current maximum log level.
1182///
1183/// The [`log!`], [`error!`], [`warn!`], [`info!`], [`debug!`], and [`trace!`] macros check
1184/// this value and discard any message logged at a higher level. The maximum
1185/// log level is set by the [`set_max_level`] function.
1186///
1187/// [`log!`]: macro.log.html
1188/// [`error!`]: macro.error.html
1189/// [`warn!`]: macro.warn.html
1190/// [`info!`]: macro.info.html
1191/// [`debug!`]: macro.debug.html
1192/// [`trace!`]: macro.trace.html
1193/// [`set_max_level`]: fn.set_max_level.html
1194#[inline(always)]
1195pub fn max_level() -> LevelFilter {
1196    unsafe { mem::transmute(MAX_LOG_LEVEL_FILTER.load(Ordering::Relaxed)) }
1197}
1198
1199/// Sets the global logger to a `Box<Log>`.
1200///
1201/// This is a simple convenience wrapper over `set_logger`, which takes a
1202/// `Box<Log>` rather than a `&'static Log`. See the documentation for
1203/// [`set_logger`] for more details.
1204///
1205/// Requires the `std` feature.
1206///
1207/// # Errors
1208///
1209/// An error is returned if a logger has already been set.
1210///
1211/// [`set_logger`]: fn.set_logger.html
1212#[cfg(all(feature = "std", atomic_cas))]
1213pub fn set_boxed_logger(logger: Box<Log>) -> Result<(), SetLoggerError> {
1214    set_logger_inner(|| unsafe { &*Box::into_raw(logger) })
1215}
1216
1217/// Sets the global logger to a `&'static Log`.
1218///
1219/// This function may only be called once in the lifetime of a program. Any log
1220/// events that occur before the call to `set_logger` completes will be ignored.
1221///
1222/// This function does not typically need to be called manually. Logger
1223/// implementations should provide an initialization method that installs the
1224/// logger internally.
1225///
1226/// # Availability
1227///
1228/// This method is available even when the `std` feature is disabled. However,
1229/// it is currently unavailable on `thumbv6` targets, which lack support for
1230/// some atomic operations which are used by this function. Even on those
1231/// targets, [`set_logger_racy`] will be available.
1232///
1233/// # Errors
1234///
1235/// An error is returned if a logger has already been set.
1236///
1237/// # Examples
1238///
1239/// ```edition2018
1240/// use log::{error, info, warn, Record, Level, Metadata, LevelFilter};
1241///
1242/// static MY_LOGGER: MyLogger = MyLogger;
1243///
1244/// struct MyLogger;
1245///
1246/// impl log::Log for MyLogger {
1247///     fn enabled(&self, metadata: &Metadata) -> bool {
1248///         metadata.level() <= Level::Info
1249///     }
1250///
1251///     fn log(&self, record: &Record) {
1252///         if self.enabled(record.metadata()) {
1253///             println!("{} - {}", record.level(), record.args());
1254///         }
1255///     }
1256///     fn flush(&self) {}
1257/// }
1258///
1259/// # fn main(){
1260/// log::set_logger(&MY_LOGGER).unwrap();
1261/// log::set_max_level(LevelFilter::Info);
1262///
1263/// info!("hello log");
1264/// warn!("warning");
1265/// error!("oops");
1266/// # }
1267/// ```
1268///
1269/// [`set_logger_racy`]: fn.set_logger_racy.html
1270#[cfg(atomic_cas)]
1271pub fn set_logger(logger: &'static Log) -> Result<(), SetLoggerError> {
1272    set_logger_inner(|| logger)
1273}
1274
1275#[cfg(atomic_cas)]
1276fn set_logger_inner<F>(make_logger: F) -> Result<(), SetLoggerError>
1277where
1278    F: FnOnce() -> &'static Log,
1279{
1280    unsafe {
1281        match STATE.compare_and_swap(UNINITIALIZED, INITIALIZING, Ordering::SeqCst) {
1282            UNINITIALIZED => {
1283                LOGGER = make_logger();
1284                STATE.store(INITIALIZED, Ordering::SeqCst);
1285                Ok(())
1286            }
1287            INITIALIZING => {
1288                while STATE.load(Ordering::SeqCst) == INITIALIZING {}
1289                Err(SetLoggerError(()))
1290            }
1291            _ => Err(SetLoggerError(())),
1292        }
1293    }
1294}
1295
1296/// A thread-unsafe version of [`set_logger`].
1297///
1298/// This function is available on all platforms, even those that do not have
1299/// support for atomics that is needed by [`set_logger`].
1300///
1301/// In almost all cases, [`set_logger`] should be preferred.
1302///
1303/// # Safety
1304///
1305/// This function is only safe to call when no other logger initialization
1306/// function is called while this function still executes.
1307///
1308/// This can be upheld by (for example) making sure that **there are no other
1309/// threads**, and (on embedded) that **interrupts are disabled**.
1310///
1311/// It is safe to use other logging functions while this function runs
1312/// (including all logging macros).
1313///
1314/// [`set_logger`]: fn.set_logger.html
1315pub unsafe fn set_logger_racy(logger: &'static Log) -> Result<(), SetLoggerError> {
1316    match STATE.load(Ordering::SeqCst) {
1317        UNINITIALIZED => {
1318            LOGGER = logger;
1319            STATE.store(INITIALIZED, Ordering::SeqCst);
1320            Ok(())
1321        }
1322        INITIALIZING => {
1323            // This is just plain UB, since we were racing another initialization function
1324            unreachable!("set_logger_racy must not be used with other initialization functions")
1325        }
1326        _ => Err(SetLoggerError(())),
1327    }
1328}
1329
1330/// The type returned by [`set_logger`] if [`set_logger`] has already been called.
1331///
1332/// [`set_logger`]: fn.set_logger.html
1333#[allow(missing_copy_implementations)]
1334#[derive(Debug)]
1335pub struct SetLoggerError(());
1336
1337impl fmt::Display for SetLoggerError {
1338    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1339        fmt.write_str(SET_LOGGER_ERROR)
1340    }
1341}
1342
1343// The Error trait is not available in libcore
1344#[cfg(feature = "std")]
1345impl error::Error for SetLoggerError {
1346    fn description(&self) -> &str {
1347        SET_LOGGER_ERROR
1348    }
1349}
1350
1351/// The type returned by [`from_str`] when the string doesn't match any of the log levels.
1352///
1353/// [`from_str`]: https://doc.rust-lang.org/std/str/trait.FromStr.html#tymethod.from_str
1354#[allow(missing_copy_implementations)]
1355#[derive(Debug, PartialEq)]
1356pub struct ParseLevelError(());
1357
1358impl fmt::Display for ParseLevelError {
1359    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1360        fmt.write_str(LEVEL_PARSE_ERROR)
1361    }
1362}
1363
1364// The Error trait is not available in libcore
1365#[cfg(feature = "std")]
1366impl error::Error for ParseLevelError {
1367    fn description(&self) -> &str {
1368        LEVEL_PARSE_ERROR
1369    }
1370}
1371
1372/// Returns a reference to the logger.
1373///
1374/// If a logger has not been set, a no-op implementation is returned.
1375pub fn logger() -> &'static Log {
1376    unsafe {
1377        if STATE.load(Ordering::SeqCst) != INITIALIZED {
1378            static NOP: NopLogger = NopLogger;
1379            &NOP
1380        } else {
1381            LOGGER
1382        }
1383    }
1384}
1385
1386// WARNING: this is not part of the crate's public API and is subject to change at any time
1387#[doc(hidden)]
1388pub fn __private_api_log(
1389    args: fmt::Arguments,
1390    level: Level,
1391    &(target, module_path, file, line): &(&str, &'static str, &'static str, u32),
1392) {
1393    logger().log(
1394        &Record::builder()
1395            .args(args)
1396            .level(level)
1397            .target(target)
1398            .module_path_static(Some(module_path))
1399            .file_static(Some(file))
1400            .line(Some(line))
1401            .build(),
1402    );
1403}
1404
1405// WARNING: this is not part of the crate's public API and is subject to change at any time
1406#[doc(hidden)]
1407pub fn __private_api_enabled(level: Level, target: &str) -> bool {
1408    logger().enabled(&Metadata::builder().level(level).target(target).build())
1409}
1410
1411/// The statically resolved maximum log level.
1412///
1413/// See the crate level documentation for information on how to configure this.
1414///
1415/// This value is checked by the log macros, but not by the `Log`ger returned by
1416/// the [`logger`] function. Code that manually calls functions on that value
1417/// should compare the level against this value.
1418///
1419/// [`logger`]: fn.logger.html
1420pub const STATIC_MAX_LEVEL: LevelFilter = MAX_LEVEL_INNER;
1421
1422cfg_if! {
1423    if #[cfg(all(not(debug_assertions), feature = "release_max_level_off"))] {
1424        const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Off;
1425    } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_error"))] {
1426        const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Error;
1427    } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_warn"))] {
1428        const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Warn;
1429    } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_info"))] {
1430        const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Info;
1431    } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_debug"))] {
1432        const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Debug;
1433    } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_trace"))] {
1434        const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Trace;
1435    } else if #[cfg(feature = "max_level_off")] {
1436        const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Off;
1437    } else if #[cfg(feature = "max_level_error")] {
1438        const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Error;
1439    } else if #[cfg(feature = "max_level_warn")] {
1440        const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Warn;
1441    } else if #[cfg(feature = "max_level_info")] {
1442        const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Info;
1443    } else if #[cfg(feature = "max_level_debug")] {
1444        const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Debug;
1445    } else {
1446        const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Trace;
1447    }
1448}
1449
1450#[cfg(test)]
1451mod tests {
1452    extern crate std;
1453    use super::{Level, LevelFilter, ParseLevelError};
1454    use tests::std::string::ToString;
1455
1456    #[test]
1457    fn test_levelfilter_from_str() {
1458        let tests = [
1459            ("off", Ok(LevelFilter::Off)),
1460            ("error", Ok(LevelFilter::Error)),
1461            ("warn", Ok(LevelFilter::Warn)),
1462            ("info", Ok(LevelFilter::Info)),
1463            ("debug", Ok(LevelFilter::Debug)),
1464            ("trace", Ok(LevelFilter::Trace)),
1465            ("OFF", Ok(LevelFilter::Off)),
1466            ("ERROR", Ok(LevelFilter::Error)),
1467            ("WARN", Ok(LevelFilter::Warn)),
1468            ("INFO", Ok(LevelFilter::Info)),
1469            ("DEBUG", Ok(LevelFilter::Debug)),
1470            ("TRACE", Ok(LevelFilter::Trace)),
1471            ("asdf", Err(ParseLevelError(()))),
1472        ];
1473        for &(s, ref expected) in &tests {
1474            assert_eq!(expected, &s.parse());
1475        }
1476    }
1477
1478    #[test]
1479    fn test_level_from_str() {
1480        let tests = [
1481            ("OFF", Err(ParseLevelError(()))),
1482            ("error", Ok(Level::Error)),
1483            ("warn", Ok(Level::Warn)),
1484            ("info", Ok(Level::Info)),
1485            ("debug", Ok(Level::Debug)),
1486            ("trace", Ok(Level::Trace)),
1487            ("ERROR", Ok(Level::Error)),
1488            ("WARN", Ok(Level::Warn)),
1489            ("INFO", Ok(Level::Info)),
1490            ("DEBUG", Ok(Level::Debug)),
1491            ("TRACE", Ok(Level::Trace)),
1492            ("asdf", Err(ParseLevelError(()))),
1493        ];
1494        for &(s, ref expected) in &tests {
1495            assert_eq!(expected, &s.parse());
1496        }
1497    }
1498
1499    #[test]
1500    fn test_level_show() {
1501        assert_eq!("INFO", Level::Info.to_string());
1502        assert_eq!("ERROR", Level::Error.to_string());
1503    }
1504
1505    #[test]
1506    fn test_levelfilter_show() {
1507        assert_eq!("OFF", LevelFilter::Off.to_string());
1508        assert_eq!("ERROR", LevelFilter::Error.to_string());
1509    }
1510
1511    #[test]
1512    fn test_cross_cmp() {
1513        assert!(Level::Debug > LevelFilter::Error);
1514        assert!(LevelFilter::Warn < Level::Trace);
1515        assert!(LevelFilter::Off < Level::Error);
1516    }
1517
1518    #[test]
1519    fn test_cross_eq() {
1520        assert!(Level::Error == LevelFilter::Error);
1521        assert!(LevelFilter::Off != Level::Error);
1522        assert!(Level::Trace == LevelFilter::Trace);
1523    }
1524
1525    #[test]
1526    fn test_to_level() {
1527        assert_eq!(Some(Level::Error), LevelFilter::Error.to_level());
1528        assert_eq!(None, LevelFilter::Off.to_level());
1529        assert_eq!(Some(Level::Debug), LevelFilter::Debug.to_level());
1530    }
1531
1532    #[test]
1533    fn test_to_level_filter() {
1534        assert_eq!(LevelFilter::Error, Level::Error.to_level_filter());
1535        assert_eq!(LevelFilter::Trace, Level::Trace.to_level_filter());
1536    }
1537
1538    #[test]
1539    #[cfg(feature = "std")]
1540    fn test_error_trait() {
1541        use super::SetLoggerError;
1542        use std::error::Error;
1543        let e = SetLoggerError(());
1544        assert_eq!(
1545            e.description(),
1546            "attempted to set a logger after the logging system \
1547             was already initialized"
1548        );
1549    }
1550
1551    #[test]
1552    fn test_metadata_builder() {
1553        use super::MetadataBuilder;
1554        let target = "myApp";
1555        let metadata_test = MetadataBuilder::new()
1556            .level(Level::Debug)
1557            .target(target)
1558            .build();
1559        assert_eq!(metadata_test.level(), Level::Debug);
1560        assert_eq!(metadata_test.target(), "myApp");
1561    }
1562
1563    #[test]
1564    fn test_metadata_convenience_builder() {
1565        use super::Metadata;
1566        let target = "myApp";
1567        let metadata_test = Metadata::builder()
1568            .level(Level::Debug)
1569            .target(target)
1570            .build();
1571        assert_eq!(metadata_test.level(), Level::Debug);
1572        assert_eq!(metadata_test.target(), "myApp");
1573    }
1574
1575    #[test]
1576    fn test_record_builder() {
1577        use super::{MetadataBuilder, RecordBuilder};
1578        let target = "myApp";
1579        let metadata = MetadataBuilder::new().target(target).build();
1580        let fmt_args = format_args!("hello");
1581        let record_test = RecordBuilder::new()
1582            .args(fmt_args)
1583            .metadata(metadata)
1584            .module_path(Some("foo"))
1585            .file(Some("bar"))
1586            .line(Some(30))
1587            .build();
1588        assert_eq!(record_test.metadata().target(), "myApp");
1589        assert_eq!(record_test.module_path(), Some("foo"));
1590        assert_eq!(record_test.file(), Some("bar"));
1591        assert_eq!(record_test.line(), Some(30));
1592    }
1593
1594    #[test]
1595    fn test_record_convenience_builder() {
1596        use super::{Metadata, Record};
1597        let target = "myApp";
1598        let metadata = Metadata::builder().target(target).build();
1599        let fmt_args = format_args!("hello");
1600        let record_test = Record::builder()
1601            .args(fmt_args)
1602            .metadata(metadata)
1603            .module_path(Some("foo"))
1604            .file(Some("bar"))
1605            .line(Some(30))
1606            .build();
1607        assert_eq!(record_test.target(), "myApp");
1608        assert_eq!(record_test.module_path(), Some("foo"));
1609        assert_eq!(record_test.file(), Some("bar"));
1610        assert_eq!(record_test.line(), Some(30));
1611    }
1612
1613    #[test]
1614    fn test_record_complete_builder() {
1615        use super::{Level, Record};
1616        let target = "myApp";
1617        let record_test = Record::builder()
1618            .module_path(Some("foo"))
1619            .file(Some("bar"))
1620            .line(Some(30))
1621            .target(target)
1622            .level(Level::Error)
1623            .build();
1624        assert_eq!(record_test.target(), "myApp");
1625        assert_eq!(record_test.level(), Level::Error);
1626        assert_eq!(record_test.module_path(), Some("foo"));
1627        assert_eq!(record_test.file(), Some("bar"));
1628        assert_eq!(record_test.line(), Some(30));
1629    }
1630
1631    #[test]
1632    #[cfg(feature = "kv_unstable")]
1633    fn test_record_key_values_builder() {
1634        use super::Record;
1635        use kv::{self, Visitor};
1636
1637        struct TestVisitor {
1638            seen_pairs: usize,
1639        }
1640
1641        impl<'kvs> Visitor<'kvs> for TestVisitor {
1642            fn visit_pair(
1643                &mut self,
1644                _: kv::Key<'kvs>,
1645                _: kv::Value<'kvs>
1646            ) -> Result<(), kv::Error> {
1647                self.seen_pairs += 1;
1648                Ok(())
1649            }
1650        }
1651
1652        let kvs: &[(&str, i32)] = &[
1653            ("a", 1),
1654            ("b", 2)
1655        ];
1656        let record_test = Record::builder()
1657            .key_values(&kvs)
1658            .build();
1659
1660        let mut visitor = TestVisitor {
1661            seen_pairs: 0,
1662        };
1663
1664        record_test.key_values().visit(&mut visitor).unwrap();
1665
1666        assert_eq!(2, visitor.seen_pairs);
1667    }
1668}