1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use log::{LevelFilter, Metadata, Record};

pub trait Filter {
  fn filter(&self) -> LevelFilter;
  fn enabled(&self, metadata: &Metadata) -> bool;
  fn matches(&self, record: &Record) -> bool;
}

pub fn create_default_filter() -> Box<dyn Filter + Send + Sync> {
  #[cfg(feature = "env")]
  return Box::new(env::EnvFilter::default());
  #[cfg(not(feature = "env"))]
  return Box::new(nop::NopFilter::default());
}

#[cfg(feature = "env")]
pub mod env {
  use env_logger::filter::{Builder as EnvLogBuilder, Filter as EnvLogFilter};
  use log::{LevelFilter, Metadata, Record, SetLoggerError};

  use crate::filter::Filter;
  use crate::LogFmtLogger;

  pub struct EnvFilter {
    inner: EnvLogFilter,
  }

  impl EnvFilter {
    pub fn new(env: &str) -> Self {
      Self {
        inner: EnvLogBuilder::from_env(env).build(),
      }
    }
  }

  impl Filter for EnvFilter {
    fn filter(&self) -> LevelFilter {
      self.inner.filter()
    }
    fn enabled(&self, metadata: &Metadata) -> bool {
      self.inner.enabled(metadata)
    }
    fn matches(&self, record: &Record) -> bool {
      self.inner.matches(record)
    }
  }

  impl Default for EnvFilter {
    fn default() -> Self {
      Self {
        inner: EnvLogBuilder::from_env("RUST_LOG").build(),
      }
    }
  }

  pub trait WithEnvFilter {
    fn init(env: &str) -> Result<(), SetLoggerError>;
    fn with_env_filter(self, env: &str) -> Self;
  }

  impl WithEnvFilter for LogFmtLogger {
    fn init(env: &str) -> Result<(), SetLoggerError> {
      LogFmtLogger::new().with_env_filter(env).init()
    }

    fn with_env_filter(self, env: &str) -> Self {
      self.with_filter(EnvFilter::new(env))
    }
  }
}

pub mod nop {
  use log::{LevelFilter, Metadata, Record};

  use crate::filter::Filter;

  #[derive(Default)]
  pub struct NopFilter;

  impl Filter for NopFilter {
    fn filter(&self) -> LevelFilter {
      LevelFilter::Trace
    }
    fn enabled(&self, _metadata: &Metadata) -> bool {
      true
    }
    fn matches(&self, _record: &Record) -> bool {
      true
    }
  }
}