Skip to main content

zeroclaw_runtime/observability/
noop.rs

1use super::traits::{Observer, ObserverEvent, ObserverMetric};
2use std::any::Any;
3
4/// Zero-overhead observer — all methods compile to nothing
5pub struct NoopObserver;
6
7impl Observer for NoopObserver {
8    #[inline(always)]
9    fn record_event(&self, _event: &ObserverEvent) {}
10
11    #[inline(always)]
12    fn record_metric(&self, _metric: &ObserverMetric) {}
13
14    fn name(&self) -> &str {
15        "noop"
16    }
17
18    fn as_any(&self) -> &dyn Any {
19        self
20    }
21}
22
23#[cfg(test)]
24mod tests {
25    use super::*;
26    use std::time::Duration;
27
28    #[test]
29    fn noop_name() {
30        assert_eq!(NoopObserver.name(), "noop");
31    }
32
33    #[test]
34    fn noop_record_event_does_not_panic() {
35        let obs = NoopObserver;
36        obs.record_event(&ObserverEvent::HeartbeatTick);
37        obs.record_event(&ObserverEvent::AgentStart {
38            model_provider: "test".into(),
39            model: "test".into(),
40        });
41        obs.record_event(&ObserverEvent::AgentEnd {
42            model_provider: "test".into(),
43            model: "test".into(),
44            duration: Duration::from_millis(100),
45            tokens_used: Some(42),
46            cost_usd: Some(0.001),
47        });
48        obs.record_event(&ObserverEvent::AgentEnd {
49            model_provider: "test".into(),
50            model: "test".into(),
51            duration: Duration::ZERO,
52            tokens_used: None,
53            cost_usd: None,
54        });
55        obs.record_event(&ObserverEvent::ToolCall {
56            tool: "shell".into(),
57            tool_call_id: None,
58            duration: Duration::from_secs(1),
59            success: true,
60            arguments: None,
61            result: None,
62        });
63        obs.record_event(&ObserverEvent::ChannelMessage {
64            channel: "cli".into(),
65            direction: "inbound".into(),
66        });
67        obs.record_event(&ObserverEvent::Error {
68            component: "test".into(),
69            message: "boom".into(),
70        });
71    }
72
73    #[test]
74    fn noop_record_metric_does_not_panic() {
75        let obs = NoopObserver;
76        obs.record_metric(&ObserverMetric::RequestLatency(Duration::from_millis(50)));
77        obs.record_metric(&ObserverMetric::TokensUsed(1000));
78        obs.record_metric(&ObserverMetric::ActiveSessions(5));
79        obs.record_metric(&ObserverMetric::QueueDepth(0));
80    }
81
82    #[test]
83    fn noop_flush_does_not_panic() {
84        NoopObserver.flush();
85    }
86}