dynpatch_core/
metrics.rs

1//! Metrics and observability for patch operations
2
3use std::sync::atomic::{AtomicU64, Ordering};
4use std::sync::Arc;
5
6/// Metrics collector for patch operations
7#[derive(Debug, Clone)]
8pub struct PatchMetrics {
9    loads_attempted: Arc<AtomicU64>,
10    loads_successful: Arc<AtomicU64>,
11    loads_failed: Arc<AtomicU64>,
12    rollbacks: Arc<AtomicU64>,
13    validation_failures: Arc<AtomicU64>,
14}
15
16impl Default for PatchMetrics {
17    fn default() -> Self {
18        Self::new()
19    }
20}
21
22impl PatchMetrics {
23    pub fn new() -> Self {
24        Self {
25            loads_attempted: Arc::new(AtomicU64::new(0)),
26            loads_successful: Arc::new(AtomicU64::new(0)),
27            loads_failed: Arc::new(AtomicU64::new(0)),
28            rollbacks: Arc::new(AtomicU64::new(0)),
29            validation_failures: Arc::new(AtomicU64::new(0)),
30        }
31    }
32
33    pub fn record_load_attempt(&self) {
34        self.loads_attempted.fetch_add(1, Ordering::Relaxed);
35    }
36
37    pub fn record_load_success(&self) {
38        self.loads_successful.fetch_add(1, Ordering::Relaxed);
39    }
40
41    pub fn record_load_failure(&self) {
42        self.loads_failed.fetch_add(1, Ordering::Relaxed);
43    }
44
45    pub fn record_rollback(&self) {
46        self.rollbacks.fetch_add(1, Ordering::Relaxed);
47    }
48
49    pub fn record_validation_failure(&self) {
50        self.validation_failures.fetch_add(1, Ordering::Relaxed);
51    }
52
53    pub fn loads_attempted(&self) -> u64 {
54        self.loads_attempted.load(Ordering::Relaxed)
55    }
56
57    pub fn loads_successful(&self) -> u64 {
58        self.loads_successful.load(Ordering::Relaxed)
59    }
60
61    pub fn loads_failed(&self) -> u64 {
62        self.loads_failed.load(Ordering::Relaxed)
63    }
64
65    pub fn rollbacks(&self) -> u64 {
66        self.rollbacks.load(Ordering::Relaxed)
67    }
68
69    pub fn validation_failures(&self) -> u64 {
70        self.validation_failures.load(Ordering::Relaxed)
71    }
72
73    pub fn reset(&self) {
74        self.loads_attempted.store(0, Ordering::Relaxed);
75        self.loads_successful.store(0, Ordering::Relaxed);
76        self.loads_failed.store(0, Ordering::Relaxed);
77        self.rollbacks.store(0, Ordering::Relaxed);
78        self.validation_failures.store(0, Ordering::Relaxed);
79    }
80}
81
82// Global metrics instance
83static GLOBAL_METRICS: once_cell::sync::Lazy<PatchMetrics> =
84    once_cell::sync::Lazy::new(PatchMetrics::new);
85
86/// Get the global metrics instance
87pub fn global_metrics() -> &'static PatchMetrics {
88    &GLOBAL_METRICS
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[test]
96    fn test_metrics() {
97        let metrics = PatchMetrics::new();
98        
99        assert_eq!(metrics.loads_attempted(), 0);
100        
101        metrics.record_load_attempt();
102        assert_eq!(metrics.loads_attempted(), 1);
103        
104        metrics.record_load_success();
105        assert_eq!(metrics.loads_successful(), 1);
106        
107        metrics.reset();
108        assert_eq!(metrics.loads_attempted(), 0);
109        assert_eq!(metrics.loads_successful(), 0);
110    }
111}