1use std::fmt::Write as _;
2use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
3use std::sync::OnceLock;
4
5const QUEUE_WAIT_BUCKETS_MS: &[u64] = &[
6 1, 2, 5, 10, 20, 50, 75, 100, 150, 200, 300, 500, 750, 1_000, 1_500, 2_000, 5_000,
7];
8const CLIENT_WRITE_BUCKETS_MS: &[u64] = &[
9 1, 2, 5, 10, 20, 50, 75, 100, 150, 200, 300, 500, 750, 1_000, 1_500, 2_000, 5_000, 10_000,
10];
11const QUORUM_ACK_BUCKETS_MS: &[u64] = &[
12 1, 2, 5, 10, 20, 50, 75, 100, 150, 200, 300, 500, 750, 1_000, 1_500, 2_000, 5_000, 10_000,
13];
14const BATCH_SIZE_BUCKETS: &[u64] = &[1, 2, 4, 8, 16, 32, 64, 96, 128, 192, 256, 384, 512, 1024];
15const BG_IO_WAIT_BUCKETS_MS: &[u64] = &[
16 1, 2, 5, 10, 20, 50, 75, 100, 150, 200, 300, 500, 750, 1_000, 1_500, 2_000, 5_000, 10_000,
17];
18const WRITE_STALL_BUCKETS_MS: &[u64] = &[
19 1, 2, 5, 10, 20, 50, 75, 100, 150, 200, 300, 500, 750, 1_000, 1_500, 2_000, 5_000, 10_000,
20];
21
22#[derive(Clone, Copy, Debug)]
23enum HistogramMode {
24 SecondsFromMillis,
25 Raw,
26}
27
28#[derive(Debug)]
29struct Histogram {
30 bounds: &'static [u64],
31 mode: HistogramMode,
32 buckets: Vec<AtomicU64>,
33 count: AtomicU64,
34 sum: AtomicU64,
35}
36
37impl Histogram {
38 fn new(bounds: &'static [u64], mode: HistogramMode) -> Self {
39 let buckets = (0..=bounds.len()).map(|_| AtomicU64::new(0)).collect();
40 Self {
41 bounds,
42 mode,
43 buckets,
44 count: AtomicU64::new(0),
45 sum: AtomicU64::new(0),
46 }
47 }
48
49 fn observe(&self, value: u64) {
50 self.count.fetch_add(1, Ordering::Relaxed);
51 self.sum.fetch_add(value, Ordering::Relaxed);
52
53 let bucket_idx = self
54 .bounds
55 .iter()
56 .position(|bound| value <= *bound)
57 .unwrap_or(self.bounds.len());
58 self.buckets[bucket_idx].fetch_add(1, Ordering::Relaxed);
59 }
60
61 fn render(&self, out: &mut String, metric_name: &str, help: &str) {
62 let _ = writeln!(out, "# HELP {metric_name} {help}");
63 let _ = writeln!(out, "# TYPE {metric_name} histogram");
64
65 let mut cumulative = 0_u64;
66 for (idx, bound) in self.bounds.iter().enumerate() {
67 cumulative = cumulative.saturating_add(self.buckets[idx].load(Ordering::Relaxed));
68 let bound_label = match self.mode {
69 HistogramMode::SecondsFromMillis => format!("{:.6}", (*bound as f64) / 1_000.0),
70 HistogramMode::Raw => bound.to_string(),
71 };
72 let _ = writeln!(
73 out,
74 "{metric_name}_bucket{{le=\"{bound_label}\"}} {cumulative}"
75 );
76 }
77
78 cumulative =
79 cumulative.saturating_add(self.buckets[self.bounds.len()].load(Ordering::Relaxed));
80 let _ = writeln!(out, "{metric_name}_bucket{{le=\"+Inf\"}} {cumulative}");
81
82 let sum_value = self.sum.load(Ordering::Relaxed);
83 let sum_label = match self.mode {
84 HistogramMode::SecondsFromMillis => format!("{:.6}", (sum_value as f64) / 1_000.0),
85 HistogramMode::Raw => sum_value.to_string(),
86 };
87 let _ = writeln!(out, "{metric_name}_sum {sum_label}");
88 let _ = writeln!(
89 out,
90 "{metric_name}_count {}",
91 self.count.load(Ordering::Relaxed)
92 );
93 }
94}
95
96#[derive(Debug)]
97struct AstraMetrics {
98 enabled: AtomicBool,
99 put_queue_wait_ms: Histogram,
100 put_queue_wait_tier0_ms: Histogram,
101 put_queue_wait_normal_ms: Histogram,
102 put_raft_write_ms: Histogram,
103 put_quorum_ack_ms: Histogram,
104 put_batch_size: Histogram,
105 bg_io_throttle_wait_ms: Histogram,
106 put_batches_total: AtomicU64,
107 put_batch_requests_total: AtomicU64,
108 put_tier0_enqueued_total: AtomicU64,
109 put_tier0_dispatch_total: AtomicU64,
110 put_tier0_bypass_write_pressure_total: AtomicU64,
111 quorum_ack_observations: AtomicU64,
112 latest_quorum_ack_ms: AtomicU64,
113 put_inflight_requests: AtomicU64,
114 put_tier0_queue_depth: AtomicU64,
115 put_normal_queue_depth: AtomicU64,
116 wal_effective_linger_us: AtomicU64,
117 wal_queue_depth: AtomicU64,
118 wal_queue_bytes: AtomicU64,
119 lsm_synth_l0_files: AtomicU64,
120 write_stall_delay_ms: Histogram,
121 write_stall_events_total: AtomicU64,
122 write_stall_band_5_events_total: AtomicU64,
123 write_stall_band_6_events_total: AtomicU64,
124 write_stall_band_7_plus_events_total: AtomicU64,
125 write_reject_events_total: AtomicU64,
126 bg_io_tokens_available: AtomicU64,
127 bg_io_sqe_tokens_available: AtomicU64,
128 bg_io_throttle_events_total: AtomicU64,
129 bg_io_sqe_wait_ms: Histogram,
130 bg_io_sqe_throttle_events_total: AtomicU64,
131 list_prefix_filter_skips_total: AtomicU64,
132 list_prefix_filter_hits_total: AtomicU64,
133 list_revision_filter_skips_total: AtomicU64,
134 list_revision_filter_hits_total: AtomicU64,
135 list_prefetch_hits_total: AtomicU64,
136 list_prefetch_misses_total: AtomicU64,
137 read_isolation_dispatch_total: AtomicU64,
138 read_isolation_failures_total: AtomicU64,
139 read_quorum_checks_total: AtomicU64,
140 read_quorum_failures_total: AtomicU64,
141 read_quorum_internal_total: AtomicU64,
142 transport_closed_conn_unavailable_total: AtomicU64,
143 forward_retry_attempts_total: AtomicU64,
144 gateway_read_ticket_hits_total: AtomicU64,
145 gateway_read_ticket_misses_total: AtomicU64,
146 gateway_singleflight_leader_total: AtomicU64,
147 gateway_singleflight_waiter_total: AtomicU64,
148 gateway_singleflight_overflow_total: AtomicU64,
149 gateway_singleflight_waiter_timeouts_total: AtomicU64,
150 request_get_total: AtomicU64,
151 request_list_total: AtomicU64,
152 request_put_total: AtomicU64,
153 request_delete_total: AtomicU64,
154 request_txn_total: AtomicU64,
155 request_lease_total: AtomicU64,
156 request_watch_total: AtomicU64,
157 request_tier0_total: AtomicU64,
158 profile_switch_total: AtomicU64,
159 profile_active_kubernetes: AtomicU64,
160 profile_active_omni: AtomicU64,
161 profile_active_gateway: AtomicU64,
162 profile_active_auto: AtomicU64,
163 profile_applied_put_max_requests: AtomicU64,
164 profile_applied_put_linger_us: AtomicU64,
165 profile_applied_prefetch_entries: AtomicU64,
166 profile_applied_bg_io_tokens_per_sec: AtomicU64,
167}
168
169impl AstraMetrics {
170 fn new() -> Self {
171 Self {
172 enabled: AtomicBool::new(true),
173 put_queue_wait_ms: Histogram::new(
174 QUEUE_WAIT_BUCKETS_MS,
175 HistogramMode::SecondsFromMillis,
176 ),
177 put_queue_wait_tier0_ms: Histogram::new(
178 QUEUE_WAIT_BUCKETS_MS,
179 HistogramMode::SecondsFromMillis,
180 ),
181 put_queue_wait_normal_ms: Histogram::new(
182 QUEUE_WAIT_BUCKETS_MS,
183 HistogramMode::SecondsFromMillis,
184 ),
185 put_raft_write_ms: Histogram::new(
186 CLIENT_WRITE_BUCKETS_MS,
187 HistogramMode::SecondsFromMillis,
188 ),
189 put_quorum_ack_ms: Histogram::new(
190 QUORUM_ACK_BUCKETS_MS,
191 HistogramMode::SecondsFromMillis,
192 ),
193 put_batch_size: Histogram::new(BATCH_SIZE_BUCKETS, HistogramMode::Raw),
194 bg_io_throttle_wait_ms: Histogram::new(
195 BG_IO_WAIT_BUCKETS_MS,
196 HistogramMode::SecondsFromMillis,
197 ),
198 put_batches_total: AtomicU64::new(0),
199 put_batch_requests_total: AtomicU64::new(0),
200 put_tier0_enqueued_total: AtomicU64::new(0),
201 put_tier0_dispatch_total: AtomicU64::new(0),
202 put_tier0_bypass_write_pressure_total: AtomicU64::new(0),
203 quorum_ack_observations: AtomicU64::new(0),
204 latest_quorum_ack_ms: AtomicU64::new(0),
205 put_inflight_requests: AtomicU64::new(0),
206 put_tier0_queue_depth: AtomicU64::new(0),
207 put_normal_queue_depth: AtomicU64::new(0),
208 wal_effective_linger_us: AtomicU64::new(0),
209 wal_queue_depth: AtomicU64::new(0),
210 wal_queue_bytes: AtomicU64::new(0),
211 lsm_synth_l0_files: AtomicU64::new(0),
212 write_stall_delay_ms: Histogram::new(
213 WRITE_STALL_BUCKETS_MS,
214 HistogramMode::SecondsFromMillis,
215 ),
216 write_stall_events_total: AtomicU64::new(0),
217 write_stall_band_5_events_total: AtomicU64::new(0),
218 write_stall_band_6_events_total: AtomicU64::new(0),
219 write_stall_band_7_plus_events_total: AtomicU64::new(0),
220 write_reject_events_total: AtomicU64::new(0),
221 bg_io_tokens_available: AtomicU64::new(0),
222 bg_io_sqe_tokens_available: AtomicU64::new(0),
223 bg_io_throttle_events_total: AtomicU64::new(0),
224 bg_io_sqe_wait_ms: Histogram::new(
225 BG_IO_WAIT_BUCKETS_MS,
226 HistogramMode::SecondsFromMillis,
227 ),
228 bg_io_sqe_throttle_events_total: AtomicU64::new(0),
229 list_prefix_filter_skips_total: AtomicU64::new(0),
230 list_prefix_filter_hits_total: AtomicU64::new(0),
231 list_revision_filter_skips_total: AtomicU64::new(0),
232 list_revision_filter_hits_total: AtomicU64::new(0),
233 list_prefetch_hits_total: AtomicU64::new(0),
234 list_prefetch_misses_total: AtomicU64::new(0),
235 read_isolation_dispatch_total: AtomicU64::new(0),
236 read_isolation_failures_total: AtomicU64::new(0),
237 read_quorum_checks_total: AtomicU64::new(0),
238 read_quorum_failures_total: AtomicU64::new(0),
239 read_quorum_internal_total: AtomicU64::new(0),
240 transport_closed_conn_unavailable_total: AtomicU64::new(0),
241 forward_retry_attempts_total: AtomicU64::new(0),
242 gateway_read_ticket_hits_total: AtomicU64::new(0),
243 gateway_read_ticket_misses_total: AtomicU64::new(0),
244 gateway_singleflight_leader_total: AtomicU64::new(0),
245 gateway_singleflight_waiter_total: AtomicU64::new(0),
246 gateway_singleflight_overflow_total: AtomicU64::new(0),
247 gateway_singleflight_waiter_timeouts_total: AtomicU64::new(0),
248 request_get_total: AtomicU64::new(0),
249 request_list_total: AtomicU64::new(0),
250 request_put_total: AtomicU64::new(0),
251 request_delete_total: AtomicU64::new(0),
252 request_txn_total: AtomicU64::new(0),
253 request_lease_total: AtomicU64::new(0),
254 request_watch_total: AtomicU64::new(0),
255 request_tier0_total: AtomicU64::new(0),
256 profile_switch_total: AtomicU64::new(0),
257 profile_active_kubernetes: AtomicU64::new(0),
258 profile_active_omni: AtomicU64::new(0),
259 profile_active_gateway: AtomicU64::new(0),
260 profile_active_auto: AtomicU64::new(1),
261 profile_applied_put_max_requests: AtomicU64::new(0),
262 profile_applied_put_linger_us: AtomicU64::new(0),
263 profile_applied_prefetch_entries: AtomicU64::new(0),
264 profile_applied_bg_io_tokens_per_sec: AtomicU64::new(0),
265 }
266 }
267
268 fn enabled(&self) -> bool {
269 self.enabled.load(Ordering::Relaxed)
270 }
271}
272
273static METRICS: OnceLock<AstraMetrics> = OnceLock::new();
274
275fn metrics() -> &'static AstraMetrics {
276 METRICS.get_or_init(AstraMetrics::new)
277}
278
279#[derive(Debug, Clone, Copy, Default)]
280pub struct RequestMixSnapshot {
281 pub get: u64,
282 pub list: u64,
283 pub put: u64,
284 pub delete: u64,
285 pub txn: u64,
286 pub lease: u64,
287 pub watch: u64,
288 pub tier0: u64,
289}
290
291impl RequestMixSnapshot {
292 pub fn total(self) -> u64 {
293 self.get
294 .saturating_add(self.list)
295 .saturating_add(self.put)
296 .saturating_add(self.delete)
297 .saturating_add(self.txn)
298 .saturating_add(self.lease)
299 .saturating_add(self.watch)
300 }
301
302 pub fn delta_since(self, previous: Self) -> Self {
303 Self {
304 get: self.get.saturating_sub(previous.get),
305 list: self.list.saturating_sub(previous.list),
306 put: self.put.saturating_sub(previous.put),
307 delete: self.delete.saturating_sub(previous.delete),
308 txn: self.txn.saturating_sub(previous.txn),
309 lease: self.lease.saturating_sub(previous.lease),
310 watch: self.watch.saturating_sub(previous.watch),
311 tier0: self.tier0.saturating_sub(previous.tier0),
312 }
313 }
314}
315
316pub fn request_mix_snapshot() -> RequestMixSnapshot {
317 let reg = metrics();
318 if !reg.enabled() {
319 return RequestMixSnapshot::default();
320 }
321 RequestMixSnapshot {
322 get: reg.request_get_total.load(Ordering::Relaxed),
323 list: reg.request_list_total.load(Ordering::Relaxed),
324 put: reg.request_put_total.load(Ordering::Relaxed),
325 delete: reg.request_delete_total.load(Ordering::Relaxed),
326 txn: reg.request_txn_total.load(Ordering::Relaxed),
327 lease: reg.request_lease_total.load(Ordering::Relaxed),
328 watch: reg.request_watch_total.load(Ordering::Relaxed),
329 tier0: reg.request_tier0_total.load(Ordering::Relaxed),
330 }
331}
332
333pub fn set_enabled(enabled: bool) {
334 metrics().enabled.store(enabled, Ordering::Relaxed);
335}
336
337pub fn observe_put_queue_wait_ms(value_ms: u64) {
338 let reg = metrics();
339 if !reg.enabled() {
340 return;
341 }
342 reg.put_queue_wait_ms.observe(value_ms);
343}
344
345pub fn observe_put_queue_wait_ms_by_priority(value_ms: u64, tier0: bool) {
346 let reg = metrics();
347 if !reg.enabled() {
348 return;
349 }
350 if tier0 {
351 reg.put_queue_wait_tier0_ms.observe(value_ms);
352 } else {
353 reg.put_queue_wait_normal_ms.observe(value_ms);
354 }
355}
356
357pub fn observe_put_raft_client_write_ms(value_ms: u64) {
358 let reg = metrics();
359 if !reg.enabled() {
360 return;
361 }
362 reg.put_raft_write_ms.observe(value_ms);
363}
364
365pub fn observe_put_quorum_ack_ms(value_ms: u64) {
366 let reg = metrics();
367 if !reg.enabled() {
368 return;
369 }
370 reg.put_quorum_ack_ms.observe(value_ms);
371 reg.latest_quorum_ack_ms.store(value_ms, Ordering::Relaxed);
372 reg.quorum_ack_observations.fetch_add(1, Ordering::Relaxed);
373}
374
375pub fn observe_put_batch_size(size: usize) {
376 let reg = metrics();
377 if !reg.enabled() {
378 return;
379 }
380 reg.put_batch_size.observe(size as u64);
381}
382
383pub fn inc_put_batches() {
384 let reg = metrics();
385 if !reg.enabled() {
386 return;
387 }
388 reg.put_batches_total.fetch_add(1, Ordering::Relaxed);
389}
390
391pub fn add_put_batch_requests(count: usize) {
392 let reg = metrics();
393 if !reg.enabled() {
394 return;
395 }
396 reg.put_batch_requests_total
397 .fetch_add(count as u64, Ordering::Relaxed);
398}
399
400pub fn inc_put_tier0_enqueued() {
401 let reg = metrics();
402 if !reg.enabled() {
403 return;
404 }
405 reg.put_tier0_enqueued_total.fetch_add(1, Ordering::Relaxed);
406}
407
408pub fn inc_put_tier0_dispatch_events() {
409 let reg = metrics();
410 if !reg.enabled() {
411 return;
412 }
413 reg.put_tier0_dispatch_total.fetch_add(1, Ordering::Relaxed);
414}
415
416pub fn inc_put_tier0_bypass_write_pressure() {
417 let reg = metrics();
418 if !reg.enabled() {
419 return;
420 }
421 reg.put_tier0_bypass_write_pressure_total
422 .fetch_add(1, Ordering::Relaxed);
423}
424
425pub fn set_put_inflight_requests(count: usize) {
426 let reg = metrics();
427 if !reg.enabled() {
428 return;
429 }
430 reg.put_inflight_requests
431 .store(count as u64, Ordering::Relaxed);
432}
433
434pub fn set_put_tier0_queue_depth(count: usize) {
435 let reg = metrics();
436 if !reg.enabled() {
437 return;
438 }
439 reg.put_tier0_queue_depth
440 .store(count as u64, Ordering::Relaxed);
441}
442
443pub fn set_put_normal_queue_depth(count: usize) {
444 let reg = metrics();
445 if !reg.enabled() {
446 return;
447 }
448 reg.put_normal_queue_depth
449 .store(count as u64, Ordering::Relaxed);
450}
451
452pub fn current_put_inflight_requests() -> u64 {
453 let reg = metrics();
454 if !reg.enabled() {
455 return 0;
456 }
457 reg.put_inflight_requests.load(Ordering::Relaxed)
458}
459
460pub fn set_wal_effective_linger_us(value: u64) {
461 let reg = metrics();
462 if !reg.enabled() {
463 return;
464 }
465 reg.wal_effective_linger_us.store(value, Ordering::Relaxed);
466}
467
468pub fn set_wal_queue_depth(depth: usize) {
469 let reg = metrics();
470 reg.wal_queue_depth.store(depth as u64, Ordering::Relaxed);
471}
472
473pub fn set_wal_queue_bytes(bytes: usize) {
474 let reg = metrics();
475 reg.wal_queue_bytes.store(bytes as u64, Ordering::Relaxed);
476}
477
478pub fn current_wal_queue_depth() -> u64 {
479 metrics().wal_queue_depth.load(Ordering::Relaxed)
480}
481
482pub fn current_wal_queue_bytes() -> u64 {
483 metrics().wal_queue_bytes.load(Ordering::Relaxed)
484}
485
486pub fn set_lsm_synth_l0_files(value: u64) {
487 let reg = metrics();
488 if !reg.enabled() {
489 return;
490 }
491 reg.lsm_synth_l0_files.store(value, Ordering::Relaxed);
492}
493
494pub fn observe_write_stall_delay_ms(value_ms: u64) {
495 let reg = metrics();
496 if !reg.enabled() {
497 return;
498 }
499 reg.write_stall_delay_ms.observe(value_ms);
500 reg.write_stall_events_total.fetch_add(1, Ordering::Relaxed);
501}
502
503pub fn inc_write_stall_band_5_events() {
504 let reg = metrics();
505 if !reg.enabled() {
506 return;
507 }
508 reg.write_stall_band_5_events_total
509 .fetch_add(1, Ordering::Relaxed);
510}
511
512pub fn inc_write_stall_band_6_events() {
513 let reg = metrics();
514 if !reg.enabled() {
515 return;
516 }
517 reg.write_stall_band_6_events_total
518 .fetch_add(1, Ordering::Relaxed);
519}
520
521pub fn inc_write_stall_band_7_plus_events() {
522 let reg = metrics();
523 if !reg.enabled() {
524 return;
525 }
526 reg.write_stall_band_7_plus_events_total
527 .fetch_add(1, Ordering::Relaxed);
528}
529
530pub fn inc_write_reject_events() {
531 let reg = metrics();
532 if !reg.enabled() {
533 return;
534 }
535 reg.write_reject_events_total
536 .fetch_add(1, Ordering::Relaxed);
537}
538
539pub fn set_bg_io_tokens_available(tokens: u64) {
540 let reg = metrics();
541 if !reg.enabled() {
542 return;
543 }
544 reg.bg_io_tokens_available.store(tokens, Ordering::Relaxed);
545}
546
547pub fn set_bg_io_sqe_tokens_available(tokens: u64) {
548 let reg = metrics();
549 if !reg.enabled() {
550 return;
551 }
552 reg.bg_io_sqe_tokens_available
553 .store(tokens, Ordering::Relaxed);
554}
555
556pub fn observe_bg_io_throttle_wait_ms(value_ms: u64) {
557 let reg = metrics();
558 if !reg.enabled() {
559 return;
560 }
561 reg.bg_io_throttle_wait_ms.observe(value_ms);
562 reg.bg_io_throttle_events_total
563 .fetch_add(1, Ordering::Relaxed);
564}
565
566pub fn observe_bg_io_sqe_wait_ms(value_ms: u64) {
567 let reg = metrics();
568 if !reg.enabled() {
569 return;
570 }
571 reg.bg_io_sqe_wait_ms.observe(value_ms);
572 reg.bg_io_sqe_throttle_events_total
573 .fetch_add(1, Ordering::Relaxed);
574}
575
576pub fn inc_list_prefix_filter_skips() {
577 let reg = metrics();
578 if !reg.enabled() {
579 return;
580 }
581 reg.list_prefix_filter_skips_total
582 .fetch_add(1, Ordering::Relaxed);
583}
584
585pub fn inc_list_prefix_filter_hits() {
586 let reg = metrics();
587 if !reg.enabled() {
588 return;
589 }
590 reg.list_prefix_filter_hits_total
591 .fetch_add(1, Ordering::Relaxed);
592}
593
594pub fn inc_list_revision_filter_skips() {
595 let reg = metrics();
596 if !reg.enabled() {
597 return;
598 }
599 reg.list_revision_filter_skips_total
600 .fetch_add(1, Ordering::Relaxed);
601}
602
603pub fn inc_list_revision_filter_hits() {
604 let reg = metrics();
605 if !reg.enabled() {
606 return;
607 }
608 reg.list_revision_filter_hits_total
609 .fetch_add(1, Ordering::Relaxed);
610}
611
612pub fn inc_list_prefetch_hits() {
613 let reg = metrics();
614 if !reg.enabled() {
615 return;
616 }
617 reg.list_prefetch_hits_total.fetch_add(1, Ordering::Relaxed);
618}
619
620pub fn inc_list_prefetch_misses() {
621 let reg = metrics();
622 if !reg.enabled() {
623 return;
624 }
625 reg.list_prefetch_misses_total
626 .fetch_add(1, Ordering::Relaxed);
627}
628
629pub fn inc_read_isolation_dispatch() {
630 let reg = metrics();
631 if !reg.enabled() {
632 return;
633 }
634 reg.read_isolation_dispatch_total
635 .fetch_add(1, Ordering::Relaxed);
636}
637
638pub fn inc_read_isolation_failures() {
639 let reg = metrics();
640 if !reg.enabled() {
641 return;
642 }
643 reg.read_isolation_failures_total
644 .fetch_add(1, Ordering::Relaxed);
645}
646
647pub fn inc_read_quorum_checks() {
648 let reg = metrics();
649 if !reg.enabled() {
650 return;
651 }
652 reg.read_quorum_checks_total.fetch_add(1, Ordering::Relaxed);
653}
654
655pub fn inc_read_quorum_failures() {
656 let reg = metrics();
657 if !reg.enabled() {
658 return;
659 }
660 reg.read_quorum_failures_total
661 .fetch_add(1, Ordering::Relaxed);
662}
663
664pub fn inc_read_quorum_internal() {
665 let reg = metrics();
666 if !reg.enabled() {
667 return;
668 }
669 reg.read_quorum_internal_total
670 .fetch_add(1, Ordering::Relaxed);
671}
672
673pub fn inc_transport_closed_conn_unavailable() {
674 let reg = metrics();
675 if !reg.enabled() {
676 return;
677 }
678 reg.transport_closed_conn_unavailable_total
679 .fetch_add(1, Ordering::Relaxed);
680}
681
682pub fn inc_forward_retry_attempts() {
683 let reg = metrics();
684 if !reg.enabled() {
685 return;
686 }
687 reg.forward_retry_attempts_total
688 .fetch_add(1, Ordering::Relaxed);
689}
690
691pub fn inc_gateway_read_ticket_hits() {
692 let reg = metrics();
693 if !reg.enabled() {
694 return;
695 }
696 reg.gateway_read_ticket_hits_total
697 .fetch_add(1, Ordering::Relaxed);
698}
699
700pub fn inc_gateway_read_ticket_misses() {
701 let reg = metrics();
702 if !reg.enabled() {
703 return;
704 }
705 reg.gateway_read_ticket_misses_total
706 .fetch_add(1, Ordering::Relaxed);
707}
708
709pub fn inc_gateway_singleflight_leader() {
710 let reg = metrics();
711 if !reg.enabled() {
712 return;
713 }
714 reg.gateway_singleflight_leader_total
715 .fetch_add(1, Ordering::Relaxed);
716}
717
718pub fn inc_gateway_singleflight_waiter() {
719 let reg = metrics();
720 if !reg.enabled() {
721 return;
722 }
723 reg.gateway_singleflight_waiter_total
724 .fetch_add(1, Ordering::Relaxed);
725}
726
727pub fn inc_gateway_singleflight_overflow() {
728 let reg = metrics();
729 if !reg.enabled() {
730 return;
731 }
732 reg.gateway_singleflight_overflow_total
733 .fetch_add(1, Ordering::Relaxed);
734}
735
736pub fn inc_gateway_singleflight_waiter_timeout() {
737 let reg = metrics();
738 if !reg.enabled() {
739 return;
740 }
741 reg.gateway_singleflight_waiter_timeouts_total
742 .fetch_add(1, Ordering::Relaxed);
743}
744
745pub fn inc_request_get_total() {
746 let reg = metrics();
747 if !reg.enabled() {
748 return;
749 }
750 reg.request_get_total.fetch_add(1, Ordering::Relaxed);
751}
752
753pub fn inc_request_list_total() {
754 let reg = metrics();
755 if !reg.enabled() {
756 return;
757 }
758 reg.request_list_total.fetch_add(1, Ordering::Relaxed);
759}
760
761pub fn inc_request_put_total() {
762 let reg = metrics();
763 if !reg.enabled() {
764 return;
765 }
766 reg.request_put_total.fetch_add(1, Ordering::Relaxed);
767}
768
769pub fn inc_request_delete_total() {
770 let reg = metrics();
771 if !reg.enabled() {
772 return;
773 }
774 reg.request_delete_total.fetch_add(1, Ordering::Relaxed);
775}
776
777pub fn inc_request_txn_total() {
778 let reg = metrics();
779 if !reg.enabled() {
780 return;
781 }
782 reg.request_txn_total.fetch_add(1, Ordering::Relaxed);
783}
784
785pub fn inc_request_lease_total() {
786 let reg = metrics();
787 if !reg.enabled() {
788 return;
789 }
790 reg.request_lease_total.fetch_add(1, Ordering::Relaxed);
791}
792
793pub fn inc_request_watch_total() {
794 let reg = metrics();
795 if !reg.enabled() {
796 return;
797 }
798 reg.request_watch_total.fetch_add(1, Ordering::Relaxed);
799}
800
801pub fn inc_request_tier0_total() {
802 let reg = metrics();
803 if !reg.enabled() {
804 return;
805 }
806 reg.request_tier0_total.fetch_add(1, Ordering::Relaxed);
807}
808
809pub fn inc_profile_switch_total() {
810 let reg = metrics();
811 if !reg.enabled() {
812 return;
813 }
814 reg.profile_switch_total.fetch_add(1, Ordering::Relaxed);
815}
816
817pub fn set_profile_active(profile: &str) {
818 let reg = metrics();
819 if !reg.enabled() {
820 return;
821 }
822 let (k8s, omni, gateway, auto) = match profile {
823 "kubernetes" => (1, 0, 0, 0),
824 "omni" => (0, 1, 0, 0),
825 "gateway" => (0, 0, 1, 0),
826 _ => (0, 0, 0, 1),
827 };
828 reg.profile_active_kubernetes.store(k8s, Ordering::Relaxed);
829 reg.profile_active_omni.store(omni, Ordering::Relaxed);
830 reg.profile_active_gateway.store(gateway, Ordering::Relaxed);
831 reg.profile_active_auto.store(auto, Ordering::Relaxed);
832}
833
834pub fn set_profile_applied_put_max_requests(value: usize) {
835 let reg = metrics();
836 if !reg.enabled() {
837 return;
838 }
839 reg.profile_applied_put_max_requests
840 .store(value as u64, Ordering::Relaxed);
841}
842
843pub fn set_profile_applied_put_linger_us(value: u64) {
844 let reg = metrics();
845 if !reg.enabled() {
846 return;
847 }
848 reg.profile_applied_put_linger_us
849 .store(value, Ordering::Relaxed);
850}
851
852pub fn set_profile_applied_prefetch_entries(value: usize) {
853 let reg = metrics();
854 if !reg.enabled() {
855 return;
856 }
857 reg.profile_applied_prefetch_entries
858 .store(value as u64, Ordering::Relaxed);
859}
860
861pub fn set_profile_applied_bg_io_tokens_per_sec(value: u64) {
862 let reg = metrics();
863 if !reg.enabled() {
864 return;
865 }
866 reg.profile_applied_bg_io_tokens_per_sec
867 .store(value, Ordering::Relaxed);
868}
869
870pub fn latest_put_quorum_ack_ms() -> Option<u64> {
871 let reg = metrics();
872 if !reg.enabled() {
873 return None;
874 }
875 if reg.quorum_ack_observations.load(Ordering::Relaxed) == 0 {
876 None
877 } else {
878 Some(reg.latest_quorum_ack_ms.load(Ordering::Relaxed))
879 }
880}
881
882pub fn render_prometheus() -> String {
883 let reg = metrics();
884 let mut out = String::new();
885 if !reg.enabled() {
886 let _ = writeln!(&mut out, "# astra metrics disabled");
887 return out;
888 }
889
890 reg.put_queue_wait_ms.render(
891 &mut out,
892 "astra_put_queue_wait_seconds",
893 "Queue wait time between enqueue and batch dispatch for put requests.",
894 );
895 reg.put_queue_wait_tier0_ms.render(
896 &mut out,
897 "astra_put_queue_wait_tier0_seconds",
898 "Queue wait time between enqueue and batch dispatch for tier0 put requests.",
899 );
900 reg.put_queue_wait_normal_ms.render(
901 &mut out,
902 "astra_put_queue_wait_normal_seconds",
903 "Queue wait time between enqueue and batch dispatch for normal put requests.",
904 );
905 reg.put_raft_write_ms.render(
906 &mut out,
907 "astra_put_raft_client_write_seconds",
908 "Duration of raft client_write for put batches.",
909 );
910 reg.put_quorum_ack_ms.render(
911 &mut out,
912 "astra_put_quorum_ack_seconds",
913 "Time from batch submit to commit advancement signal.",
914 );
915 reg.put_batch_size.render(
916 &mut out,
917 "astra_put_batch_size",
918 "Number of put operations per dispatched batch.",
919 );
920 reg.bg_io_throttle_wait_ms.render(
921 &mut out,
922 "astra_bg_io_throttle_wait_seconds",
923 "Time spent waiting for background IO token-bucket budget.",
924 );
925 reg.bg_io_sqe_wait_ms.render(
926 &mut out,
927 "astra_bg_io_sqe_wait_seconds",
928 "Time spent waiting for background SQE operation budget.",
929 );
930 reg.write_stall_delay_ms.render(
931 &mut out,
932 "astra_write_stall_delay_seconds",
933 "Write stall delay injected by L0 pressure controller.",
934 );
935
936 let _ = writeln!(
937 &mut out,
938 "# HELP astra_put_batches_total Total dispatched put batches."
939 );
940 let _ = writeln!(&mut out, "# TYPE astra_put_batches_total counter");
941 let _ = writeln!(
942 &mut out,
943 "astra_put_batches_total {}",
944 reg.put_batches_total.load(Ordering::Relaxed)
945 );
946
947 let _ = writeln!(
948 &mut out,
949 "# HELP astra_put_batch_requests_total Total put requests dispatched through the batcher."
950 );
951 let _ = writeln!(&mut out, "# TYPE astra_put_batch_requests_total counter");
952 let _ = writeln!(
953 &mut out,
954 "astra_put_batch_requests_total {}",
955 reg.put_batch_requests_total.load(Ordering::Relaxed)
956 );
957 let _ = writeln!(
958 &mut out,
959 "# HELP astra_put_tier0_enqueued_total Total tier0 put requests enqueued."
960 );
961 let _ = writeln!(&mut out, "# TYPE astra_put_tier0_enqueued_total counter");
962 let _ = writeln!(
963 &mut out,
964 "astra_put_tier0_enqueued_total {}",
965 reg.put_tier0_enqueued_total.load(Ordering::Relaxed)
966 );
967 let _ = writeln!(
968 &mut out,
969 "# HELP astra_put_tier0_dispatch_total Total tier0 batches dispatched."
970 );
971 let _ = writeln!(&mut out, "# TYPE astra_put_tier0_dispatch_total counter");
972 let _ = writeln!(
973 &mut out,
974 "astra_put_tier0_dispatch_total {}",
975 reg.put_tier0_dispatch_total.load(Ordering::Relaxed)
976 );
977 let _ = writeln!(
978 &mut out,
979 "# HELP astra_put_tier0_bypass_write_pressure_total Total tier0 requests bypassing write-pressure control."
980 );
981 let _ = writeln!(
982 &mut out,
983 "# TYPE astra_put_tier0_bypass_write_pressure_total counter"
984 );
985 let _ = writeln!(
986 &mut out,
987 "astra_put_tier0_bypass_write_pressure_total {}",
988 reg.put_tier0_bypass_write_pressure_total
989 .load(Ordering::Relaxed)
990 );
991
992 let _ = writeln!(
993 &mut out,
994 "# HELP astra_put_inflight_requests Current estimated in-flight put requests (queued + dispatched)."
995 );
996 let _ = writeln!(&mut out, "# TYPE astra_put_inflight_requests gauge");
997 let _ = writeln!(
998 &mut out,
999 "astra_put_inflight_requests {}",
1000 reg.put_inflight_requests.load(Ordering::Relaxed)
1001 );
1002 let _ = writeln!(
1003 &mut out,
1004 "# HELP astra_put_tier0_queue_depth Current estimated queued tier0 put requests."
1005 );
1006 let _ = writeln!(&mut out, "# TYPE astra_put_tier0_queue_depth gauge");
1007 let _ = writeln!(
1008 &mut out,
1009 "astra_put_tier0_queue_depth {}",
1010 reg.put_tier0_queue_depth.load(Ordering::Relaxed)
1011 );
1012 let _ = writeln!(
1013 &mut out,
1014 "# HELP astra_put_normal_queue_depth Current estimated queued normal put requests."
1015 );
1016 let _ = writeln!(&mut out, "# TYPE astra_put_normal_queue_depth gauge");
1017 let _ = writeln!(
1018 &mut out,
1019 "astra_put_normal_queue_depth {}",
1020 reg.put_normal_queue_depth.load(Ordering::Relaxed)
1021 );
1022
1023 let _ = writeln!(
1024 &mut out,
1025 "# HELP astra_wal_effective_linger_microseconds Effective WAL linger currently applied."
1026 );
1027 let _ = writeln!(
1028 &mut out,
1029 "# TYPE astra_wal_effective_linger_microseconds gauge"
1030 );
1031 let _ = writeln!(
1032 &mut out,
1033 "astra_wal_effective_linger_microseconds {}",
1034 reg.wal_effective_linger_us.load(Ordering::Relaxed)
1035 );
1036
1037 let _ = writeln!(
1038 &mut out,
1039 "# HELP astra_wal_queue_depth Current queued WAL frames waiting for flush."
1040 );
1041 let _ = writeln!(&mut out, "# TYPE astra_wal_queue_depth gauge");
1042 let _ = writeln!(
1043 &mut out,
1044 "astra_wal_queue_depth {}",
1045 reg.wal_queue_depth.load(Ordering::Relaxed)
1046 );
1047
1048 let _ = writeln!(
1049 &mut out,
1050 "# HELP astra_wal_queue_bytes Current queued WAL payload bytes waiting for flush."
1051 );
1052 let _ = writeln!(&mut out, "# TYPE astra_wal_queue_bytes gauge");
1053 let _ = writeln!(
1054 &mut out,
1055 "astra_wal_queue_bytes {}",
1056 reg.wal_queue_bytes.load(Ordering::Relaxed)
1057 );
1058
1059 let _ = writeln!(
1060 &mut out,
1061 "# HELP astra_lsm_synth_l0_files Synthetic L0 file pressure estimate derived from WAL queues."
1062 );
1063 let _ = writeln!(&mut out, "# TYPE astra_lsm_synth_l0_files gauge");
1064 let _ = writeln!(
1065 &mut out,
1066 "astra_lsm_synth_l0_files {}",
1067 reg.lsm_synth_l0_files.load(Ordering::Relaxed)
1068 );
1069
1070 let _ = writeln!(
1071 &mut out,
1072 "# HELP astra_bg_io_tokens_available Current available tokens in the background IO token bucket."
1073 );
1074 let _ = writeln!(&mut out, "# TYPE astra_bg_io_tokens_available gauge");
1075 let _ = writeln!(
1076 &mut out,
1077 "astra_bg_io_tokens_available {}",
1078 reg.bg_io_tokens_available.load(Ordering::Relaxed)
1079 );
1080
1081 let _ = writeln!(
1082 &mut out,
1083 "# HELP astra_bg_io_sqe_tokens_available Current available tokens in the background SQE token bucket."
1084 );
1085 let _ = writeln!(&mut out, "# TYPE astra_bg_io_sqe_tokens_available gauge");
1086 let _ = writeln!(
1087 &mut out,
1088 "astra_bg_io_sqe_tokens_available {}",
1089 reg.bg_io_sqe_tokens_available.load(Ordering::Relaxed)
1090 );
1091
1092 let _ = writeln!(
1093 &mut out,
1094 "# HELP astra_bg_io_throttle_events_total Total background IO throttle wait events."
1095 );
1096 let _ = writeln!(&mut out, "# TYPE astra_bg_io_throttle_events_total counter");
1097 let _ = writeln!(
1098 &mut out,
1099 "astra_bg_io_throttle_events_total {}",
1100 reg.bg_io_throttle_events_total.load(Ordering::Relaxed)
1101 );
1102
1103 let _ = writeln!(
1104 &mut out,
1105 "# HELP astra_bg_io_sqe_throttle_events_total Total background SQE throttle wait events."
1106 );
1107 let _ = writeln!(
1108 &mut out,
1109 "# TYPE astra_bg_io_sqe_throttle_events_total counter"
1110 );
1111 let _ = writeln!(
1112 &mut out,
1113 "astra_bg_io_sqe_throttle_events_total {}",
1114 reg.bg_io_sqe_throttle_events_total.load(Ordering::Relaxed)
1115 );
1116
1117 let _ = writeln!(
1118 &mut out,
1119 "# HELP astra_write_stall_events_total Total write requests delayed by L0 pressure control."
1120 );
1121 let _ = writeln!(&mut out, "# TYPE astra_write_stall_events_total counter");
1122 let _ = writeln!(
1123 &mut out,
1124 "astra_write_stall_events_total {}",
1125 reg.write_stall_events_total.load(Ordering::Relaxed)
1126 );
1127
1128 let _ = writeln!(
1129 &mut out,
1130 "# HELP astra_write_reject_events_total Total write requests rejected by L0 pressure control."
1131 );
1132 let _ = writeln!(&mut out, "# TYPE astra_write_reject_events_total counter");
1133 let _ = writeln!(
1134 &mut out,
1135 "astra_write_reject_events_total {}",
1136 reg.write_reject_events_total.load(Ordering::Relaxed)
1137 );
1138
1139 let _ = writeln!(
1140 &mut out,
1141 "# HELP astra_write_stall_band_5_events_total Total writes delayed by the L0==5 pressure band."
1142 );
1143 let _ = writeln!(
1144 &mut out,
1145 "# TYPE astra_write_stall_band_5_events_total counter"
1146 );
1147 let _ = writeln!(
1148 &mut out,
1149 "astra_write_stall_band_5_events_total {}",
1150 reg.write_stall_band_5_events_total.load(Ordering::Relaxed)
1151 );
1152
1153 let _ = writeln!(
1154 &mut out,
1155 "# HELP astra_write_stall_band_6_events_total Total writes delayed by the L0==6 pressure band."
1156 );
1157 let _ = writeln!(
1158 &mut out,
1159 "# TYPE astra_write_stall_band_6_events_total counter"
1160 );
1161 let _ = writeln!(
1162 &mut out,
1163 "astra_write_stall_band_6_events_total {}",
1164 reg.write_stall_band_6_events_total.load(Ordering::Relaxed)
1165 );
1166
1167 let _ = writeln!(
1168 &mut out,
1169 "# HELP astra_write_stall_band_7_plus_events_total Total writes delayed by the L0>=7 pressure band."
1170 );
1171 let _ = writeln!(
1172 &mut out,
1173 "# TYPE astra_write_stall_band_7_plus_events_total counter"
1174 );
1175 let _ = writeln!(
1176 &mut out,
1177 "astra_write_stall_band_7_plus_events_total {}",
1178 reg.write_stall_band_7_plus_events_total
1179 .load(Ordering::Relaxed)
1180 );
1181
1182 let _ = writeln!(
1183 &mut out,
1184 "# HELP astra_list_prefix_filter_skips_total LIST requests skipped by prefix negative filter."
1185 );
1186 let _ = writeln!(
1187 &mut out,
1188 "# TYPE astra_list_prefix_filter_skips_total counter"
1189 );
1190 let _ = writeln!(
1191 &mut out,
1192 "astra_list_prefix_filter_skips_total {}",
1193 reg.list_prefix_filter_skips_total.load(Ordering::Relaxed)
1194 );
1195
1196 let _ = writeln!(
1197 &mut out,
1198 "# HELP astra_list_prefix_filter_hits_total LIST requests processed after prefix filter positive hit."
1199 );
1200 let _ = writeln!(
1201 &mut out,
1202 "# TYPE astra_list_prefix_filter_hits_total counter"
1203 );
1204 let _ = writeln!(
1205 &mut out,
1206 "astra_list_prefix_filter_hits_total {}",
1207 reg.list_prefix_filter_hits_total.load(Ordering::Relaxed)
1208 );
1209
1210 let _ = writeln!(
1211 &mut out,
1212 "# HELP astra_list_revision_filter_skips_total LIST requests skipped by prefix+revision filter."
1213 );
1214 let _ = writeln!(
1215 &mut out,
1216 "# TYPE astra_list_revision_filter_skips_total counter"
1217 );
1218 let _ = writeln!(
1219 &mut out,
1220 "astra_list_revision_filter_skips_total {}",
1221 reg.list_revision_filter_skips_total.load(Ordering::Relaxed)
1222 );
1223
1224 let _ = writeln!(
1225 &mut out,
1226 "# HELP astra_list_revision_filter_hits_total LIST requests processed after prefix+revision filter hit."
1227 );
1228 let _ = writeln!(
1229 &mut out,
1230 "# TYPE astra_list_revision_filter_hits_total counter"
1231 );
1232 let _ = writeln!(
1233 &mut out,
1234 "astra_list_revision_filter_hits_total {}",
1235 reg.list_revision_filter_hits_total.load(Ordering::Relaxed)
1236 );
1237
1238 let _ = writeln!(
1239 &mut out,
1240 "# HELP astra_list_prefetch_hits_total LIST prefetch cache hits."
1241 );
1242 let _ = writeln!(&mut out, "# TYPE astra_list_prefetch_hits_total counter");
1243 let _ = writeln!(
1244 &mut out,
1245 "astra_list_prefetch_hits_total {}",
1246 reg.list_prefetch_hits_total.load(Ordering::Relaxed)
1247 );
1248
1249 let _ = writeln!(
1250 &mut out,
1251 "# HELP astra_list_prefetch_misses_total LIST prefetch cache misses."
1252 );
1253 let _ = writeln!(&mut out, "# TYPE astra_list_prefetch_misses_total counter");
1254 let _ = writeln!(
1255 &mut out,
1256 "astra_list_prefetch_misses_total {}",
1257 reg.list_prefetch_misses_total.load(Ordering::Relaxed)
1258 );
1259
1260 let _ = writeln!(
1261 &mut out,
1262 "# HELP astra_read_isolation_dispatch_total Total read requests routed through isolated read lane."
1263 );
1264 let _ = writeln!(
1265 &mut out,
1266 "# TYPE astra_read_isolation_dispatch_total counter"
1267 );
1268 let _ = writeln!(
1269 &mut out,
1270 "astra_read_isolation_dispatch_total {}",
1271 reg.read_isolation_dispatch_total.load(Ordering::Relaxed)
1272 );
1273
1274 let _ = writeln!(
1275 &mut out,
1276 "# HELP astra_read_isolation_failures_total Total isolated read dispatch failures that required inline fallback."
1277 );
1278 let _ = writeln!(
1279 &mut out,
1280 "# TYPE astra_read_isolation_failures_total counter"
1281 );
1282 let _ = writeln!(
1283 &mut out,
1284 "astra_read_isolation_failures_total {}",
1285 reg.read_isolation_failures_total.load(Ordering::Relaxed)
1286 );
1287 let _ = writeln!(
1288 &mut out,
1289 "# HELP astra_read_quorum_checks_total Total linearizable read quorum checks attempted."
1290 );
1291 let _ = writeln!(&mut out, "# TYPE astra_read_quorum_checks_total counter");
1292 let _ = writeln!(
1293 &mut out,
1294 "astra_read_quorum_checks_total {}",
1295 reg.read_quorum_checks_total.load(Ordering::Relaxed)
1296 );
1297 let _ = writeln!(
1298 &mut out,
1299 "# HELP astra_read_quorum_failures_total Total linearizable read quorum check failures."
1300 );
1301 let _ = writeln!(&mut out, "# TYPE astra_read_quorum_failures_total counter");
1302 let _ = writeln!(
1303 &mut out,
1304 "astra_read_quorum_failures_total {}",
1305 reg.read_quorum_failures_total.load(Ordering::Relaxed)
1306 );
1307 let _ = writeln!(
1308 &mut out,
1309 "# HELP astra_read_quorum_internal_total Total quorum-related internal read errors."
1310 );
1311 let _ = writeln!(&mut out, "# TYPE astra_read_quorum_internal_total counter");
1312 let _ = writeln!(
1313 &mut out,
1314 "astra_read_quorum_internal_total {}",
1315 reg.read_quorum_internal_total.load(Ordering::Relaxed)
1316 );
1317 let _ = writeln!(
1318 &mut out,
1319 "# HELP astra_transport_closed_conn_unavailable_total Total unavailable responses attributed to closed transport connections."
1320 );
1321 let _ = writeln!(
1322 &mut out,
1323 "# TYPE astra_transport_closed_conn_unavailable_total counter"
1324 );
1325 let _ = writeln!(
1326 &mut out,
1327 "astra_transport_closed_conn_unavailable_total {}",
1328 reg.transport_closed_conn_unavailable_total
1329 .load(Ordering::Relaxed)
1330 );
1331 let _ = writeln!(
1332 &mut out,
1333 "# HELP astra_forward_retry_attempts_total Total forwarded RPC retry attempts."
1334 );
1335 let _ = writeln!(
1336 &mut out,
1337 "# TYPE astra_forward_retry_attempts_total counter"
1338 );
1339 let _ = writeln!(
1340 &mut out,
1341 "astra_forward_retry_attempts_total {}",
1342 reg.forward_retry_attempts_total.load(Ordering::Relaxed)
1343 );
1344 let _ = writeln!(
1345 &mut out,
1346 "# HELP astra_gateway_read_ticket_hits_total Total gateway read requests that reused an active read ticket."
1347 );
1348 let _ = writeln!(
1349 &mut out,
1350 "# TYPE astra_gateway_read_ticket_hits_total counter"
1351 );
1352 let _ = writeln!(
1353 &mut out,
1354 "astra_gateway_read_ticket_hits_total {}",
1355 reg.gateway_read_ticket_hits_total.load(Ordering::Relaxed)
1356 );
1357 let _ = writeln!(
1358 &mut out,
1359 "# HELP astra_gateway_read_ticket_misses_total Total gateway read requests that required a fresh quorum check."
1360 );
1361 let _ = writeln!(
1362 &mut out,
1363 "# TYPE astra_gateway_read_ticket_misses_total counter"
1364 );
1365 let _ = writeln!(
1366 &mut out,
1367 "astra_gateway_read_ticket_misses_total {}",
1368 reg.gateway_read_ticket_misses_total.load(Ordering::Relaxed)
1369 );
1370 let _ = writeln!(
1371 &mut out,
1372 "# HELP astra_gateway_singleflight_leader_total Total gateway read requests elected as singleflight leaders."
1373 );
1374 let _ = writeln!(
1375 &mut out,
1376 "# TYPE astra_gateway_singleflight_leader_total counter"
1377 );
1378 let _ = writeln!(
1379 &mut out,
1380 "astra_gateway_singleflight_leader_total {}",
1381 reg.gateway_singleflight_leader_total
1382 .load(Ordering::Relaxed)
1383 );
1384 let _ = writeln!(
1385 &mut out,
1386 "# HELP astra_gateway_singleflight_waiter_total Total gateway read requests collapsed behind an in-flight leader request."
1387 );
1388 let _ = writeln!(
1389 &mut out,
1390 "# TYPE astra_gateway_singleflight_waiter_total counter"
1391 );
1392 let _ = writeln!(
1393 &mut out,
1394 "astra_gateway_singleflight_waiter_total {}",
1395 reg.gateway_singleflight_waiter_total
1396 .load(Ordering::Relaxed)
1397 );
1398 let _ = writeln!(
1399 &mut out,
1400 "# HELP astra_gateway_singleflight_overflow_total Total gateway read requests that bypassed singleflight due to waiter cap."
1401 );
1402 let _ = writeln!(
1403 &mut out,
1404 "# TYPE astra_gateway_singleflight_overflow_total counter"
1405 );
1406 let _ = writeln!(
1407 &mut out,
1408 "astra_gateway_singleflight_overflow_total {}",
1409 reg.gateway_singleflight_overflow_total
1410 .load(Ordering::Relaxed)
1411 );
1412 let _ = writeln!(
1413 &mut out,
1414 "# HELP astra_gateway_singleflight_waiter_timeouts_total Total gateway waiter requests that timed out waiting for singleflight leader completion."
1415 );
1416 let _ = writeln!(
1417 &mut out,
1418 "# TYPE astra_gateway_singleflight_waiter_timeouts_total counter"
1419 );
1420 let _ = writeln!(
1421 &mut out,
1422 "astra_gateway_singleflight_waiter_timeouts_total {}",
1423 reg.gateway_singleflight_waiter_timeouts_total
1424 .load(Ordering::Relaxed)
1425 );
1426
1427 let _ = writeln!(
1428 &mut out,
1429 "# HELP astra_request_get_total Total GET-like range requests."
1430 );
1431 let _ = writeln!(&mut out, "# TYPE astra_request_get_total counter");
1432 let _ = writeln!(
1433 &mut out,
1434 "astra_request_get_total {}",
1435 reg.request_get_total.load(Ordering::Relaxed)
1436 );
1437 let _ = writeln!(
1438 &mut out,
1439 "# HELP astra_request_list_total Total LIST/prefix range requests."
1440 );
1441 let _ = writeln!(&mut out, "# TYPE astra_request_list_total counter");
1442 let _ = writeln!(
1443 &mut out,
1444 "astra_request_list_total {}",
1445 reg.request_list_total.load(Ordering::Relaxed)
1446 );
1447 let _ = writeln!(
1448 &mut out,
1449 "# HELP astra_request_put_total Total put requests."
1450 );
1451 let _ = writeln!(&mut out, "# TYPE astra_request_put_total counter");
1452 let _ = writeln!(
1453 &mut out,
1454 "astra_request_put_total {}",
1455 reg.request_put_total.load(Ordering::Relaxed)
1456 );
1457 let _ = writeln!(
1458 &mut out,
1459 "# HELP astra_request_delete_total Total delete range requests."
1460 );
1461 let _ = writeln!(&mut out, "# TYPE astra_request_delete_total counter");
1462 let _ = writeln!(
1463 &mut out,
1464 "astra_request_delete_total {}",
1465 reg.request_delete_total.load(Ordering::Relaxed)
1466 );
1467 let _ = writeln!(
1468 &mut out,
1469 "# HELP astra_request_txn_total Total txn requests."
1470 );
1471 let _ = writeln!(&mut out, "# TYPE astra_request_txn_total counter");
1472 let _ = writeln!(
1473 &mut out,
1474 "astra_request_txn_total {}",
1475 reg.request_txn_total.load(Ordering::Relaxed)
1476 );
1477 let _ = writeln!(
1478 &mut out,
1479 "# HELP astra_request_lease_total Total lease API requests."
1480 );
1481 let _ = writeln!(&mut out, "# TYPE astra_request_lease_total counter");
1482 let _ = writeln!(
1483 &mut out,
1484 "astra_request_lease_total {}",
1485 reg.request_lease_total.load(Ordering::Relaxed)
1486 );
1487 let _ = writeln!(
1488 &mut out,
1489 "# HELP astra_request_watch_total Total watch stream requests."
1490 );
1491 let _ = writeln!(&mut out, "# TYPE astra_request_watch_total counter");
1492 let _ = writeln!(
1493 &mut out,
1494 "astra_request_watch_total {}",
1495 reg.request_watch_total.load(Ordering::Relaxed)
1496 );
1497 let _ = writeln!(
1498 &mut out,
1499 "# HELP astra_request_tier0_total Total requests classified as tier0 critical."
1500 );
1501 let _ = writeln!(&mut out, "# TYPE astra_request_tier0_total counter");
1502 let _ = writeln!(
1503 &mut out,
1504 "astra_request_tier0_total {}",
1505 reg.request_tier0_total.load(Ordering::Relaxed)
1506 );
1507
1508 let _ = writeln!(
1509 &mut out,
1510 "# HELP astra_profile_switch_total Total profile transitions applied by the governor."
1511 );
1512 let _ = writeln!(&mut out, "# TYPE astra_profile_switch_total counter");
1513 let _ = writeln!(
1514 &mut out,
1515 "astra_profile_switch_total {}",
1516 reg.profile_switch_total.load(Ordering::Relaxed)
1517 );
1518 let _ = writeln!(
1519 &mut out,
1520 "# HELP astra_profile_active_kubernetes Active profile gauge (1 when active)."
1521 );
1522 let _ = writeln!(&mut out, "# TYPE astra_profile_active_kubernetes gauge");
1523 let _ = writeln!(
1524 &mut out,
1525 "astra_profile_active_kubernetes {}",
1526 reg.profile_active_kubernetes.load(Ordering::Relaxed)
1527 );
1528 let _ = writeln!(
1529 &mut out,
1530 "# HELP astra_profile_active_omni Active profile gauge (1 when active)."
1531 );
1532 let _ = writeln!(&mut out, "# TYPE astra_profile_active_omni gauge");
1533 let _ = writeln!(
1534 &mut out,
1535 "astra_profile_active_omni {}",
1536 reg.profile_active_omni.load(Ordering::Relaxed)
1537 );
1538 let _ = writeln!(
1539 &mut out,
1540 "# HELP astra_profile_active_gateway Active profile gauge (1 when active)."
1541 );
1542 let _ = writeln!(&mut out, "# TYPE astra_profile_active_gateway gauge");
1543 let _ = writeln!(
1544 &mut out,
1545 "astra_profile_active_gateway {}",
1546 reg.profile_active_gateway.load(Ordering::Relaxed)
1547 );
1548 let _ = writeln!(
1549 &mut out,
1550 "# HELP astra_profile_active_auto Active profile gauge (1 when active)."
1551 );
1552 let _ = writeln!(&mut out, "# TYPE astra_profile_active_auto gauge");
1553 let _ = writeln!(
1554 &mut out,
1555 "astra_profile_active_auto {}",
1556 reg.profile_active_auto.load(Ordering::Relaxed)
1557 );
1558 let _ = writeln!(
1559 &mut out,
1560 "# HELP astra_profile_applied_put_max_requests Last profile-applied put max_requests."
1561 );
1562 let _ = writeln!(
1563 &mut out,
1564 "# TYPE astra_profile_applied_put_max_requests gauge"
1565 );
1566 let _ = writeln!(
1567 &mut out,
1568 "astra_profile_applied_put_max_requests {}",
1569 reg.profile_applied_put_max_requests.load(Ordering::Relaxed)
1570 );
1571 let _ = writeln!(
1572 &mut out,
1573 "# HELP astra_profile_applied_put_linger_microseconds Last profile-applied put linger in microseconds."
1574 );
1575 let _ = writeln!(
1576 &mut out,
1577 "# TYPE astra_profile_applied_put_linger_microseconds gauge"
1578 );
1579 let _ = writeln!(
1580 &mut out,
1581 "astra_profile_applied_put_linger_microseconds {}",
1582 reg.profile_applied_put_linger_us.load(Ordering::Relaxed)
1583 );
1584 let _ = writeln!(
1585 &mut out,
1586 "# HELP astra_profile_applied_prefetch_entries Last profile-applied list prefetch cache entry cap."
1587 );
1588 let _ = writeln!(
1589 &mut out,
1590 "# TYPE astra_profile_applied_prefetch_entries gauge"
1591 );
1592 let _ = writeln!(
1593 &mut out,
1594 "astra_profile_applied_prefetch_entries {}",
1595 reg.profile_applied_prefetch_entries.load(Ordering::Relaxed)
1596 );
1597 let _ = writeln!(
1598 &mut out,
1599 "# HELP astra_profile_applied_bg_io_tokens_per_sec Last profile-applied background IO token rate."
1600 );
1601 let _ = writeln!(
1602 &mut out,
1603 "# TYPE astra_profile_applied_bg_io_tokens_per_sec gauge"
1604 );
1605 let _ = writeln!(
1606 &mut out,
1607 "astra_profile_applied_bg_io_tokens_per_sec {}",
1608 reg.profile_applied_bg_io_tokens_per_sec
1609 .load(Ordering::Relaxed)
1610 );
1611
1612 out
1613}