rstaples 0.1.1

Utility functions
Documentation
use std::path::{Path, PathBuf};

use log::LevelFilter;

use crate::error::Result;

pub struct StaplesLogger {
    verbose: bool,
    log_file_path: Option<PathBuf>,
    log_level: LevelFilter,
}

impl Default for StaplesLogger {
    fn default() -> Self {
        Self {
            verbose: false,
            log_file_path: None,
            log_level: LevelFilter::Warn,
        }
    }
}

impl StaplesLogger {
    pub fn new() -> Self {
        StaplesLogger::default()
    }

    pub fn with_stdout(mut self) -> Self {
        self.verbose = true;
        self
    }

    pub fn with_log_file<P>(mut self, path: P) -> Self
    where
        P: AsRef<Path>,
    {
        self.log_file_path = Some(path.as_ref().to_path_buf());
        self
    }

    pub fn with_log_level(mut self, level: LevelFilter) -> Self {
        self.log_level = level;
        self
    }

    pub fn start(&self) -> Result<()> {
        let f = fern::Dispatch::new()
            .format(|out, message, record| {
                let now_ms = chrono::Local::now().timestamp_millis();
                let now_sec = now_ms / 1000;
                let now_ms = now_ms - (now_sec * 1000);

                let target = match record.line() {
                    Some(v) => format!("{}:{v}", record.target()),
                    None => record.target().to_string(),
                };

                out.finish(format_args!(
                    "{}.{:03} :: {:<5} :: {:<45} {}",
                    now_sec,
                    now_ms,
                    record.level(),
                    target,
                    message
                ))
            })
            .level(self.log_level);

        let f = match &self.log_file_path {
            Some(v) => f.chain(fern::log_file(v)?),
            None => f,
        };

        let f = match self.verbose {
            true => f.chain(std::io::stdout()),
            false => f,
        };

        f.apply()?;
        Ok(())
    }
}