mylogger 0.2.5

my simple logger for easy integration
Documentation
//!    # Quick Start.
//!    ## MyLogger uses std runtime.
//!    ```
//!    use chrono::prelude::*;
//!    use chrono::Local;
//!    use log::{info, Level, LevelFilter, Log, Metadata, Record};
//!    use mylogger::MyLogger;
//!    let mut mylogger = MyLogger::with_default_handler("asdf");
//!    log::set_boxed_logger(Box::new(mylogger)).map(|()| log::set_max_level(LevelFilter::Info));
//!
//!    info!("this is the info message");
//!    info!("this is the info message 11");
//!    info!("this is the info message 222");
//!    ```
//!    ## custom handler
//!    ```
//!    use mylogger::{MyLogger, HandlerTrait};
//!    use chrono::prelude::*;
//!    use chrono::Local;
//!    use log::{info, Level, LevelFilter, Log, Metadata, Record};
//!    pub struct CustomHandler {
//!        pub level: Level,
//!        pub name: String
//!    }
//!    
//!    impl CustomHandler {
//!        fn new(level: Level, name:String) -> CustomHandler {
//!            CustomHandler { level: level, name:name }
//!        }
//!    }
//!
//!    impl HandlerTrait for CustomHandler {
//!        fn activate(&self, meta: &Metadata) -> bool {
//!            self.level >= meta.level()
//!        }
//!        fn format_record(&self, logger: &MyLogger, record: &Record) -> String {
//!            let now: DateTime<Local> = Local::now();
//!            let mut module_path = "".to_string();
//!            if let Some(path) = record.module_path() {
//!                module_path = path.to_string();
//!            }
//!            format!(
//!                "{}|{}|{}|{}|{} -> {}",
//!                &self.name,
//!                now.format("%Y-%m-%d %H:%M:%S"),
//!                module_path,
//!                record.target(),
//!                record.level(),
//!                record.args()
//!            )
//!        }
//!        fn log(&self, record: &Record, logger: &MyLogger) {
//!            if self.activate(record.metadata()) {
//!                let msg = self.format_record(logger, record);
//!                println!("{}", msg);
//!            }
//!        }
//!    }
//!
//!    #[test]
//!    fn custom_handler() {
//!        let mut mylogger = MyLogger::new("mylogger");
//!        log::set_boxed_logger(Box::new(mylogger)).map(|()| log::set_max_level(LevelFilter::Info));
//!    
//!        info!("this is the info message");
//!        info!("this is the info message 11");
//!        info!("this is the info message 222");
//!    }
//!    #[test]
//!    fn custom_async_handler() {
//!        let mut mylogger = MyLogger::new("mylogger");
//!        let async_handler = AsyncDefaultHandler::new(level::Info, "async".to_string());
//!        mylogger.register_handler(Box::new(async_handler));
//!        log::set_boxed_logger(Box::new(mylogger)).map(|()| log::set_max_level(LevelFilter::Info));
//!    
//!        info!("this is the async info message");
//!        info!("this is the async info message 11");
//!        info!("this is the async info message 222");
//!    }
//!    ```

use chrono::prelude::*;
use chrono::Local;
use log::{info, Level, LevelFilter, Log, Metadata, Record, RecordBuilder};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::{Duration, Instant};
use tokio;
use tokio::runtime::Runtime;

#[test]
fn custom_async_handler() {
    let mut mylogger = MyLogger::with_default_handler("mylogger");
    let async_handler = AsyncDefaultHandler::new(Level::Info, "async".to_string());
    mylogger.register_handler(Box::new(async_handler));
    log::set_boxed_logger(Box::new(mylogger)).map(|()| log::set_max_level(LevelFilter::Info));

    for i in 0..100 {
        info!("this is the async info message {}", i);
    }
    thread::sleep(Duration::from_millis(5000));
}
pub struct MyLogger {
    pub name: &'static str,
    pub handlers: Vec<Box<dyn HandlerTrait + Send + Sync>>,
}

impl MyLogger {
    pub fn new(name: &'static str) -> MyLogger {
        MyLogger {
            name,
            handlers: Vec::new(),
        }
    }

    pub fn with_default_handler(name: &'static str, level: Level) -> MyLogger {
        let default_handler = Box::new(DefaultHandler::new(level));
        MyLogger {
            name,
            handlers: vec![default_handler],
        }
    }

    pub fn register_handler(&mut self, handler: Box<dyn HandlerTrait + Send + Sync>) {
        self.handlers.push(handler)
    }
}

impl Log for MyLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        true
    }

    fn log(&self, record: &Record) {
        for handlers in &self.handlers {
            handlers.log(record, &self);
        }
    }

    fn flush(&self) {}
}

pub struct DefaultHandler {
    pub level: Level,
}

impl DefaultHandler {
    pub fn new(level: Level) -> DefaultHandler {
        DefaultHandler { level: level }
    }
}

pub trait HandlerTrait: Send {
    fn activate(&self, meta: &Metadata) -> bool {
        true
    }
    fn log(&self, record: &Record, logger: &MyLogger) {}
    fn format_record(&self, logger: &MyLogger, record: &Record) -> String {
        let now: DateTime<Local> = Local::now();
        let mut module_path = "".to_string();
        if let Some(path) = record.module_path() {
            module_path = path.to_string();
        }
        let file_name = match record.file() {
            Some(name) => name,
            None => "",
        };
        let line_number = match record.line() {
            Some(number) => number,
            None => 0,
        };
        format!(
            "{}|{}|{}<{}>|{}|{} -> {}",
            now.format("%Y-%m-%d %H:%M:%S"),
            module_path,
            file_name,
            line_number,
            record.target(),
            record.level(),
            record.args()
        )
    }
}

impl HandlerTrait for DefaultHandler {
    fn activate(&self, meta: &Metadata) -> bool {
        self.level >= meta.level()
    }
    fn log(&self, record: &Record, logger: &MyLogger) {
        if self.activate(record.metadata()) {
            let msg = self.format_record(logger, record);
            println!("{}", msg);
        }
    }
}