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);
}
}
}