use anyhow::Result; use serde::{Deserialize, Serialize}; use std::fs::{create_dir_all, OpenOptions}; use std::io::Write; use std::path::PathBuf; /// JSONL event record. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct EventRecord { pub project: String, pub query: String, pub run: String, pub turn: u32, pub event_type: String, pub data: serde_json::Value, } /// Event log writer. pub struct LogWriter { path: PathBuf, } impl LogWriter { /// Open or create log file. pub fn new(project: &str, query: &str, run: &str) -> Result { let dir = PathBuf::from(format!("log/{}/{}", project, query)); create_dir_all(&dir)?; Ok(Self { path: dir.join(format!("{}.jsonl", run)), }) } /// Append event to log. pub fn log(&mut self, record: EventRecord) -> Result<()> { let mut file = OpenOptions::new() .create(true) .append(true) .open(&self.path)?; serde_json::to_writer(&mut file, &record)?; file.write_all(b"\n")?; Ok(()) } /// Read all events from log. pub fn read_all(&self) -> Result> { let contents = std::fs::read_to_string(&self.path)?; contents .lines() .filter(|line| !line.is_empty()) .map(|line| serde_json::from_str(line).map_err(|e| anyhow::anyhow!("Parse error: {}", e))) .collect() } }