Skip to content

Commit

Permalink
Remove MaxLevelFilter in favor of a simple function
Browse files Browse the repository at this point in the history
  • Loading branch information
sfackler committed Dec 6, 2017
1 parent 3f6538e commit b1b5196
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 90 deletions.
68 changes: 18 additions & 50 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,7 @@
//! static LOGGER: SimpleLogger = SimpleLogger;
//!
//! pub fn init() -> Result<(), SetLoggerError> {
//! log::set_logger(|max_level| {
//! max_level.set(LevelFilter::Info);
//! &LOGGER
//! })
//! log::set_logger(&LOGGER)
//! }
//! ```
//!
Expand All @@ -191,10 +188,7 @@
//! # fn main() {}
//! # #[cfg(feature = "std")]
//! pub fn init() -> Result<(), SetLoggerError> {
//! log::set_boxed_logger(|max_level| {
//! max_level.set(LevelFilter::Info);
//! Box::new(SimpleLogger)
//! })
//! log::set_boxed_logger(Box::new(SimpleLogger))
//! }
//! ```
//!
Expand Down Expand Up @@ -954,33 +948,12 @@ impl Log for NopLogger {
fn flush(&self) {}
}

/// A token providing read and write access to the global maximum log level
/// filter.
/// Sets the global maximum log level.
///
/// The maximum log level is used as an optimization to avoid evaluating log
/// messages that will be ignored by the logger. Any message with a level
/// higher than the maximum log level filter will be ignored. A logger should
/// make sure to keep the maximum log level filter in sync with its current
/// configuration.
#[allow(missing_copy_implementations)]
pub struct MaxLevelFilter(());

impl fmt::Debug for MaxLevelFilter {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "MaxLevelFilter")
}
}

impl MaxLevelFilter {
/// Gets the current maximum log level filter.
pub fn get(&self) -> LevelFilter {
max_level()
}

/// Sets the maximum log level.
pub fn set(&self, level: LevelFilter) {
MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::SeqCst)
}
/// Generally, this should only be called by the active logging implementation.
#[inline]
pub fn set_max_level(level: LevelFilter) {
MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::SeqCst)
}

