Skip to main content

worldinterface_core/
metrics.rs

1//! Metrics recording trait for cross-crate observability.
2//!
3//! Defines the [`MetricsRecorder`] trait that allows leaf crates (coordinator,
4//! connector, contextstore) to record metrics without depending on a specific
5//! metrics implementation like Prometheus. The daemon provides a real
6//! implementation; embedded/test use gets [`NoopMetricsRecorder`].
7
8/// Trait for recording observability metrics across UI crates.
9///
10/// Implemented by the daemon's Prometheus registry. When no metrics
11/// are configured, [`NoopMetricsRecorder`] is used.
12pub trait MetricsRecorder: Send + Sync {
13    /// Record a successful step completion with connector name and duration.
14    fn record_step_completed(&self, connector: &str, duration_secs: f64);
15
16    /// Record a step failure with connector name.
17    fn record_step_failed(&self, connector: &str);
18
19    /// Record a connector invocation (before execution).
20    fn record_connector_invocation(&self, connector: &str);
21
22    /// Record a ContextStore write operation.
23    fn record_contextstore_write(&self);
24
25    /// Record a flow run completing successfully.
26    fn record_flow_completed(&self);
27
28    /// Record a flow run failing.
29    fn record_flow_failed(&self);
30}
31
32/// No-op implementation for embedded/test use without metrics.
33pub struct NoopMetricsRecorder;
34
35impl MetricsRecorder for NoopMetricsRecorder {
36    fn record_step_completed(&self, _: &str, _: f64) {}
37    fn record_step_failed(&self, _: &str) {}
38    fn record_connector_invocation(&self, _: &str) {}
39    fn record_contextstore_write(&self) {}
40    fn record_flow_completed(&self) {}
41    fn record_flow_failed(&self) {}
42}
43
44#[cfg(test)]
45mod tests {
46    use std::sync::Arc;
47
48    use super::*;
49
50    #[test]
51    fn noop_recorder_does_not_panic() {
52        let recorder = NoopMetricsRecorder;
53        recorder.record_step_completed("delay", 0.5);
54        recorder.record_step_failed("http.request");
55        recorder.record_connector_invocation("fs.write");
56        recorder.record_contextstore_write();
57        recorder.record_flow_completed();
58        recorder.record_flow_failed();
59    }
60
61    #[test]
62    fn noop_recorder_is_send_sync() {
63        fn assert_send_sync<T: Send + Sync>() {}
64        assert_send_sync::<NoopMetricsRecorder>();
65    }
66
67    #[test]
68    fn metrics_recorder_trait_object_is_send_sync() {
69        fn assert_send_sync<T: Send + Sync>() {}
70        assert_send_sync::<Arc<dyn MetricsRecorder>>();
71    }
72}