diff --git a/.travis.yml b/.travis.yml index 1b82ecd3a..479981582 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ script: - ([ $TRAVIS_RUST_VERSION != nightly ] || cargo build --verbose --features nightly) - cargo test --verbose - ([ $TRAVIS_RUST_VERSION != nightly ] || cargo test --verbose --no-default-features) + - cargo test --verbose --manifest-path log-test/Cargo.toml - cargo test --verbose --manifest-path env/Cargo.toml - cargo test --verbose --manifest-path env/Cargo.toml --no-default-features - cargo run --verbose --manifest-path tests/max_level_features/Cargo.toml diff --git a/Cargo.toml b/Cargo.toml index 7f4645379..77691be50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.3.7" +version = "0.3.9" authors = ["The Rust Project Developers"] license = "MIT/Apache-2.0" readme = "README.md" @@ -13,25 +13,27 @@ A lightweight logging facade for Rust """ categories = ["development-tools::debugging"] -[[test]] -name = "filters" -harness = false +[lib] +doctest = false [features] -max_level_off = [] -max_level_error = [] -max_level_warn = [] -max_level_info = [] -max_level_debug = [] -max_level_trace = [] +max_level_off = ["log/max_level_off"] +max_level_error = ["log/max_level_error"] +max_level_warn = ["log/max_level_warn"] +max_level_info = ["log/max_level_info"] +max_level_debug = ["log/max_level_debug"] +max_level_trace = ["log/max_level_trace"] -release_max_level_off = [] -release_max_level_error = [] -release_max_level_warn = [] -release_max_level_info = [] -release_max_level_debug = [] -release_max_level_trace = [] +release_max_level_off = ["log/release_max_level_off"] +release_max_level_error = ["log/release_max_level_error"] +release_max_level_warn = ["log/release_max_level_warn"] +release_max_level_info = ["log/release_max_level_info"] +release_max_level_debug = ["log/release_max_level_debug"] +release_max_level_trace = ["log/release_max_level_trace"] nightly = [] -use_std = [] +use_std = ["log/std"] default = ["use_std"] + +[dependencies] +log = "0.4" diff --git a/log-test/Cargo.toml b/log-test/Cargo.toml new file mode 100644 index 000000000..82eaf1add --- /dev/null +++ b/log-test/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "log-test" +version = "0.1.0" +authors = ["Steven Fackler "] + +[dependencies] +log = { path = ".." } + +[[test]] +name = "filters" +harness = false diff --git a/log-test/src/lib.rs b/log-test/src/lib.rs new file mode 100644 index 000000000..cdfbe1aa5 --- /dev/null +++ b/log-test/src/lib.rs @@ -0,0 +1,6 @@ +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + } +} diff --git a/tests/filters.rs b/log-test/tests/filters.rs similarity index 100% rename from tests/filters.rs rename to log-test/tests/filters.rs diff --git a/src/lib.rs b/src/lib.rs index 6c222baef..1abdf3157 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -199,6 +199,7 @@ #[cfg(not(feature = "use_std"))] extern crate core as std; +extern crate log; use std::cmp; #[cfg(feature = "use_std")] @@ -235,12 +236,9 @@ static mut LOGGER: *const Log = &NopLogger; static STATE: AtomicUsize = ATOMIC_USIZE_INIT; static REFCOUNT: AtomicUsize = ATOMIC_USIZE_INIT; -const UNINITIALIZED: usize = 0; const INITIALIZING: usize = 1; const INITIALIZED: usize = 2; -static MAX_LOG_LEVEL_FILTER: AtomicUsize = ATOMIC_USIZE_INIT; - static LOG_LEVEL_NAMES: [&'static str; 6] = ["OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"]; @@ -370,6 +368,26 @@ impl LogLevel { } } + fn from_new(level: log::Level) -> LogLevel { + match level { + log::Level::Error => LogLevel::Error, + log::Level::Warn => LogLevel::Warn, + log::Level::Info => LogLevel::Info, + log::Level::Debug => LogLevel::Debug, + log::Level::Trace => LogLevel::Trace, + } + } + + fn to_new(&self) -> log::Level { + match *self { + LogLevel::Error => log::Level::Error, + LogLevel::Warn => log::Level::Warn, + LogLevel::Info => log::Level::Info, + LogLevel::Debug => log::Level::Debug, + LogLevel::Trace => log::Level::Trace, + } + } + /// Returns the most verbose logging level. #[inline] pub fn max() -> LogLevel { @@ -475,6 +493,29 @@ impl LogLevelFilter { _ => None } } + + fn from_new(filter: log::LevelFilter) -> LogLevelFilter { + match filter { + log::LevelFilter::Off => LogLevelFilter::Off, + log::LevelFilter::Error => LogLevelFilter::Error, + log::LevelFilter::Warn => LogLevelFilter::Warn, + log::LevelFilter::Info => LogLevelFilter::Info, + log::LevelFilter::Debug => LogLevelFilter::Debug, + log::LevelFilter::Trace => LogLevelFilter::Trace, + } + } + + fn to_new(&self) -> log::LevelFilter { + match *self { + LogLevelFilter::Off => log::LevelFilter::Off, + LogLevelFilter::Error => log::LevelFilter::Error, + LogLevelFilter::Warn => log::LevelFilter::Warn, + LogLevelFilter::Info => log::LevelFilter::Info, + LogLevelFilter::Debug => log::LevelFilter::Debug, + LogLevelFilter::Trace => log::LevelFilter::Trace, + } + } + /// Returns the most verbose logging level filter. #[inline] pub fn max() -> LogLevelFilter { @@ -611,7 +652,6 @@ impl LogLocation { /// 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 MaxLogLevelFilter(()); impl fmt::Debug for MaxLogLevelFilter { @@ -628,7 +668,7 @@ impl MaxLogLevelFilter { /// Sets the maximum log level. pub fn set(&self, level: LogLevelFilter) { - MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::SeqCst) + log::set_max_level(level.to_new()) } } @@ -639,7 +679,7 @@ impl MaxLogLevelFilter { /// log level is set by the `MaxLogLevel` token passed to loggers. #[inline(always)] pub fn max_log_level() -> LogLevelFilter { - unsafe { mem::transmute(MAX_LOG_LEVEL_FILTER.load(Ordering::Relaxed)) } + LogLevelFilter::from_new(log::max_level()) } /// Sets the global logger. @@ -687,14 +727,15 @@ pub fn set_logger(make_logger: M) -> Result<(), SetLoggerError> /// addition, `shutdown_logger` *must not* be called after this function. pub unsafe fn set_logger_raw(make_logger: M) -> Result<(), SetLoggerError> where M: FnOnce(MaxLogLevelFilter) -> *const Log { - if STATE.compare_and_swap(UNINITIALIZED, INITIALIZING, - Ordering::SeqCst) != UNINITIALIZED { - return Err(SetLoggerError(())); + static ADAPTOR: LoggerAdaptor = LoggerAdaptor; + match log::set_logger(&ADAPTOR) { + Ok(()) => { + LOGGER = make_logger(MaxLogLevelFilter(())); + STATE.store(INITIALIZED, Ordering::SeqCst); + Ok(()) + } + Err(_) => Err(SetLoggerError(())), } - - LOGGER = make_logger(MaxLogLevelFilter(())); - STATE.store(INITIALIZED, Ordering::SeqCst); - Ok(()) } /// Shuts down the global logger. @@ -727,9 +768,6 @@ pub fn shutdown_logger() -> Result, ShutdownLoggerError> { /// success. At that point it is guaranteed that no other threads are /// concurrently accessing the logger object. pub fn shutdown_logger_raw() -> Result<*const Log, ShutdownLoggerError> { - // Set the global log level to stop other thread from logging - MAX_LOG_LEVEL_FILTER.store(0, Ordering::SeqCst); - // Set to INITIALIZING to prevent re-initialization after if STATE.compare_and_swap(INITIALIZED, INITIALIZING, Ordering::SeqCst) != INITIALIZED { @@ -848,15 +886,66 @@ fn logger() -> Option { } } +struct LoggerAdaptor; + +impl log::Log for LoggerAdaptor { + fn log(&self, record: &log::Record) { + if let Some(logger) = logger() { + let record = LogRecord { + metadata: LogMetadata { + level: LogLevel::from_new(record.level()), + target: record.target(), + }, + // file and module path aren't static in 0.4 so we can't forward them. + location: &LogLocation { + __file: "", + __line: record.line().unwrap_or(0), + __module_path: "", + }, + args: *record.args(), + }; + logger.log(&record); + } + } + + fn enabled(&self, metadata: &log::Metadata) -> bool { + match logger() { + Some(logger) => { + let metadata = LogMetadata { + level: LogLevel::from_new(metadata.level()), + target: metadata.target(), + }; + logger.enabled(&metadata) + } + None => false + } + } + + fn flush(&self) {} +} + // WARNING // This is not considered part of the crate's public API. It is subject to // change at any time. #[doc(hidden)] pub fn __enabled(level: LogLevel, target: &str) -> bool { - if let Some(logger) = logger() { - logger.enabled(&LogMetadata { level: level, target: target }) - } else { - false + match logger() { + Some(logger) => { + let metadata = LogMetadata { + level: level, + target: target, + }; + logger.enabled(&metadata) + } + None => { + log::Log::enabled( + log::logger(), + &log::Metadata::builder() + .level(level.to_new()) + .target(target) + .build() + ) + } } } @@ -866,16 +955,31 @@ pub fn __enabled(level: LogLevel, target: &str) -> bool { #[doc(hidden)] pub fn __log(level: LogLevel, target: &str, loc: &LogLocation, args: fmt::Arguments) { - if let Some(logger) = logger() { - let record = LogRecord { - metadata: LogMetadata { - level: level, - target: target, - }, - location: loc, - args: args - }; - logger.log(&record) + match logger() { + Some(logger) => { + let record = LogRecord { + metadata: LogMetadata { + level: level, + target: target, + }, + location: loc, + args: args, + }; + logger.log(&record); + } + None => { + log::Log::log( + log::logger(), + &log::Record::builder() + .level(level.to_new()) + .target(target) + .file(Some(loc.__file)) + .line(Some(loc.__line)) + .module_path(Some(loc.__module_path)) + .args(args) + .build() + ) + } } } @@ -885,35 +989,7 @@ pub fn __log(level: LogLevel, target: &str, loc: &LogLocation, #[inline(always)] #[doc(hidden)] pub fn __static_max_level() -> LogLevelFilter { - if !cfg!(debug_assertions) { - // This is a release build. Check `release_max_level_*` first. - if cfg!(feature = "release_max_level_off") { - return LogLevelFilter::Off - } else if cfg!(feature = "release_max_level_error") { - return LogLevelFilter::Error - } else if cfg!(feature = "release_max_level_warn") { - return LogLevelFilter::Warn - } else if cfg!(feature = "release_max_level_info") { - return LogLevelFilter::Info - } else if cfg!(feature = "release_max_level_debug") { - return LogLevelFilter::Debug - } else if cfg!(feature = "release_max_level_trace") { - return LogLevelFilter::Trace - } - } - if cfg!(feature = "max_level_off") { - LogLevelFilter::Off - } else if cfg!(feature = "max_level_error") { - LogLevelFilter::Error - } else if cfg!(feature = "max_level_warn") { - LogLevelFilter::Warn - } else if cfg!(feature = "max_level_info") { - LogLevelFilter::Info - } else if cfg!(feature = "max_level_debug") { - LogLevelFilter::Debug - } else { - LogLevelFilter::Trace - } + LogLevelFilter::from_new(log::STATIC_MAX_LEVEL) } #[cfg(test)]