use std::time::Duration; /// Events the observer can record #[derive(Debug, Clone)] pub enum ObserverEvent { AgentStart { provider: String, model: String, }, AgentEnd { duration: Duration, tokens_used: Option, }, ToolCall { tool: String, duration: Duration, success: bool, }, ChannelMessage { channel: String, direction: String, }, HeartbeatTick, Error { component: String, message: String, }, } /// Numeric metrics #[derive(Debug, Clone)] pub enum ObserverMetric { RequestLatency(Duration), TokensUsed(u64), ActiveSessions(u64), QueueDepth(u64), } /// Core observability trait — implement for any backend pub trait Observer: Send + Sync + 'static { /// Record a discrete event fn record_event(&self, event: &ObserverEvent); /// Record a numeric metric fn record_metric(&self, metric: &ObserverMetric); /// Flush any buffered data (no-op for most backends) fn flush(&self) {} /// Human-readable name of this observer fn name(&self) -> &str; /// Downcast to `Any` for backend-specific operations fn as_any(&self) -> &dyn std::any::Any where Self: Sized, { self } }