use fern for logging to stdout and to file

master
rasul 5 years ago
parent dc2dfc4bbc
commit f6ab14470b

12
Cargo.lock generated

@ -173,6 +173,16 @@ dependencies = [
"synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fern"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
@ -354,6 +364,7 @@ dependencies = [
"chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"fern 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
@ -463,6 +474,7 @@ dependencies = [
"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9"
"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08"
"checksum fern 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e69ab0d5aca163e388c3a49d284fed6c3d0810700e77c5ae2756a50ec1a4daaa"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"

@ -8,6 +8,7 @@ edition = "2018"
chrono = "0.4"
colored = "1.8"
dirs = "2.0"
fern = { version = "0.5", features = ["colored"] }
getopts = "0.2"
log = "0.4"
serde = "1.0"

@ -9,8 +9,7 @@ use log::LevelFilter;
pub struct Config {
pub config_directory: PathBuf,
pub log_level: LevelFilter,
pub stdout: PathBuf,
pub stderr: PathBuf,
pub log_file: PathBuf,
}
impl Config {
@ -26,8 +25,7 @@ impl Config {
"log level (error, warn, info, debug, trace)",
"LEVEL",
);
opts.optopt("o", "out", "stdout path", "STDOUT");
opts.optopt("e", "err", "stderr path", "STDERR");
opts.optopt("f", "logfile", "log file", "FILE");
opts.optflag("h", "help", "print this help menu");
let matches = match opts.parse(&args[1..]) {
@ -53,27 +51,11 @@ impl Config {
PathBuf::from(".")
};
let stdout = if let Some(dir) = matches.opt_str("o") {
PathBuf::from(dir)
} else if let Some(mut dir) = config_dir() {
dir.push("sup");
dir.push("stdout.log");
dir
} else {
let mut p = PathBuf::from(".");
p.push("stdout.log");
p
};
let stderr = if let Some(dir) = matches.opt_str("e") {
PathBuf::from(dir)
} else if let Some(mut dir) = config_dir() {
dir.push("sup");
dir.push("stderr.log");
dir
let log_file = if let Some(f) = matches.opt_str("f") {
PathBuf::from(f)
} else {
let mut p = PathBuf::from(".");
p.push("stderr.log");
let mut p = PathBuf::new();
p.push("sup.log");
p
};
@ -97,8 +79,7 @@ impl Config {
Config {
config_directory,
log_level,
stdout,
stderr,
log_file,
}
}
}

@ -1,84 +1,34 @@
use std::boxed::Box;
use std::error::Error;
use std::fmt;
use std::path::PathBuf;
use chrono::Local;
use colored::Colorize;
use log::*;
use fern::{Dispatch, log_file};
use fern::colors::{Color, ColoredLevelConfig};
use log::LevelFilter;
use crate::result::Result;
static LOGGER: Logger = Logger;
#[derive(Debug)]
pub enum LoggerError {
SetLogger(SetLoggerError),
}
impl From<SetLoggerError> for LoggerError {
fn from(e: SetLoggerError) -> Self {
LoggerError::SetLogger(e)
}
}
impl Error for LoggerError {
fn description(&self) -> &str {
match *self {
LoggerError::SetLogger(_) => "Logger already initialized",
}
}
fn cause(&self) -> Option<&dyn Error> {
match *self {
LoggerError::SetLogger(_) => Some(self),
}
}
}
impl fmt::Display for LoggerError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use std::error::Error as FmtError;
write!(f, "{}", self.description())
}
}
struct Logger;
impl Log for Logger {
fn enabled(&self, metadata: &Metadata) -> bool {
metadata.level() <= Level::Trace
}
fn log(&self, record: &Record) {
if self.enabled(record.metadata()) {
let now = chrono::Local::now();
let ts = now.format("%Y-%m-%dT%H:%M:%S%.3f%z").to_string();
let msg = match record.level() {
Level::Error => format!("{} {} {}", ts.white().bold(), "ERR".red(), record.args()),
Level::Warn => {
format!("{} {} {}", ts.white().bold(), "WRN".purple(), record.args())
}
Level::Info => format!("{} {} {}", ts.white().bold(), "INF".cyan(), record.args()),
Level::Debug => {
format!("{} {} {}", ts.white().bold(), "DBG".yellow(), record.args())
}
Level::Trace => {
format!("{} {} {}", ts.white().bold(), "TRC".green(), record.args())
}
};
println!("{}", msg);
}
}
fn flush(&self) {}
}
pub fn init() -> Result<()> {
match set_logger(&LOGGER).map(|()| set_max_level(LevelFilter::Info)) {
Ok(_) => Ok(()),
Err(e) => Err(Box::new(LoggerError::from(e))),
}
}
pub fn set_level(level: LevelFilter) {
set_max_level(level);
pub fn setup_logger(logfile: PathBuf, level: LevelFilter) -> Result<()> {
Dispatch::new()
.format(|out, message, record| {
let colors = ColoredLevelConfig::new()
.error(Color::Red)
.warn(Color::Magenta)
.info(Color::Cyan)
.debug(Color::Yellow)
.trace(Color::Green);
out.finish(format_args!(
"{} {} {}",
Local::now().format("%Y-%m-%dT%H:%M:%S%.3f%z").to_string().white().bold(),
colors.color(record.level()),
message
))
})
.level(level)
.chain(std::io::stdout())
.chain(log_file(logfile)?)
.apply()?;
Ok(())
}

@ -1,6 +1,7 @@
extern crate chrono;
extern crate colored;
extern crate dirs;
extern crate fern;
extern crate getopts;
#[macro_use]
extern crate log;
@ -26,11 +27,10 @@ use result::Result;
fn main() {
let config = Config::from_args();
if let Err(e) = logger::init() {
if let Err(e) = logger::setup_logger(config.log_file, config.log_level) {
println!("FATAL: Error initializing logger: {:?}", e);
std::process::exit(1);
}
logger::set_level(config.log_level);
let mut apps_file = config.config_directory.clone();
apps_file.push("apps.toml");

Loading…
Cancel
Save