lean_ctx/proxy/
prefix_cache_stats.rs1use std::sync::atomic::{AtomicU64, Ordering};
8
9use serde::{Deserialize, Serialize};
10
11static PREFIX_HITS: AtomicU64 = AtomicU64::new(0);
12static PREFIX_MISSES: AtomicU64 = AtomicU64::new(0);
13static FROZEN_MSG_SUM: AtomicU64 = AtomicU64::new(0);
14static FROZEN_MSG_COUNT: AtomicU64 = AtomicU64::new(0);
15static DELTA_BYTES_ORIGINAL: AtomicU64 = AtomicU64::new(0);
16static DELTA_BYTES_COMPRESSED: AtomicU64 = AtomicU64::new(0);
17static REPLAY_HITS: AtomicU64 = AtomicU64::new(0);
18static REPLAY_MISSES: AtomicU64 = AtomicU64::new(0);
19static STICKY_INJECTIONS: AtomicU64 = AtomicU64::new(0);
20static HEADROOM_COMPAT_REQUESTS: AtomicU64 = AtomicU64::new(0);
21
22pub fn record_hit() {
23 PREFIX_HITS.fetch_add(1, Ordering::Relaxed);
24}
25
26pub fn record_miss() {
27 PREFIX_MISSES.fetch_add(1, Ordering::Relaxed);
28}
29
30pub fn record_frozen_count(count: u64) {
31 FROZEN_MSG_SUM.fetch_add(count, Ordering::Relaxed);
32 FROZEN_MSG_COUNT.fetch_add(1, Ordering::Relaxed);
33}
34
35pub fn record_delta(original: u64, compressed: u64) {
36 DELTA_BYTES_ORIGINAL.fetch_add(original, Ordering::Relaxed);
37 DELTA_BYTES_COMPRESSED.fetch_add(compressed, Ordering::Relaxed);
38}
39
40pub fn record_replay_hit() {
41 REPLAY_HITS.fetch_add(1, Ordering::Relaxed);
42}
43
44pub fn record_replay_miss() {
45 REPLAY_MISSES.fetch_add(1, Ordering::Relaxed);
46}
47
48pub fn record_sticky_injection() {
49 STICKY_INJECTIONS.fetch_add(1, Ordering::Relaxed);
50}
51
52pub fn record_headroom_compat() {
53 HEADROOM_COMPAT_REQUESTS.fetch_add(1, Ordering::Relaxed);
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
57pub struct PrefixCacheStats {
58 pub hits: u64,
59 pub misses: u64,
60 pub hit_rate: f64,
61 pub alignment_score: u64,
62 pub frozen_message_count_avg: f64,
63 pub delta_compression_ratio: f64,
64 pub replay_hits: u64,
65 pub replay_misses: u64,
66 pub sticky_tool_injections: u64,
67 pub headroom_compat_requests: u64,
68}
69
70fn alignment_score(volatile_detected: u64, requests_scanned: u64) -> u64 {
71 if requests_scanned == 0 {
72 return 100;
73 }
74 let avg = volatile_detected as f64 / requests_scanned as f64;
75 100u64.saturating_sub((avg * 10.0).round() as u64)
76}
77
78#[must_use]
79pub fn snapshot() -> PrefixCacheStats {
80 let hits = PREFIX_HITS.load(Ordering::Relaxed);
81 let misses = PREFIX_MISSES.load(Ordering::Relaxed);
82 let total = hits + misses;
83 let hit_rate = if total > 0 {
84 hits as f64 / total as f64
85 } else {
86 1.0
87 };
88
89 let frozen_sum = FROZEN_MSG_SUM.load(Ordering::Relaxed);
90 let frozen_count = FROZEN_MSG_COUNT.load(Ordering::Relaxed);
91 let frozen_avg = if frozen_count > 0 {
92 frozen_sum as f64 / frozen_count as f64
93 } else {
94 0.0
95 };
96
97 let d_orig = DELTA_BYTES_ORIGINAL.load(Ordering::Relaxed);
98 let d_comp = DELTA_BYTES_COMPRESSED.load(Ordering::Relaxed);
99 let delta_ratio = if d_orig > 0 {
100 d_comp as f64 / d_orig as f64
101 } else {
102 0.0
103 };
104
105 let cs = super::cache_safety::snapshot();
106 let score = alignment_score(cs.volatile_fields_detected, cs.volatile_system_requests);
107
108 PrefixCacheStats {
109 hits,
110 misses,
111 hit_rate,
112 alignment_score: score,
113 frozen_message_count_avg: frozen_avg,
114 delta_compression_ratio: delta_ratio,
115 replay_hits: REPLAY_HITS.load(Ordering::Relaxed),
116 replay_misses: REPLAY_MISSES.load(Ordering::Relaxed),
117 sticky_tool_injections: STICKY_INJECTIONS.load(Ordering::Relaxed),
118 headroom_compat_requests: HEADROOM_COMPAT_REQUESTS.load(Ordering::Relaxed),
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn alignment_score_perfect_when_no_volatiles() {
128 assert_eq!(alignment_score(0, 100), 100);
129 }
130
131 #[test]
132 fn alignment_score_degrades_with_volatiles() {
133 assert_eq!(alignment_score(10, 10), 90);
134 assert_eq!(alignment_score(50, 10), 50);
135 }
136
137 #[test]
138 fn alignment_score_clamps_to_zero() {
139 assert_eq!(alignment_score(1000, 10), 0);
140 }
141
142 #[test]
143 fn alignment_score_is_100_when_no_requests() {
144 assert_eq!(alignment_score(0, 0), 100);
145 }
146}