use std::collections::VecDeque; use serde::Serialize; const MAX_EVENTS: usize = 200; #[derive(Debug, Clone, Copy, Serialize, PartialEq, Eq)] #[serde(rename_all = "lowercase")] pub enum ActivityLevel { Info, Warn, Error, } #[derive(Debug, Clone, Copy, Serialize, PartialEq, Eq)] #[serde(rename_all = "lowercase")] pub enum ActivityCategory { Growth, Rebalance, Recovery, Anchor, Connection, Relay, } #[derive(Debug, Clone, Serialize)] pub struct ActivityEvent { pub timestamp_ms: u64, pub level: ActivityLevel, pub category: ActivityCategory, pub message: String, pub peer_id: Option<[u8; 32]>, } pub struct ActivityLog { events: VecDeque, } impl ActivityLog { pub fn new() -> Self { Self { events: VecDeque::with_capacity(MAX_EVENTS), } } pub fn log( &mut self, level: ActivityLevel, cat: ActivityCategory, msg: String, peer: Option<[u8; 32]>, ) { let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap_or_default() .as_millis() as u64; if self.events.len() >= MAX_EVENTS { self.events.pop_front(); } self.events.push_back(ActivityEvent { timestamp_ms: now, level, category: cat, message: msg, peer_id: peer, }); } pub fn recent(&self, limit: usize) -> Vec { let start = self.events.len().saturating_sub(limit); self.events.iter().skip(start).cloned().collect() } }