Skip to content

Commit

Permalink
set_logger wants to panic
Browse files Browse the repository at this point in the history
  • Loading branch information
Alisha committed Jun 14, 2017
1 parent ec2e44d commit a6f61e5
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 34 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -72,7 +72,7 @@ extern crate log;
extern crate env_logger;

fn main() {
env_logger::init().unwrap();
env_logger::init();

info!("starting up");

Expand Down Expand Up @@ -185,5 +185,5 @@ builder.target(Target::Stdout);
if env::var("RUST_LOG").is_ok() {
builder.parse(&env::var("RUST_LOG").unwrap());
}
builder.init().unwrap();
builder.init();
```
39 changes: 33 additions & 6 deletions env/src/lib.rs
Expand Up @@ -20,7 +20,7 @@
//! use log::Level;
//!
//! fn main() {
//! env_logger::init().unwrap();
//! env_logger::init();
//!
//! debug!("this is a debug {}", "message");
//! error!("this is printed by default");
Expand Down Expand Up @@ -194,7 +194,7 @@ pub struct Logger {
/// builder.parse(&env::var("RUST_LOG").unwrap());
/// }
///
/// builder.init().unwrap();
/// builder.init();
///
/// error!("error message");
/// info!("info message");
Expand Down Expand Up @@ -273,15 +273,27 @@ impl Builder {
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization
/// attempts will return an error.
pub fn init(&mut self) -> Result<(), SetLoggerError> {
log::set_logger(|max_level| {
/// attempts will return error.
pub fn try_init(&mut self) -> Result<(), SetLoggerError> {
log::try_set_logger(|max_level| {
let logger = self.build();
max_level.set(logger.filter());
Box::new(logger)
})
}

/// Initializes the global logger with an env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization
/// attempts will panic.
pub fn init(&mut self) {
let logger = self.build();
let filter = logger.filter();
let logger = Box::new(logger);
log::set_logger(logger, filter);
}

/// Build an env logger.
pub fn build(&mut self) -> Logger {
if self.directives.is_empty() {
Expand Down Expand Up @@ -375,7 +387,22 @@ struct Directive {
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will return an error.
pub fn init() -> Result<(), SetLoggerError> {
pub fn try_init() -> Result<(), SetLoggerError> {
let mut builder = Builder::new();

if let Ok(s) = env::var("RUST_LOG") {
builder.parse(&s);
}

builder.try_init()
}

/// Initializes the global logger with an env logger.
///
/// This should be called early in the execution of a Rust program, and the
/// global logger may only be initialized once. Future initialization attempts
/// will panic.
pub fn init() {
let mut builder = Builder::new();

if let Ok(s) = env::var("RUST_LOG") {
Expand Down
2 changes: 1 addition & 1 deletion env/tests/regexp_filter.rs
Expand Up @@ -14,7 +14,7 @@ fn main() {
}

fn child_main() {
env_logger::init().unwrap();
env_logger::init();
info!("XYZ Message");
}

Expand Down
44 changes: 34 additions & 10 deletions src/lib.rs
Expand Up @@ -83,7 +83,7 @@
//! fn main() {
//! // Select env_logger, one possible logger implementation
//! // (see https://doc.rust-lang.org/log/env_logger/index.html)
//! env_logger::init().unwrap();
//! env_logger::init();
//!
//! info!("starting up");
//! error!("error: {}", 404);
Expand Down Expand Up @@ -141,11 +141,10 @@
//! # }
//! # fn main() {}
//! # #[cfg(feature = "use_std")]
//! pub fn init() -> Result<(), SetLoggerError> {
//! log::set_logger(|max_level| {
//! max_level.set(LevelFilter::Info);
//! Box::new(SimpleLogger)
//! })
//! pub fn init() {
//! let filter = LevelFilter::Info;
//! let logger = Box::new(SimpleLogger);
//! log::set_logger(logger, filter);
//! }
//! ```
//!
Expand All @@ -171,7 +170,7 @@
//! # fn flush(&self) {}
//! # }
//! # fn main() {}
//! pub fn init() -> Result<(), SetLoggerError> {
//! pub fn try_init() -> Result<(), SetLoggerError> {
//! unsafe {
//! log::set_logger_raw(|max_level| {
//! static LOGGER: SimpleLogger = SimpleLogger;
Expand Down Expand Up @@ -825,21 +824,46 @@ pub fn max_level() -> LevelFilter {
/// 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
/// events that occur before the call to `try_set_logger` completes will be
/// ignored.
///
/// This function does not typically need to be called manually. Logger
/// implementations should provide an initialization method that calls
/// `set_logger` internally.
/// `try_set_logger` internally.
///
/// Requires the `use_std` feature (enabled by default).
#[cfg(feature = "use_std")]
pub fn set_logger<M>(make_logger: M) -> Result<(), SetLoggerError>
pub fn try_set_logger<M>(make_logger: M) -> Result<(), SetLoggerError>
where M: FnOnce(MaxLevelFilter) -> Box<Log>
{
unsafe { set_logger_raw(|max_level| mem::transmute(make_logger(max_level))) }
}

/// Sets the global logger.
///
/// 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.
///
/// This function will panic on future initialization attempts.
///
/// This function does not typically need to be called manually. Logger
/// implementations should provide an initialization method that calls
/// `set_logger` internally.
///
/// Requires the `use_std` feature (enabled by default).
///
/// # Panics
///
/// The function will panic if it is called more than once.
#[cfg(feature = "use_std")]
pub fn set_logger(logger: Box<Log>, filter: LevelFilter) {
match try_set_logger(|max| { max.set(filter); logger }) {
Ok(()) => {}
Err(_) => panic!("global logger is already initialized"),
}
}

/// Sets the global logger from a raw pointer.
///
/// This function is similar to `set_logger` except that it is usable in
Expand Down
21 changes: 10 additions & 11 deletions tests/filters.rs
Expand Up @@ -6,9 +6,9 @@ use log::{Level, LevelFilter, Log, Record, Metadata};
use log::MaxLevelFilter;

#[cfg(feature = "use_std")]
use log::set_logger;
use log::try_set_logger;
#[cfg(not(feature = "use_std"))]
fn set_logger<M>(make_logger: M) -> Result<(), log::SetLoggerError>
fn try_set_logger<M>(make_logger: M) -> Result<(), log::SetLoggerError>
where M: FnOnce(MaxLevelFilter) -> Box<Log>
{
unsafe { log::set_logger_raw(|x| std::mem::transmute(make_logger(x))) }
Expand All @@ -33,15 +33,14 @@ impl Log for Logger {

fn main() {
let mut a = None;
set_logger(|max| {
let me = Arc::new(State {
last_log: Mutex::new(None),
filter: max,
});
a = Some(me.clone());
Box::new(Logger(me))
})
.unwrap();
try_set_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();

test(&a, LevelFilter::Off);
Expand Down
9 changes: 5 additions & 4 deletions tests/max_level_features/main.rs
@@ -1,13 +1,14 @@
#[macro_use] extern crate log;
#[macro_use]
extern crate log;

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

#[cfg(feature = "use_std")]
use log::set_logger;
use log::try_set_logger;
#[cfg(not(feature = "use_std"))]
fn set_logger<M>(make_logger: M) -> Result<(), log::SetLoggerError>
fn try_set_logger<M>(make_logger: M) -> Result<(), log::SetLoggerError>
where M: FnOnce(MaxLevelFilter) -> Box<Log> {
unsafe {
log::set_logger_raw(|x| std::mem::transmute(make_logger(x)))
Expand All @@ -33,7 +34,7 @@ impl Log for Logger {

fn main() {
let mut a = None;
set_logger(|max| {
try_set_logger(|max| {
let me = Arc::new(State {
last_log: Mutex::new(None),
filter: max,
Expand Down

0 comments on commit a6f61e5

Please sign in to comment.