mahogany 0.1.0

[BETA] Logging framework for Rust
Documentation
use chrono::Utc;
use std::{
    fs,
    io::Write,
    sync::mpsc::{channel, Receiver, Sender},
    thread,
};
use crate::{LogLevel, Loggable, LogLocation};

#[derive(Clone)]
pub struct Logger<T: LogLevel> {
    sender: Sender<LogTransmit<T>>,
}
impl<T: LogLevel> Logger<T> {
    pub fn new(output: LogLocation) -> Logger<T> {
        let (sender, receiver) = channel();

        let output_path = output.resolve();

        LoggerTool {
            receiver,
            output_path,
        }
        .start();

        Logger::<T> { sender }
    }

    pub fn log(&self, level: T, message: &dyn Loggable) {
        self.sender
            .send(LogTransmit::Log(LogInstance {
                level,
                message: message.as_log(),
            }))
            .unwrap();
    }
}

struct LoggerTool<T: LogLevel> {
    receiver: Receiver<LogTransmit<T>>,
    output_path: String,
}
impl<T: LogLevel> LoggerTool<T> {
    fn start(self) {
        thread::spawn(move || {
            match fs::OpenOptions::new()
                
                .append(true)
                .create(true)
                .open(&self.output_path)
            {
                Ok(mut file) => {
                    while let Ok(message) = self.receiver.recv() {
                        match message {
                            LogTransmit::Close => {
                                self.write_msg(&mut file, "SYSTEM", "Abort message recieved".to_string());
                                break;
                            },
                            LogTransmit::Log(log) => {
                                self.write_msg(&mut file, log.level.level_string(), log.message);
                            }
                        };
                    }
                },
                Err(e) => {
                    println!("[CRITICAL] Failed to open log file: {}", e);
                }
            }
        });
    }

    fn write_msg(&self, file: &mut fs::File, level: &'static str, message: String) {
        let msg = format!(
            "{} [{}]: {}\n",
            self.current_ts(),
            level,
            message
        );

        if let Err(e) = file.write(msg.as_bytes()) {
            println!("[CRITICAL] Failed to write to log file: {}", e)
        }
    }

    fn current_ts(&self) -> String {
        Utc::now().format("%Y-%m-%d %H:%M:%S").to_string()
    }
}

pub enum LogTransmit<T: LogLevel> {
    Log(LogInstance<T>),
    Close,
}

pub struct LogInstance<T: LogLevel> {
    pub level: T,
    pub message: String,
}