refactor output system (#74)

This commit is contained in:
Clément DOUIN
2021-04-09 00:15:16 +02:00
parent ebf1b854be
commit f26051685c
9 changed files with 325 additions and 92 deletions
+8 -5
View File
@@ -6,12 +6,15 @@ pub fn output_args<'a>() -> Vec<Arg<'a, 'a>> {
.long("output")
.short("o")
.help("Defines the output format")
.value_name("STRING")
.value_name("FMT")
.possible_values(&["plain", "json"])
.default_value("plain"),
Arg::with_name("silent")
.long("silent")
.short("s")
.help("Disables any output"),
Arg::with_name("log")
.long("log")
.short("l")
.help("Defines the logs level")
.value_name("LEVEL")
.possible_values(&["error", "warn", "info", "debug", "trace"])
.default_value("info"),
]
}
+28
View File
@@ -0,0 +1,28 @@
use std::fmt;
pub enum OutputFmt {
Json,
Plain,
}
impl From<&str> for OutputFmt {
fn from(s: &str) -> Self {
match s {
"json" => Self::Json,
"plain" | _ => Self::Plain,
}
}
}
impl fmt::Display for OutputFmt {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match *self {
OutputFmt::Json => "JSON",
OutputFmt::Plain => "PLAIN",
},
)
}
}
+86
View File
@@ -0,0 +1,86 @@
use error_chain::error_chain;
use log::{Level, LevelFilter, Metadata, Record};
use std::fmt;
use super::fmt::OutputFmt;
error_chain! {}
// Log level struct
pub struct LogLevel(pub LevelFilter);
impl From<&str> for LogLevel {
fn from(s: &str) -> Self {
match s {
"error" => Self(LevelFilter::Error),
"warn" => Self(LevelFilter::Warn),
"debug" => Self(LevelFilter::Debug),
"trace" => Self(LevelFilter::Trace),
"info" | _ => Self(LevelFilter::Info),
}
}
}
impl fmt::Display for LogLevel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0.to_string())
}
}
// Plain logger
struct PlainLogger;
impl log::Log for PlainLogger {
fn enabled(&self, metadata: &Metadata) -> bool {
metadata.level() <= Level::Trace
}
fn log(&self, record: &Record) {
if self.enabled(record.metadata()) {
if let Level::Error = record.level() {
eprintln!("{}", record.args());
} else {
println!("{}", record.args());
}
}
}
fn flush(&self) {}
}
// JSON logger
struct JsonLogger;
impl log::Log for JsonLogger {
fn enabled(&self, metadata: &Metadata) -> bool {
[Level::Error, Level::Info].contains(&metadata.level())
}
fn log(&self, record: &Record) {
if self.enabled(record.metadata()) {
if let Level::Error = record.level() {
eprintln!("{}", record.args());
} else {
// Should be safe enough to `.unwrap()` since it's
// formatted by Himalaya itself
print!("{}", serde_json::to_string(record.args()).unwrap());
}
}
}
fn flush(&self) {}
}
// Init
pub fn init(fmt: &OutputFmt, level: &LogLevel) -> Result<()> {
log::set_boxed_logger(match fmt {
&OutputFmt::Json => Box::new(JsonLogger),
&OutputFmt::Plain => Box::new(PlainLogger),
})
.map(|()| log::set_max_level(level.0))
.chain_err(|| "Could not init logger")
}