cachekit_core/
metrics.rs

1//! Observability metrics for Rust operations
2//!
3//! Tracks performance and resource usage of compression, checksums, and encryption.
4//! Metrics are designed to be sent to Python layer for Prometheus export.
5
6use serde::{Deserialize, Serialize};
7
8/// Operation metrics for visibility into Rust layer performance
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct OperationMetrics {
11    /// Compression operation time in microseconds (0 if not performed)
12    pub compression_time_micros: u64,
13
14    /// Compression ratio (original_size / compressed_size, >1.0 means compression helped)
15    pub compression_ratio: f64,
16
17    /// Checksum (xxHash3-64) operation time in microseconds
18    pub checksum_time_micros: u64,
19
20    /// Encryption operation time in microseconds (None if not performed)
21    pub encryption_time_micros: Option<u64>,
22
23    /// Whether hardware acceleration was used (for SHA, AES, etc.)
24    pub hardware_accelerated: bool,
25}
26
27impl OperationMetrics {
28    /// Create new empty metrics
29    pub fn new() -> Self {
30        OperationMetrics {
31            compression_time_micros: 0,
32            compression_ratio: 1.0,
33            checksum_time_micros: 0,
34            encryption_time_micros: None,
35            hardware_accelerated: false,
36        }
37    }
38
39    /// Set compression metrics
40    pub fn with_compression(
41        mut self,
42        time_micros: u64,
43        original_size: usize,
44        compressed_size: usize,
45    ) -> Self {
46        self.compression_time_micros = time_micros;
47        if compressed_size > 0 {
48            self.compression_ratio = original_size as f64 / compressed_size as f64;
49        }
50        self
51    }
52
53    /// Set checksum metrics
54    pub fn with_checksum(mut self, time_micros: u64) -> Self {
55        self.checksum_time_micros = time_micros;
56        self
57    }
58
59    /// Set encryption metrics
60    pub fn with_encryption(mut self, time_micros: u64, hw_accel: bool) -> Self {
61        self.encryption_time_micros = Some(time_micros);
62        self.hardware_accelerated = hw_accel;
63        self
64    }
65
66    /// Total operation time in microseconds
67    pub fn total_time_micros(&self) -> u64 {
68        let mut total = self.compression_time_micros + self.checksum_time_micros;
69        if let Some(enc_time) = self.encryption_time_micros {
70            total += enc_time;
71        }
72        total
73    }
74}
75
76impl Default for OperationMetrics {
77    fn default() -> Self {
78        Self::new()
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn test_metrics_creation() {
88        let metrics = OperationMetrics::new();
89        assert_eq!(metrics.compression_time_micros, 0);
90        assert_eq!(metrics.checksum_time_micros, 0);
91        assert_eq!(metrics.compression_ratio, 1.0);
92        assert_eq!(metrics.encryption_time_micros, None);
93    }
94
95    #[test]
96    fn test_compression_metrics() {
97        let metrics = OperationMetrics::new().with_compression(100, 1000, 250);
98
99        assert_eq!(metrics.compression_time_micros, 100);
100        assert!((metrics.compression_ratio - 4.0).abs() < 0.01); // 1000/250 = 4.0
101    }
102
103    #[test]
104    fn test_total_time() {
105        let metrics = OperationMetrics::new()
106            .with_compression(100, 1000, 250)
107            .with_checksum(50)
108            .with_encryption(200, true);
109
110        assert_eq!(metrics.total_time_micros(), 350); // 100 + 50 + 200
111    }
112}