Skip to main content

zeroclaw_runtime/observability/
traits.rs

1pub use zeroclaw_api::observability_traits::*;
2
3#[allow(unused_imports)]
4pub use async_trait::async_trait;
5
6#[cfg(test)]
7mod tests {
8    use super::*;
9    use parking_lot::Mutex;
10    use std::time::Duration;
11
12    #[derive(Default)]
13    struct DummyObserver {
14        events: Mutex<u64>,
15        metrics: Mutex<u64>,
16    }
17
18    impl Observer for DummyObserver {
19        fn record_event(&self, _event: &ObserverEvent) {
20            let mut guard = self.events.lock();
21            *guard += 1;
22        }
23
24        fn record_metric(&self, _metric: &ObserverMetric) {
25            let mut guard = self.metrics.lock();
26            *guard += 1;
27        }
28
29        fn name(&self) -> &str {
30            "dummy-observer"
31        }
32
33        fn as_any(&self) -> &dyn std::any::Any {
34            self
35        }
36    }
37
38    #[test]
39    fn observer_records_events_and_metrics() {
40        let observer = DummyObserver::default();
41
42        observer.record_event(&ObserverEvent::HeartbeatTick);
43        observer.record_event(&ObserverEvent::Error {
44            component: "test".into(),
45            message: "boom".into(),
46        });
47        observer.record_metric(&ObserverMetric::TokensUsed(42));
48
49        assert_eq!(*observer.events.lock(), 2);
50        assert_eq!(*observer.metrics.lock(), 1);
51    }
52
53    #[test]
54    fn observer_default_flush_and_as_any_work() {
55        let observer = DummyObserver::default();
56
57        observer.flush();
58        assert_eq!(observer.name(), "dummy-observer");
59        assert!(observer.as_any().downcast_ref::<DummyObserver>().is_some());
60    }
61
62    #[test]
63    fn observer_event_and_metric_are_cloneable() {
64        let event = ObserverEvent::ToolCall {
65            tool: "shell".into(),
66            tool_call_id: None,
67            duration: Duration::from_millis(10),
68            success: true,
69            arguments: None,
70            result: None,
71        };
72        let metric = ObserverMetric::RequestLatency(Duration::from_millis(8));
73
74        let cloned_event = event.clone();
75        let cloned_metric = metric.clone();
76
77        assert!(matches!(cloned_event, ObserverEvent::ToolCall { .. }));
78        assert!(matches!(cloned_metric, ObserverMetric::RequestLatency(_)));
79    }
80}