extern crate log;
extern crate std;
extern crate term;
use utils;
use self::SubLoggerError::SetLogger;
use std::error::Error;
#[derive(Debug)]
pub enum SubLoggerError {
SetLogger(log::SetLoggerError),
}
impl std::fmt::Display for SubLoggerError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.description())
}
}
impl From<log::SetLoggerError> for SubLoggerError {
fn from(error: log::SetLoggerError) -> Self {
SetLogger(error)
}
}
impl std::error::Error for SubLoggerError {
fn description(&self) -> &str {
match *self {
SetLogger(ref err) => err.description(),
}
}
}
pub struct SubLogger {
level: log::LogLevelFilter,
stream: std::sync::Mutex<Box<term::StderrTerminal>>,
tty: bool,
}
impl log::Log for SubLogger {
fn enabled(&self, metadata: &log::LogMetadata) -> bool {
metadata.level() <= self.level
}
fn log(&self, record: &log::LogRecord) {
if self.enabled(record.metadata()) {
let _ = self.log_handle(record);
}
}
}
impl SubLogger {
fn log_handle(&self, record: &log::LogRecord) -> Result<(), std::io::Error> {
let (color, prefix) = match record.level() {
log::LogLevel::Error => ( term::color::RED, "error: " ),
log::LogLevel::Warn => ( term::color::YELLOW, "warning: " ),
log::LogLevel::Info => ( term::color::GREEN, "info: " ),
log::LogLevel::Debug => ( term::color::BLUE, "debug: " ),
log::LogLevel::Trace => ( term::color::WHITE, "trace: " )
};
let mut term = self.stream.lock().unwrap();
if self.tty {
try!(term.fg(color));
try!(term.attr(term::Attr::Bold));
}
try!(write!(term, "{}", prefix));
if self.tty {
try!(term.reset());
}
try!(writeln!(term, "{}", record.args()));
try!(term.flush());
Ok(())
}
pub fn init(log_level: log::LogLevelFilter) -> Result<(), SubLoggerError> {
let term_std = term::stderr().unwrap();
let stream = std::sync::Mutex::new(term_std);
let tty = utils::isatty(&utils::Output::Stderr);
let logger = Box::new(SubLogger {
level: log_level,
stream: stream,
tty: tty,
});
try!(log::set_logger(|max_log_level| {
max_log_level.set(log_level);
logger
}));
Ok(())
}
}
pub fn init(level: log::LogLevelFilter) {
if let Err(err) = SubLogger::init(level) {
panic!("*** Failed to initialize logger: {}", err);
}
}