1use std::sync::atomic::{AtomicU64, Ordering};
4use std::sync::Arc;
5
6#[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
82static GLOBAL_METRICS: once_cell::sync::Lazy<PatchMetrics> =
84 once_cell::sync::Lazy::new(PatchMetrics::new);
85
86pub 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}