1 //! Simple logger that logs either to stderr or to a file, using `env_logger`
2 //! filter syntax. Amusingly, there's no crates.io crate that can do this and
7 io::{self, BufWriter, Write},
10 use env_logger::filter::{Builder, Filter};
11 use log::{Log, Metadata, Record};
12 use parking_lot::Mutex;
14 pub(crate) struct Logger {
16 file: Option<Mutex<BufWriter<File>>>,
21 pub(crate) fn new(log_file: Option<File>, no_buffering: bool, filter: Option<&str>) -> Logger {
23 let mut builder = Builder::new();
24 if let Some(filter) = filter {
25 builder.parse(filter);
30 let file = log_file.map(|it| Mutex::new(BufWriter::new(it)));
32 Logger { filter, file, no_buffering }
35 pub(crate) fn install(self) {
36 let max_level = self.filter.filter();
37 let _ = log::set_boxed_logger(Box::new(self)).map(|()| log::set_max_level(max_level));
42 fn enabled(&self, metadata: &Metadata) -> bool {
43 self.filter.enabled(metadata)
46 fn log(&self, record: &Record) {
47 if !self.filter.matches(record) {
51 let should_flush = match &self.file {
57 record.module_path().unwrap_or_default(),
66 record.module_path().unwrap_or_default(),
69 true // flush stderr unconditionally
81 let _ = w.lock().flush();
84 let _ = io::stderr().flush();