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 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
66pub 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}