1use std::time::Duration;
2
3pub trait MetricsCollector: Send + Sync {
6 fn record_exchange_duration(&self, route_id: &str, duration: Duration);
8
9 fn increment_errors(&self, route_id: &str, error_type: &str);
11
12 fn increment_exchanges(&self, route_id: &str);
14
15 fn set_queue_depth(&self, route_id: &str, depth: usize);
17
18 fn record_circuit_breaker_change(&self, route_id: &str, from: &str, to: &str);
20}
21
22pub struct NoOpMetrics;
24
25impl MetricsCollector for NoOpMetrics {
26 fn record_exchange_duration(&self, _route_id: &str, _duration: Duration) {}
27 fn increment_errors(&self, _route_id: &str, _error_type: &str) {}
28 fn increment_exchanges(&self, _route_id: &str) {}
29 fn set_queue_depth(&self, _route_id: &str, _depth: usize) {}
30 fn record_circuit_breaker_change(&self, _route_id: &str, _from: &str, _to: &str) {}
31}
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36 use std::sync::Arc;
37
38 #[test]
39 fn test_noop_metrics_implements_trait() {
40 let metrics = NoOpMetrics;
41 let metrics_arc: Arc<dyn MetricsCollector> = Arc::new(metrics);
42
43 metrics_arc.record_exchange_duration("test-route", Duration::from_millis(100));
45 metrics_arc.increment_errors("test-route", "test-error");
46 metrics_arc.increment_exchanges("test-route");
47 metrics_arc.set_queue_depth("test-route", 5);
48 metrics_arc.record_circuit_breaker_change("test-route", "closed", "open");
49 }
50
51 #[test]
52 fn test_custom_metrics_collector() {
53 struct TestMetrics {
54 exchange_count: std::sync::atomic::AtomicU64,
55 }
56
57 impl MetricsCollector for TestMetrics {
58 fn record_exchange_duration(&self, route_id: &str, duration: Duration) {
59 println!("Route {} took {}ms", route_id, duration.as_millis());
61 }
62
63 fn increment_errors(&self, route_id: &str, error_type: &str) {
64 println!("Route {} had error: {}", route_id, error_type);
66 }
67
68 fn increment_exchanges(&self, route_id: &str) {
69 self.exchange_count
71 .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
72 println!("Route {} processed exchange", route_id);
73 }
74
75 fn set_queue_depth(&self, route_id: &str, depth: usize) {
76 println!("Route {} queue depth: {}", route_id, depth);
78 }
79
80 fn record_circuit_breaker_change(&self, route_id: &str, from: &str, to: &str) {
81 println!("Route {} circuit breaker: {} -> {}", route_id, from, to);
83 }
84 }
85
86 let test_metrics = TestMetrics {
87 exchange_count: std::sync::atomic::AtomicU64::new(0),
88 };
89 let metrics_arc: Arc<dyn MetricsCollector> = Arc::new(test_metrics);
90
91 metrics_arc.record_exchange_duration("test-route", Duration::from_millis(100));
93 metrics_arc.increment_errors("test-route", "test-error");
94 metrics_arc.increment_exchanges("test-route");
95 metrics_arc.set_queue_depth("test-route", 5);
96 metrics_arc.record_circuit_breaker_change("test-route", "closed", "open");
97
98 }
101}