2020-08-26 12:21:12 +02:00
|
|
|
//! Simple logger that logs either to stderr or to a file, using `env_logger`
|
|
|
|
|
//! filter syntax. Amusingly, there's no crates.io crate that can do this and
|
|
|
|
|
//! only this.
|
|
|
|
|
|
2021-01-24 17:41:02 +03:00
|
|
|
use std::{
|
|
|
|
|
fs::File,
|
|
|
|
|
io::{self, BufWriter, Write},
|
|
|
|
|
};
|
2020-08-26 12:21:12 +02:00
|
|
|
|
|
|
|
|
use env_logger::filter::{Builder, Filter};
|
|
|
|
|
use log::{Log, Metadata, Record};
|
|
|
|
|
use parking_lot::Mutex;
|
|
|
|
|
|
|
|
|
|
pub(crate) struct Logger {
|
|
|
|
|
filter: Filter,
|
|
|
|
|
file: Option<Mutex<BufWriter<File>>>,
|
2021-01-24 17:06:55 +03:00
|
|
|
no_buffering: bool,
|
2020-08-26 12:21:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Logger {
|
2021-01-24 17:06:55 +03:00
|
|
|
pub(crate) fn new(log_file: Option<File>, no_buffering: bool, filter: Option<&str>) -> Logger {
|
2020-08-26 12:21:12 +02:00
|
|
|
let filter = {
|
|
|
|
|
let mut builder = Builder::new();
|
|
|
|
|
if let Some(filter) = filter {
|
|
|
|
|
builder.parse(filter);
|
|
|
|
|
}
|
|
|
|
|
builder.build()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let file = log_file.map(|it| Mutex::new(BufWriter::new(it)));
|
|
|
|
|
|
2021-01-24 17:06:55 +03:00
|
|
|
Logger { filter, file, no_buffering }
|
2020-08-26 12:21:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn install(self) {
|
|
|
|
|
let max_level = self.filter.filter();
|
|
|
|
|
let _ = log::set_boxed_logger(Box::new(self)).map(|()| log::set_max_level(max_level));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Log for Logger {
|
|
|
|
|
fn enabled(&self, metadata: &Metadata) -> bool {
|
|
|
|
|
self.filter.enabled(metadata)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn log(&self, record: &Record) {
|
|
|
|
|
if !self.filter.matches(record) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-01-27 00:59:31 +03:00
|
|
|
|
2021-07-05 19:46:09 +04:30
|
|
|
match &self.file {
|
2020-08-26 12:21:12 +02:00
|
|
|
Some(w) => {
|
2021-07-05 20:52:34 +04:30
|
|
|
let mut writer = w.lock();
|
2020-08-26 12:21:12 +02:00
|
|
|
let _ = writeln!(
|
2021-07-05 20:52:34 +04:30
|
|
|
writer,
|
2020-08-26 12:21:12 +02:00
|
|
|
"[{} {}] {}",
|
|
|
|
|
record.level(),
|
|
|
|
|
record.module_path().unwrap_or_default(),
|
|
|
|
|
record.args(),
|
|
|
|
|
);
|
2021-07-05 19:46:09 +04:30
|
|
|
|
|
|
|
|
if self.no_buffering {
|
2021-07-05 20:52:34 +04:30
|
|
|
let _ = writer.flush();
|
2021-07-05 19:46:09 +04:30
|
|
|
}
|
2020-08-26 12:21:12 +02:00
|
|
|
}
|
2021-01-27 00:59:31 +03:00
|
|
|
None => {
|
2021-07-05 19:46:09 +04:30
|
|
|
let message = format!(
|
|
|
|
|
"[{} {}] {}\n",
|
2021-01-27 00:59:31 +03:00
|
|
|
record.level(),
|
|
|
|
|
record.module_path().unwrap_or_default(),
|
|
|
|
|
record.args(),
|
|
|
|
|
);
|
2021-07-05 19:46:09 +04:30
|
|
|
eprint!("{}", message);
|
2021-01-27 00:59:31 +03:00
|
|
|
}
|
|
|
|
|
};
|
2020-08-26 12:21:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn flush(&self) {
|
2021-01-24 17:41:02 +03:00
|
|
|
match &self.file {
|
|
|
|
|
Some(w) => {
|
|
|
|
|
let _ = w.lock().flush();
|
|
|
|
|
}
|
|
|
|
|
None => {
|
|
|
|
|
let _ = io::stderr().flush();
|
|
|
|
|
}
|
2020-08-26 12:21:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|