use super::{msg::LogMessage, LogLevel};
use std::{fs::{self, File}, io::Write};
pub struct Writer {
dir_path: String,
single_length: usize,
current_index: usize,
log_buffer: Vec<LogMessage>,
file_record: LogLevel,
terminal_print: LogLevel,
time_details: bool,
used_length: usize,
time_prefix: String,
file: Option<File>,
time_zone: i32,
print_out: bool,
}
impl Writer {
pub fn new(dir_path: &str, single_length: usize, file_record: Option<LogLevel>, terminal_print: Option<LogLevel>, time_zone: i32, time_details: bool, print_out: bool) -> Writer {
let time_prefix = format!("{}", chrono::Utc::now().format("%Y-%m-%d"));
let mut buffer = Self {
dir_path: dir_path.to_string(),
single_length,
current_index: 1,
file_record: file_record.unwrap_or(LogLevel::Trace),
terminal_print: terminal_print.unwrap_or(LogLevel::Debug),
log_buffer: Vec::with_capacity(single_length),
time_details,
time_prefix,
used_length: 0,
file: None,
time_zone,
print_out
};
buffer.current_index = buffer.get_index(&buffer.time_prefix);
buffer.file = Some(buffer.get_file());
buffer
}
pub fn default(dir_path: &str) -> Writer { Writer::new(dir_path, 200, None, None, 0, false, true) }
pub fn push(&mut self, log_level: LogLevel, message: &str) {
let log_message = LogMessage::new(log_level, message.to_string(), self.time_zone);
self.log_buffer.push(log_message);
}
pub fn clear_dir(&mut self) {
fs::remove_dir_all(&self.dir_path).expect("Cannot remove the dir.");
fs::create_dir(&self.dir_path).expect("Cannot create the dir.");
self.current_index = 0;
self.used_length = 0;
self.file = Some(self.get_file())
}
pub fn write_all(&mut self) {
for msg in self.log_buffer.clone().iter_mut() {
if self.time_details { msg.set_detailed_time() } else { msg.set_rough_time() }
self.write_single(msg);
if self.used_length >= self.single_length && self.single_length != 0 {
self.current_index += 1;
self.used_length = 0;
self.file = Some(self.get_file());
}
}
self.log_buffer.clear();
}
pub fn record(&mut self, log_level: LogLevel, message: &str) {
self.push(log_level, message);
self.write_all();
}
pub fn info(&mut self, message: &str) {
self.record(LogLevel::Info, message);
}
pub fn debug(&mut self, message: &str) {
self.record(LogLevel::Debug, message);
}
pub fn warn(&mut self, message: &str) {
self.record(LogLevel::Warn, message);
}
pub fn error(&mut self, message: &str) {
self.record(LogLevel::Error, message);
}
pub fn trace(&mut self, message: &str) {
self.record(LogLevel::Trace, message);
}
fn write_single(&mut self, msg: &LogMessage) {
for i in msg.split_enter() {
let time_prefix = format!("{}", chrono::Utc::now().format("%Y-%m-%d"));
if self.time_prefix != time_prefix {
self.time_prefix = time_prefix;
self.current_index = 0;
self.used_length = 0;
self.file = Some(self.get_file());
};
if self.print_out && self.terminal_print.get_level() <= i.get_level() { println!("{}", i.print()) };
if self.file_record.get_level() <= i.get_level() {
self.file.as_mut().unwrap().write_all((i.print() + "\n").as_bytes()).expect("Cannot write into the log file.");
self.used_length += 1;
};
}
}
fn get_index(&self, time_prefix: &str) -> usize {
let mut count = 1;
loop {
let path = self.get_path(time_prefix, count);
if let Ok(_) = File::open(path) { count += 1 }
else {
return count
}
}
}
fn get_path(&self, time_prefix: &str, index: usize) -> String {
format!("{}\\{}-{}.log", self.dir_path, time_prefix, index)
}
fn get_file(&self) -> File {
let path = self.get_path(&self.time_prefix, self.current_index);
File::options().read(true).write(true).create_new(true).open(path).expect("Cannot create the log file.")
}
}