From f54d29b977b81f279796c735dc95ef3859ac5778 Mon Sep 17 00:00:00 2001 From: jb-alvarado Date: Sun, 27 Mar 2022 22:00:39 +0200 Subject: [PATCH] work on timer --- examples/timer.rs | 59 +++++++++++++++++ src/utils/logging.rs | 148 ++++++++++++++++++++++++++++--------------- src/utils/mod.rs | 8 +-- 3 files changed, 160 insertions(+), 55 deletions(-) create mode 100644 examples/timer.rs diff --git a/examples/timer.rs b/examples/timer.rs new file mode 100644 index 00000000..90965752 --- /dev/null +++ b/examples/timer.rs @@ -0,0 +1,59 @@ +use chrono::prelude::*; +use std::{ + thread::sleep}; + +fn get_timestamp() -> i64 { + let local: DateTime = Local::now(); + + local.timestamp_millis() as i64 +} + +struct Timer { + init: bool, + timestamp: i64, + limit: i64, + messages: Vec, +} + +impl Timer { + fn new() -> Self { + Self { + init: true, + timestamp: get_timestamp(), + limit: 10 * 1000, + messages: vec![], + } + } + + fn reset(&mut self) { + self.messages.clear(); + self.timestamp = get_timestamp(); + } + + fn send(&mut self, msg: String) { + let now = get_timestamp(); + self.messages.push(msg); + + if self.init { + self.reset(); + self.init = false; + } + + if now >= self.timestamp + self.limit { + println!("Send messages: {:?}", self.messages); + + self.reset(); + } + } +} + +fn main() { + let mut timer = Timer::new(); + + for i in 0..40 { + println!("{:?}", i); + timer.send(format!("{:?}", i)); + + sleep(std::time::Duration::from_secs(1)); + } +} diff --git a/src/utils/logging.rs b/src/utils/logging.rs index a8df6ccb..7fc779c9 100644 --- a/src/utils/logging.rs +++ b/src/utils/logging.rs @@ -2,7 +2,10 @@ extern crate log; extern crate simplelog; use regex::Regex; -use std::path::Path; +use std::{ + path::Path, + sync::{Arc, Mutex}, +}; use file_rotate::{compression::Compression, suffix::AppendCount, ContentLimit, FileRotate}; use lettre::{transport::smtp::authentication::Credentials, Message, SmtpTransport, Transport}; @@ -10,68 +13,52 @@ use log::{Level, LevelFilter, Log, Metadata, Record}; use simplelog::*; use tokio::runtime::Handle; -use crate::utils::GlobalConfig; +use crate::utils::{get_timestamp, GlobalConfig}; -pub struct LogMailer { - level: LevelFilter, - config: Config, - handle: Handle, +pub struct Timer { + init: Arc>, + timestamp: Arc>, + limit: i64, + messages: Arc>>, + rt_handle: Handle, } -impl LogMailer { - pub fn new(log_level: LevelFilter, config: Config, handle: Handle) -> Box { - Box::new(LogMailer { - level: log_level, - config, - handle, - }) - } -} - -impl Log for LogMailer { - fn enabled(&self, metadata: &Metadata<'_>) -> bool { - metadata.level() <= self.level - } - - fn log(&self, record: &Record<'_>) { - if self.enabled(record.metadata()) { - match record.level() { - Level::Error => { - self.handle.spawn(send_mail(record.args().to_string())); - }, - Level::Warn => { - self.handle.spawn(send_mail(record.args().to_string())); - }, - _ => (), - } +impl Timer { + fn new(rt_handle: Handle) -> Self { + Self { + init: Arc::new(Mutex::new(true)), + timestamp: Arc::new(Mutex::new(get_timestamp())), + limit: 30 * 1000, + messages: Arc::new(Mutex::new(vec![])), + rt_handle, } } - fn flush(&self) {} -} - -impl SharedLogger for LogMailer { - fn level(&self) -> LevelFilter { - self.level + fn reset(&self) { + self.messages.lock().unwrap().clear(); + *self.timestamp.lock().unwrap() = get_timestamp(); } - fn config(&self) -> Option<&Config> { - Some(&self.config) - } + fn queue(&self, msg: String) { + let now = get_timestamp(); + self.messages.lock().unwrap().push(msg); - fn as_log(self: Box) -> Box { - Box::new(*self) + if *self.init.lock().unwrap() { + self.reset(); + *self.init.lock().unwrap() = false; + } + + if now >= *self.timestamp.lock().unwrap() + self.limit { + self.rt_handle.spawn(send_mail(self.messages.lock().unwrap().clone())); + + self.reset(); + } } } -fn clean_string(text: String) -> String { - let regex: Regex = Regex::new(r"\x1b\[[0-9;]*[mGKF]").unwrap(); - - regex.replace_all(text.as_str(), "").to_string() -} - -async fn send_mail(msg: String) { +async fn send_mail(messages: Vec) { let config = GlobalConfig::global(); + let msg = messages.join("\n"); let email = Message::builder() .from(config.mail.sender_addr.parse().unwrap()) @@ -100,6 +87,64 @@ async fn send_mail(msg: String) { } } +pub struct LogMailer { + level: LevelFilter, + config: Config, + timer: Timer, +} + +impl LogMailer { + pub fn new(log_level: LevelFilter, config: Config, timer: Timer) -> Box { + Box::new(LogMailer { + level: log_level, + config, + timer, + }) + } +} + +impl Log for LogMailer { + fn enabled(&self, metadata: &Metadata<'_>) -> bool { + metadata.level() <= self.level + } + + fn log(&self, record: &Record<'_>) { + if self.enabled(record.metadata()) { + match record.level() { + Level::Error => { + self.timer.queue(record.args().to_string()); + } + Level::Warn => { + self.timer.queue(record.args().to_string()); + } + _ => (), + } + } + } + + fn flush(&self) {} +} + +impl SharedLogger for LogMailer { + fn level(&self) -> LevelFilter { + self.level + } + + fn config(&self) -> Option<&Config> { + Some(&self.config) + } + + fn as_log(self: Box) -> Box { + Box::new(*self) + } +} + +fn clean_string(text: String) -> String { + let regex: Regex = Regex::new(r"\x1b\[[0-9;]*[mGKF]").unwrap(); + + regex.replace_all(text.as_str(), "").to_string() +} + pub fn init_logging(rt_handle: Handle) -> Vec> { let config = GlobalConfig::global(); let app_config = config.logging.clone(); @@ -166,6 +211,7 @@ pub fn init_logging(rt_handle: Handle) -> Vec> { if config.mail.recipient.len() > 3 { let mut filter = LevelFilter::Error; + let timer = Timer::new(rt_handle); let mail_config = log_config .clone() @@ -176,7 +222,7 @@ pub fn init_logging(rt_handle: Handle) -> Vec> { filter = LevelFilter::Warn } - app_logger.push(LogMailer::new(filter, mail_config, rt_handle)); + app_logger.push(LogMailer::new(filter, mail_config, timer)); } app_logger diff --git a/src/utils/mod.rs b/src/utils/mod.rs index ca93036c..f485558e 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -151,11 +151,11 @@ impl MediaProbe { } } -// pub fn get_timestamp() -> i64 { -// let local: DateTime = Local::now(); +pub fn get_timestamp() -> i64 { + let local: DateTime = Local::now(); -// local.timestamp_millis() as i64 -// } + local.timestamp_millis() as i64 +} pub fn get_sec() -> f64 { let local: DateTime = Local::now();