use crate::log_file::LogFile;
use crate::{
Level, Opt, DEFAULT_LOG_LEVEL, DEFAULT_RETENTION_DAYS, DEFAULT_TIMEOUT_SECS, OPT_STATE, SEQ,
};
use chrono::{Date, Duration, Local, TimeZone};
use regex::Regex;
use std::fs;
use std::fs::{File, OpenOptions};
use std::ops::Add;
use std::path::Path;
use std::sync::Mutex;
lazy_static! {
pub static ref LOGGER: Mutex<Logger> = Mutex::new(Logger::default());
}
pub struct Logger {
pub file_name_important: bool,
pub file_prefix: String,
pub file_ext_important: bool,
pub file_extension: String,
pub level_important: bool,
pub level: Level,
pub retention_days_important: bool,
pub retention_days: i64,
pub timeout_secs_important: bool,
pub timeout_secs: u64,
log_file: Option<LogFile>,
}
impl Default for Logger {
fn default() -> Self {
Logger {
file_name_important: false,
file_prefix: "default".to_string(),
file_ext_important: false,
file_extension: ".log.toml".to_string(),
level_important: false,
level: DEFAULT_LOG_LEVEL,
retention_days_important: false,
retention_days: DEFAULT_RETENTION_DAYS,
timeout_secs_important: false,
timeout_secs: DEFAULT_TIMEOUT_SECS,
log_file: None,
}
}
}
impl Logger {
pub fn create_seq() -> u128 {
SEQ.with(move |seq| {
let old = *seq.borrow();
*seq.borrow_mut() += 1;
old
})
}
pub fn get_optimization() -> Opt {
if let Ok(opt_state) = OPT_STATE.lock() {
opt_state.get()
} else {
Opt::BeginnersSupport
}
}
pub fn enabled(&self, level: Level) -> bool {
if level.number() <= self.level.number() {
return true;
}
false
}
fn new_today_file(file_prefix: &str, file_extension: &str) -> (Date<Local>, File) {
let start_date = Local::today();
let file = OpenOptions::new()
.create(true)
.append(true)
.open(Path::new(&format!(
"{}-{}{}",
file_prefix,
start_date.format("%Y-%m-%d"),
file_extension
)))
.unwrap();
(start_date, file)
}
pub fn remove_old_logs(&self) -> usize {
let mut count = 0;
let re = if let Ok(x) = Regex::new(&format!(
"./{}-{}{}",
self.file_prefix, r"(\d{4})-(\d{2})-(\d{2})", self.file_extension
)) {
x
} else {
return 0;
};
let paths = if let Ok(x) = fs::read_dir("./") {
x
} else {
return 0;
};
for path in paths {
let name = if let Ok(x) = path {
x.path().display().to_string()
} else {
continue;
};
if let Some(caps) = re.captures(&name) {
let year: i32 = if let Some(cap) = caps.get(1) {
if let Ok(n) = cap.as_str().parse() {
n
} else {
0
}
} else {
0
};
let month: u32 = if let Some(cap) = caps.get(2) {
if let Ok(n) = cap.as_str().parse() {
n
} else {
0
}
} else {
0
};
let day: u32 = if let Some(cap) = caps.get(3) {
if let Ok(n) = cap.as_str().parse() {
n
} else {
0
}
} else {
0
};
if month != 0 && day != 0 {
let file_date = Local.ymd(year, month, day);
if self.retention_days < 1 {
if file_date.add(Duration::days(self.retention_days)) < Local::today() {
if let Ok(_why) = fs::remove_file(name) {
count += 1;
}
}
} else {
if file_date < Local::today().add(Duration::days(-self.retention_days)) {
if let Ok(_why) = fs::remove_file(name) {
count += 1;
}
}
}
}
}
}
count
}
pub fn current_file(&mut self) -> &File {
let date_changed = if let Some(log_file) = &self.log_file {
log_file.start_date < Local::today()
} else {
false
};
if date_changed {
self.log_file = None;
}
if let None = self.log_file {
let (start_date, file) =
Logger::new_today_file(&self.file_prefix, &self.file_extension);
self.log_file = Some(LogFile::new(start_date, file));
}
&self.log_file.as_ref().unwrap().file
}
}