spate_core/metrics/
checkpoint.rs1use super::MetricsError;
4use super::labels::{ComponentLabels, OwnedGauge, PartitionGauges};
5use super::names;
6use super::ownership::{SeriesClaim, series_key};
7use crate::record::PartitionId;
8use metrics::{Counter, Histogram};
9use std::collections::HashMap;
10use std::sync::Mutex;
11use std::time::Duration;
12
13#[derive(Debug)]
15pub struct CheckpointMetrics {
16 pending_max: OwnedGauge,
17 commits_ok: Counter,
18 commits_err: Counter,
19 commit_duration: Histogram,
20 watermark_age: OwnedGauge,
21 partition_pending: Option<PartitionGauges>,
22 _claim: Option<SeriesClaim>,
23}
24
25impl CheckpointMetrics {
26 pub fn new(labels: &ComponentLabels, per_partition_detail: bool) -> Self {
32 let claim = SeriesClaim::claim_or_shadow(Self::key(labels));
33 Self::build(labels, per_partition_detail, claim)
34 }
35
36 pub fn try_new(
43 labels: &ComponentLabels,
44 per_partition_detail: bool,
45 ) -> Result<Self, MetricsError> {
46 let claim = SeriesClaim::try_claim(Self::key(labels))?;
47 Ok(Self::build(labels, per_partition_detail, Some(claim)))
48 }
49
50 fn key(labels: &ComponentLabels) -> String {
51 series_key("checkpoint", labels, "")
52 }
53
54 fn build(
55 labels: &ComponentLabels,
56 per_partition_detail: bool,
57 claim: Option<SeriesClaim>,
58 ) -> Self {
59 let owned = claim.is_some();
60 CheckpointMetrics {
61 pending_max: OwnedGauge::new(labels.gauge(names::CHECKPOINT_PENDING_BATCHES), owned),
62 commits_ok: labels.counter1(names::CHECKPOINT_COMMITS_TOTAL, names::L_OUTCOME, "ok"),
63 commits_err: labels.counter1(
64 names::CHECKPOINT_COMMITS_TOTAL,
65 names::L_OUTCOME,
66 "error",
67 ),
68 commit_duration: labels.histogram(names::CHECKPOINT_COMMIT_DURATION_SECONDS),
69 watermark_age: OwnedGauge::new(
70 labels.gauge(names::CHECKPOINT_WATERMARK_AGE_SECONDS),
71 owned,
72 ),
73 partition_pending: per_partition_detail.then(|| PartitionGauges {
74 name: names::CHECKPOINT_PENDING_BATCHES,
75 labels: labels.clone(),
76 gauges: Mutex::new(HashMap::new()),
77 owned,
78 }),
79 _claim: claim,
80 }
81 }
82
83 pub fn set_pending_max(&self, pending: usize) {
85 self.pending_max.set(pending as f64);
86 }
87
88 pub fn set_partition_pending(&self, partition: PartitionId, pending: usize) {
91 if let Some(pg) = &self.partition_pending {
92 pg.set(partition, pending as f64);
93 }
94 }
95
96 pub fn retain_partitions(&self, keep: &[PartitionId]) {
98 if let Some(pg) = &self.partition_pending {
99 pg.retain(keep);
100 }
101 }
102
103 pub fn commit(&self, ok: bool, d: Duration) {
105 if ok {
106 self.commits_ok.increment(1);
107 } else {
108 self.commits_err.increment(1);
109 }
110 self.commit_duration.record(d.as_secs_f64());
111 }
112
113 pub fn set_watermark_age(&self, age: Duration) {
115 self.watermark_age.set(age.as_secs_f64());
116 }
117}