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
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use crate::LogBuilder;

use chalk_rs::Chalk;
use chrono::Utc;
use log::{Log, Level, Metadata, Record, SetLoggerError};

/// The logger instance
/// To configure the logger, use the `LogBuilder` struct
pub struct Loggify {
    /// all targets added are excluded from the logger
    pub(crate) exclude: Vec<String>,
    /// defines the minimum log level
    pub(crate) level: Level,
    /// sets the time format
    /// see https://docs.rs/chrono/latest/chrono/format/strftime/index.html for supported escape sequences
    pub(crate) time_format: String,
    /// defines if the target should be logged or not
    /// this option should be used as a debug option
    pub(crate) log_target: bool,
    /// determines if the output is colored or not
    /// per default `true`
    pub(crate) color: bool
}

impl Loggify {
    /// Creates a new logger using the default values
    /// 
    /// # Defaults
    /// - `level` -> The default level is `Info`
    /// - `exclude` -> No targets are excluded
    /// 
    /// # Example
    /// ```
    /// #[macro_use]
    /// extern crate log;
    /// extern crate loggify;
    /// 
    /// use loggify::Loggify;
    /// 
    /// fn main() {
    ///     Loggify::init().unwrap();
    /// 
    ///     error!("My error message");
    ///     warn!("My warn message");
    ///     info!("My info message");
    ///     debug!("Will not be shown");
    ///     trace!("Will not be shown");
    /// }
    /// ```
    pub fn init() -> Result<(), SetLoggerError> {
        LogBuilder::default().build()
    }

    /// Same as `init` but with log level
    /// 
    /// # Example
    /// ```
    /// #[macro_use]
    /// extern crate log;
    /// extern crate loggify;
    /// 
    /// use loggify::Loggify;
    /// 
    /// fn main() {
    ///     Loggify::init_with_level(log::Level::Trace).unwrap();
    /// 
    ///     error!("My error message");
    ///     warn!("My warn message");
    ///     info!("My info message");
    ///     debug!("My debug message");
    ///     trace!("My trace message");
    /// }
    /// ```
    pub fn init_with_level(level: Level) -> Result<(), SetLoggerError> {
        LogBuilder::new().set_level(level).build()
    }
}

impl Log for Loggify {
    fn enabled(&self, metadata: &Metadata) -> bool {
        let mut result = true;

        if self.log_target {
            dbg!(metadata.target());
        }

        for value in self.exclude.clone() {
            if metadata.target().contains(&value) {
                result = false;
                break;
            }
        }

        !self.exclude.contains(&metadata.target().to_string()) && result && metadata.level() <= self.level
    }

    fn log(&self, record: &Record) {
        if !self.enabled(record.metadata()) {
           return;
        }

        let level_msg = if self.color {
            match record.level() {
                Level::Error => Chalk::new().red().bold().string(&"Error"),
                Level::Warn  => Chalk::new().yellow().bold().string(&"Warn "),
                Level::Info  => Chalk::new().cyan().bold().string(&"Info "),
                Level::Debug => Chalk::new().magenta().bold().string(&"Debug"),
                Level::Trace => Chalk::new().blue().bold().string(&"Trace"),
            }
        } else {
            match record.level() {
                Level::Error => "Error".into(),
                Level::Warn  => "Warn ".into(),
                Level::Info  => "Info ".into(),
                Level::Debug => "Debug".into(),
                Level::Trace => "Trace".into(),
            }
        };

        let time = if self.color {
            Chalk::new().grey().string(&Utc::now().format(&self.time_format))
        } else {
            Utc::now().format(&self.time_format).to_string()
        };

        let msg = if self.color {
            Chalk::new().white().bold().string(&record.args())
        } else {
            record.args().to_string()
        };

        println!(
            "[{}] > {} > {}",
            time,
            level_msg,
            msg
        );
    }

    fn flush(&self) {
    }
}