use crate::app::state::AppEvent;
use std::fs::File;
use std::io::{BufRead, BufReader, Seek, SeekFrom};
use std::path::PathBuf;
use std::sync::mpsc::Sender;
use std::thread;
use std::time::Duration;
use tracing::warn;
pub struct LogWatcher {
path: PathBuf,
tx: Sender<AppEvent>,
}
impl LogWatcher {
pub fn new(path: PathBuf, tx: Sender<AppEvent>) -> Self {
Self { path, tx }
}
pub fn start(self) {
thread::spawn(move || {
let mut last_size = if let Ok(metadata) = std::fs::metadata(&self.path) {
metadata.len().saturating_sub(10000)
} else {
0
};
loop {
if let Ok(file) = File::open(&self.path)
&& let Ok(metadata) = file.metadata()
{
let current_size = metadata.len();
if current_size < last_size {
last_size = 0;
}
if current_size > last_size {
let mut reader = BufReader::new(file);
if reader.seek(SeekFrom::Start(last_size)).is_ok() {
let mut line = String::new();
while let Ok(n) = reader.read_line(&mut line) {
if n == 0 {
break;
}
if let Err(e) =
self.tx.send(AppEvent::LogLine(line.trim_end().to_string()))
{
warn!("Log watcher channel closed: {}", e);
return;
}
line.clear();
}
last_size = current_size;
}
}
}
thread::sleep(Duration::from_millis(250)); }
});
}
}