use std::{
fs::{self, File},
io::{BufWriter, Write},
path::PathBuf,
sync::Arc,
};
use parking_lot::Mutex;
use crate::{config::LogLevel, error::Result};
use super::LogAppender;
#[derive(Debug)]
pub struct FileAppender {
path: PathBuf,
writer: Arc<Mutex<BufWriter<File>>>,
}
impl FileAppender {
pub fn new(path: PathBuf) -> Result<Self> {
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)?;
}
let file = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(&path)?;
Ok(Self {
path,
writer: Arc::new(Mutex::new(BufWriter::new(file))),
})
}
pub fn path(&self) -> &PathBuf {
&self.path
}
}
impl LogAppender for FileAppender {
fn write(&self, _level: LogLevel, message: &str) -> Result<()> {
let mut writer = self.writer.lock();
writer.write_all(message.as_bytes())?;
writer.write_all(b"\n")?;
Ok(())
}
fn flush(&self) -> Result<()> {
let mut writer = self.writer.lock();
writer.flush()?;
Ok(())
}
}
impl Clone for FileAppender {
fn clone(&self) -> Self {
Self {
path: self.path.clone(),
writer: Arc::clone(&self.writer),
}
}
}