controller/
metrics.rs

1use crate::{apis::coredb_types::CoreDB, Error};
2use kube::ResourceExt;
3use prometheus::{histogram_opts, opts, HistogramVec, IntCounter, IntCounterVec, Registry};
4use tokio::time::Instant;
5
6#[derive(Clone)]
7pub struct Metrics {
8    pub reconciliations: IntCounter,
9    pub failures: IntCounterVec,
10    pub reconcile_duration: HistogramVec,
11}
12
13impl Default for Metrics {
14    fn default() -> Self {
15        let reconcile_duration = HistogramVec::new(
16            histogram_opts!(
17                "cdb_controller_reconcile_duration_seconds",
18                "The duration of reconcile to complete in seconds"
19            )
20            .buckets(vec![0.01, 0.1, 0.25, 0.5, 1., 5., 15., 60.]),
21            &[],
22        )
23        .unwrap();
24        let failures = IntCounterVec::new(
25            opts!(
26                "cbd_controller_reconciliation_errors_total",
27                "reconciliation errors",
28            ),
29            &["instance", "error"],
30        )
31        .unwrap();
32        let reconciliations =
33            IntCounter::new("cdb_controller_reconciliations_total", "reconciliations").unwrap();
34        Metrics {
35            reconciliations,
36            failures,
37            reconcile_duration,
38        }
39    }
40}
41
42impl Metrics {
43    /// Register API metrics to start tracking them.
44    pub fn register(self, registry: &Registry) -> Result<Self, prometheus::Error> {
45        registry.register(Box::new(self.reconcile_duration.clone()))?;
46        registry.register(Box::new(self.failures.clone()))?;
47        registry.register(Box::new(self.reconciliations.clone()))?;
48        Ok(self)
49    }
50
51    pub fn reconcile_failure(&self, cdb: &CoreDB, e: &Error) {
52        self.failures
53            .with_label_values(&[cdb.name_any().as_ref(), e.metric_label().as_ref()])
54            .inc()
55    }
56
57    pub fn count_and_measure(&self) -> ReconcileMeasurer {
58        self.reconciliations.inc();
59        ReconcileMeasurer {
60            start: Instant::now(),
61            metric: self.reconcile_duration.clone(),
62        }
63    }
64}
65
66/// Smart function duration measurer
67///
68/// Relies on Drop to calculate duration and register the observation in the histogram
69pub struct ReconcileMeasurer {
70    start: Instant,
71    metric: HistogramVec,
72}
73
74impl Drop for ReconcileMeasurer {
75    fn drop(&mut self) {
76        #[allow(clippy::cast_precision_loss)]
77        let duration = self.start.elapsed().as_millis() as f64 / 1000.0;
78        self.metric.with_label_values(&[]).observe(duration);
79    }
80}