use std::fs::{File, OpenOptions};
use std::io::{self, Write};
use std::path::Path;
use std::sync::Mutex;
use chrono::Local;
use lazy_static::lazy_static;
use crate::{FancyLogger, LogLevel};
lazy_static! {
static ref FILE_LOGGER: Mutex<Option<FileLogger>> = Mutex::new(None);
}
pub struct FileLogger {
file: File,
level: LogLevel,
}
impl FileLogger {
pub fn init<P: AsRef<Path>>(path: P, level: LogLevel) -> io::Result<()> {
let file = OpenOptions::new()
.create(true)
.append(true)
.open(path)?;
let mut file_logger = FILE_LOGGER.lock().unwrap();
*file_logger = Some(FileLogger { file, level });
Ok(())
}
pub fn log(level: LogLevel, message: &str, file: &str, line: u32) -> io::Result<()> {
let mut file_logger = FILE_LOGGER.lock().unwrap();
if let Some(logger) = file_logger.as_mut() {
if level >= logger.level {
let now = Local::now();
let timestamp = now.format("%Y-%m-%d %H:%M:%S%.3f").to_string();
writeln!(
logger.file,
"{} [{}] [{}:{}] {}",
timestamp,
level,
file,
line,
message
)?;
}
}
Ok(())
}
}
pub struct LogFormatter {
format: String,
}
impl LogFormatter {
pub fn new(format: &str) -> Self {
Self {
format: format.to_string(),
}
}
pub fn format(&self, level: LogLevel, message: &str, file: &str, line: u32) -> String {
let now = Local::now();
let timestamp = now.format("%Y-%m-%d %H:%M:%S%.3f").to_string();
let mut result = self.format.clone();
result = result.replace("{timestamp}", ×tamp);
result = result.replace("{level}", &level.to_string());
result = result.replace("{message}", message);
result = result.replace("{file}", file);
result = result.replace("{line}", &line.to_string());
result
}
}
impl FancyLogger {
pub fn init_file_logging<P: AsRef<Path>>(path: P, level: LogLevel) -> io::Result<()> {
FileLogger::init(path, level)
}
pub fn log_to_file(level: LogLevel, message: &str, file: &str, line: u32) -> io::Result<()> {
FileLogger::log(level, message, file, line)
}
pub fn log_everywhere(level: LogLevel, message: &str, file: &str, line: u32) -> io::Result<()> {
Self::log(level, message, file, line);
FileLogger::log(level, message, file, line)
}
}