/// Returns the current maximum log level.
Expand Down Expand Up @@ -1015,19 +988,12 @@ pub fn max_level() -> LevelFilter {
///
/// [`set_logger`]: fn.set_logger.html
#[cfg(feature = "std")]
pub fn set_boxed_logger<M>(make_logger: M) -> Result<(), SetLoggerError>
where
M: FnOnce(MaxLevelFilter) -> Box<Log>,
{
unsafe { set_logger(|max_level| &*Box::into_raw(make_logger(max_level))) }
pub fn set_boxed_logger(logger: Box<Log>) -> Result<(), SetLoggerError> {
set_logger_inner(|| unsafe { &*Box::into_raw(logger) })
}

/// Sets the global logger to a `&'static Log`.
///
/// The `make_logger` closure is passed a `MaxLevelFilter` object, which the
/// logger should use to keep the global maximum log level in sync with the
/// highest log level that the logger will not ignore.
///
/// This function may only be called once in the lifetime of a program. Any log
/// events that occur before the call to `set_logger` completes will be ignored.
///
Expand Down Expand Up @@ -1065,26 +1031,28 @@ where
/// }
///
/// # fn main(){
/// log::set_logger(|max_log_level| {
/// max_log_level.set(LevelFilter::Info);
/// &MY_LOGGER
/// }).unwrap();
/// log::set_logger(&MY_LOGGER).unwrap();
/// log::set_max_level(LevelFilter::Info);
///
/// info!("hello log");
/// warn!("warning");
/// error!("oops");
/// # }
/// ```
pub fn set_logger<M>(make_logger: M) -> Result<(), SetLoggerError>
pub fn set_logger(logger: &'static Log) -> Result<(), SetLoggerError> {
set_logger_inner(|| logger)
}

fn set_logger_inner<F>(make_logger: F) -> Result<(), SetLoggerError>
where
M: FnOnce(MaxLevelFilter) -> &'static Log,
F: FnOnce() -> &'static Log
{
unsafe {
if STATE.compare_and_swap(UNINITIALIZED, INITIALIZING, Ordering::SeqCst) != UNINITIALIZED {
return Err(SetLoggerError(()));
}

LOGGER = make_logger(MaxLevelFilter(()));
LOGGER = make_logger();
STATE.store(INITIALIZED, Ordering::SeqCst);
Ok(())
}
Expand Down
33 changes: 11 additions & 22 deletions tests/filters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,17 @@ extern crate log;

use std::sync::{Arc, Mutex};
use log::{Level, LevelFilter, Log, Record, Metadata};
use log::MaxLevelFilter;

#[cfg(feature = "use_std")]
#[cfg(feature = "std")]
use log::set_boxed_logger;
#[cfg(not(feature = "use_std"))]
fn set_boxed_logger<M>(make_logger: M) -> Result<(), log::SetLoggerError>
where M: FnOnce(MaxLevelFilter) -> Box<Log>
{
log::set_logger(|x| unsafe { &*Box::into_raw(make_logger(x)) })

#[cfg(not(feature = "std"))]
fn set_boxed_logger(logger: Box<Log>) -> Result<(), log::SetLoggerError> {
log::set_logger(unsafe { &*Box::into_raw(logger) })
}

struct State {
last_log: Mutex<Option<Level>>,
filter: MaxLevelFilter,
}

struct Logger(Arc<State>);
Expand All @@ -33,16 +30,9 @@ impl Log for Logger {
}

fn main() {
let mut a = None;
set_boxed_logger(|max| {
let me = Arc::new(State {
last_log: Mutex::new(None),
filter: max,
});
a = Some(me.clone());
Box::new(Logger(me))
}).unwrap();
let a = a.unwrap();
let me = Arc::new(State { last_log: Mutex::new(None) });
let a = me.clone();
set_boxed_logger(Box::new(Logger(me))).unwrap();

test(&a, LevelFilter::Off);
test(&a, LevelFilter::Error);
Expand All @@ -53,7 +43,7 @@ fn main() {
}

fn test(a: &State, filter: LevelFilter) {
a.filter.set(filter);
log::set_max_level(filter);
error!("");
last(&a, t(Level::Error, filter));
warn!("");
Expand All @@ -71,7 +61,6 @@ fn test(a: &State, filter: LevelFilter) {
}

fn last(state: &State, expected: Option<Level>) {
let mut lvl = state.last_log.lock().unwrap();
assert_eq!(*lvl, expected);
*lvl = None;
let lvl = state.last_log.lock().unwrap().take();
assert_eq!(lvl, expected);
}
26 changes: 8 additions & 18 deletions tests/max_level_features/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,18 @@ extern crate log;

use std::sync::{Arc, Mutex};
use log::{Level, LevelFilter, Log, Record, Metadata};
use log::MaxLevelFilter;

#[cfg(feature = "use_std")]
#[cfg(feature = "std")]
use log::set_boxed_logger;
#[cfg(not(feature = "use_std"))]
fn set_boxed_logger<M>(make_logger: M) -> Result<(), log::SetLoggerError>
where M: FnOnce(MaxLevelFilter) -> Box<Log> {
#[cfg(not(feature = "std"))]
fn set_boxed_logger(logger: Box<Log>) -> Result<(), log::SetLoggerError> {
unsafe {
log::set_logger(|x| &*Box::into_raw(make_logger(x)))
log::set_logger(&*Box::into_raw(logger))
}
}

struct State {
last_log: Mutex<Option<Level>>,
filter: MaxLevelFilter,
}

struct Logger(Arc<State>);
Expand All @@ -35,16 +32,9 @@ impl Log for Logger {
}

fn main() {
let mut a = None;
set_boxed_logger(|max| {
let me = Arc::new(State {
last_log: Mutex::new(None),
filter: max,
});
a = Some(me.clone());
Box::new(Logger(me))
}).unwrap();
let a = a.unwrap();
let me = Arc::new(State { last_log: Mutex::new(None) });
let a = me.clone();
set_boxed_logger(Box::new(Logger(me))).unwrap();

test(&a, LevelFilter::Off);
test(&a, LevelFilter::Error);
Expand All @@ -55,7 +45,7 @@ fn main() {
}

fn test(a: &State, filter: LevelFilter) {
a.filter.set(filter);
log::set_max_level(filter);
error!("");
last(&a, t(Level::Error, filter));
warn!("");
Expand Down

0 comments on commit b1b5196

Please sign in to comment.