rocketmq_observability/metrics/
auth.rs1use std::sync::atomic::AtomicU64;
16use std::sync::atomic::Ordering;
17use std::sync::Arc;
18
19#[derive(Clone, Default)]
20pub struct AuthMetrics {
21 inner: Arc<AuthMetricsInner>,
22}
23
24#[derive(Default)]
25struct AuthMetricsInner {
26 acl_reload_attempts: AtomicU64,
27 acl_reload_successes: AtomicU64,
28 acl_reload_failures: AtomicU64,
29 acl_reload_skipped: AtomicU64,
30 cache_hits: AtomicU64,
31 cache_misses: AtomicU64,
32 cache_invalidations: AtomicU64,
33 signature_successes: AtomicU64,
34 signature_failures: AtomicU64,
35 whitelist_hits: AtomicU64,
36 whitelist_misses: AtomicU64,
37 authentication_successes: AtomicU64,
38 authentication_failures: AtomicU64,
39 authorization_successes: AtomicU64,
40 authorization_failures: AtomicU64,
41}
42
43#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
44pub struct AuthMetricsSnapshot {
45 pub acl_reload_attempts: u64,
46 pub acl_reload_successes: u64,
47 pub acl_reload_failures: u64,
48 pub acl_reload_skipped: u64,
49 pub cache_hits: u64,
50 pub cache_misses: u64,
51 pub cache_invalidations: u64,
52 pub signature_successes: u64,
53 pub signature_failures: u64,
54 pub whitelist_hits: u64,
55 pub whitelist_misses: u64,
56 pub authentication_successes: u64,
57 pub authentication_failures: u64,
58 pub authorization_successes: u64,
59 pub authorization_failures: u64,
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub struct AuthMetricSample {
64 pub name: &'static str,
65 pub value: u64,
66}
67
68impl AuthMetricsSnapshot {
69 pub const SAMPLE_COUNT: usize = 15;
70
71 pub fn samples(&self) -> [AuthMetricSample; Self::SAMPLE_COUNT] {
72 [
73 AuthMetricSample {
74 name: "acl_reload_attempts",
75 value: self.acl_reload_attempts,
76 },
77 AuthMetricSample {
78 name: "acl_reload_successes",
79 value: self.acl_reload_successes,
80 },
81 AuthMetricSample {
82 name: "acl_reload_failures",
83 value: self.acl_reload_failures,
84 },
85 AuthMetricSample {
86 name: "acl_reload_skipped",
87 value: self.acl_reload_skipped,
88 },
89 AuthMetricSample {
90 name: "cache_hits",
91 value: self.cache_hits,
92 },
93 AuthMetricSample {
94 name: "cache_misses",
95 value: self.cache_misses,
96 },
97 AuthMetricSample {
98 name: "cache_invalidations",
99 value: self.cache_invalidations,
100 },
101 AuthMetricSample {
102 name: "signature_successes",
103 value: self.signature_successes,
104 },
105 AuthMetricSample {
106 name: "signature_failures",
107 value: self.signature_failures,
108 },
109 AuthMetricSample {
110 name: "whitelist_hits",
111 value: self.whitelist_hits,
112 },
113 AuthMetricSample {
114 name: "whitelist_misses",
115 value: self.whitelist_misses,
116 },
117 AuthMetricSample {
118 name: "authentication_successes",
119 value: self.authentication_successes,
120 },
121 AuthMetricSample {
122 name: "authentication_failures",
123 value: self.authentication_failures,
124 },
125 AuthMetricSample {
126 name: "authorization_successes",
127 value: self.authorization_successes,
128 },
129 AuthMetricSample {
130 name: "authorization_failures",
131 value: self.authorization_failures,
132 },
133 ]
134 }
135}
136
137impl AuthMetrics {
138 pub fn snapshot(&self) -> AuthMetricsSnapshot {
139 AuthMetricsSnapshot {
140 acl_reload_attempts: self.inner.acl_reload_attempts.load(Ordering::Relaxed),
141 acl_reload_successes: self.inner.acl_reload_successes.load(Ordering::Relaxed),
142 acl_reload_failures: self.inner.acl_reload_failures.load(Ordering::Relaxed),
143 acl_reload_skipped: self.inner.acl_reload_skipped.load(Ordering::Relaxed),
144 cache_hits: self.inner.cache_hits.load(Ordering::Relaxed),
145 cache_misses: self.inner.cache_misses.load(Ordering::Relaxed),
146 cache_invalidations: self.inner.cache_invalidations.load(Ordering::Relaxed),
147 signature_successes: self.inner.signature_successes.load(Ordering::Relaxed),
148 signature_failures: self.inner.signature_failures.load(Ordering::Relaxed),
149 whitelist_hits: self.inner.whitelist_hits.load(Ordering::Relaxed),
150 whitelist_misses: self.inner.whitelist_misses.load(Ordering::Relaxed),
151 authentication_successes: self.inner.authentication_successes.load(Ordering::Relaxed),
152 authentication_failures: self.inner.authentication_failures.load(Ordering::Relaxed),
153 authorization_successes: self.inner.authorization_successes.load(Ordering::Relaxed),
154 authorization_failures: self.inner.authorization_failures.load(Ordering::Relaxed),
155 }
156 }
157
158 #[inline]
159 pub fn record_acl_reload_attempt(&self) {
160 self.inner.acl_reload_attempts.fetch_add(1, Ordering::Relaxed);
161 }
162
163 #[inline]
164 pub fn record_acl_reload_success(&self) {
165 self.inner.acl_reload_successes.fetch_add(1, Ordering::Relaxed);
166 }
167
168 #[inline]
169 pub fn record_acl_reload_failure(&self) {
170 self.inner.acl_reload_failures.fetch_add(1, Ordering::Relaxed);
171 }
172
173 #[inline]
174 pub fn record_acl_reload_skipped(&self) {
175 self.inner.acl_reload_skipped.fetch_add(1, Ordering::Relaxed);
176 }
177
178 #[inline]
179 pub fn record_cache_hit(&self) {
180 self.inner.cache_hits.fetch_add(1, Ordering::Relaxed);
181 }
182
183 #[inline]
184 pub fn record_cache_miss(&self) {
185 self.inner.cache_misses.fetch_add(1, Ordering::Relaxed);
186 }
187
188 #[inline]
189 pub fn record_cache_invalidation(&self) {
190 self.inner.cache_invalidations.fetch_add(1, Ordering::Relaxed);
191 }
192
193 #[inline]
194 pub fn record_signature_verification(&self, success: bool) {
195 if success {
196 self.inner.signature_successes.fetch_add(1, Ordering::Relaxed);
197 } else {
198 self.inner.signature_failures.fetch_add(1, Ordering::Relaxed);
199 }
200 }
201
202 #[inline]
203 pub fn record_whitelist_check(&self, matched: bool) {
204 if matched {
205 self.inner.whitelist_hits.fetch_add(1, Ordering::Relaxed);
206 } else {
207 self.inner.whitelist_misses.fetch_add(1, Ordering::Relaxed);
208 }
209 }
210
211 #[inline]
212 pub fn record_authentication_result(&self, success: bool) {
213 if success {
214 self.inner.authentication_successes.fetch_add(1, Ordering::Relaxed);
215 } else {
216 self.inner.authentication_failures.fetch_add(1, Ordering::Relaxed);
217 }
218 }
219
220 #[inline]
221 pub fn record_authorization_result(&self, success: bool) {
222 if success {
223 self.inner.authorization_successes.fetch_add(1, Ordering::Relaxed);
224 } else {
225 self.inner.authorization_failures.fetch_add(1, Ordering::Relaxed);
226 }
227 }
228}
229
230#[cfg(test)]
231mod tests {
232 use super::AuthMetrics;
233 use super::AuthMetricsSnapshot;
234
235 #[test]
236 fn auth_metrics_snapshot_tracks_all_counter_groups() {
237 let metrics = AuthMetrics::default();
238
239 metrics.record_acl_reload_attempt();
240 metrics.record_acl_reload_success();
241 metrics.record_acl_reload_failure();
242 metrics.record_acl_reload_skipped();
243 metrics.record_cache_hit();
244 metrics.record_cache_miss();
245 metrics.record_cache_invalidation();
246 metrics.record_signature_verification(true);
247 metrics.record_signature_verification(false);
248 metrics.record_whitelist_check(true);
249 metrics.record_whitelist_check(false);
250 metrics.record_authentication_result(true);
251 metrics.record_authentication_result(false);
252 metrics.record_authorization_result(true);
253 metrics.record_authorization_result(false);
254
255 let snapshot = metrics.snapshot();
256 assert_eq!(snapshot.acl_reload_attempts, 1);
257 assert_eq!(snapshot.acl_reload_successes, 1);
258 assert_eq!(snapshot.acl_reload_failures, 1);
259 assert_eq!(snapshot.acl_reload_skipped, 1);
260 assert_eq!(snapshot.cache_hits, 1);
261 assert_eq!(snapshot.cache_misses, 1);
262 assert_eq!(snapshot.cache_invalidations, 1);
263 assert_eq!(snapshot.signature_successes, 1);
264 assert_eq!(snapshot.signature_failures, 1);
265 assert_eq!(snapshot.whitelist_hits, 1);
266 assert_eq!(snapshot.whitelist_misses, 1);
267 assert_eq!(snapshot.authentication_successes, 1);
268 assert_eq!(snapshot.authentication_failures, 1);
269 assert_eq!(snapshot.authorization_successes, 1);
270 assert_eq!(snapshot.authorization_failures, 1);
271 }
272
273 #[test]
274 fn auth_metrics_snapshot_exports_stable_samples() {
275 let snapshot = AuthMetricsSnapshot {
276 acl_reload_attempts: 1,
277 authorization_failures: 15,
278 ..AuthMetricsSnapshot::default()
279 };
280
281 let samples = snapshot.samples();
282
283 assert_eq!(samples.len(), AuthMetricsSnapshot::SAMPLE_COUNT);
284 assert_eq!(samples[0].name, "acl_reload_attempts");
285 assert_eq!(samples[0].value, 1);
286 assert_eq!(samples[14].name, "authorization_failures");
287 assert_eq!(samples[14].value, 15);
288 }
289}