commonware_runtime/telemetry/metrics/
status.rs

1//! Recording metrics with a status.
2
3use prometheus_client::{
4    encoding::{EncodeLabelSet, EncodeLabelValue},
5    metrics::{counter::Counter as DefaultCounter, family::Family},
6};
7
8/// Metric label that indicates status.
9#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, EncodeLabelSet)]
10pub struct Label {
11    /// The value of the label.
12    status: Status,
13}
14
15/// Possible values for the status label.
16#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, EncodeLabelValue)]
17pub enum Status {
18    /// Processed successfully.
19    Success,
20    /// Processing failed.
21    Failure,
22    /// Input was malformed or invalid in some way. Indicates a client error.
23    Invalid,
24    /// Input was valid, but intentionally not processed.
25    /// For example due to a rate limit, being a duplicate, etc.
26    Dropped,
27    /// Processing returned no result before some deadline.
28    Timeout,
29}
30
31/// A counter metric with a status label.
32pub type Counter = Family<Label, DefaultCounter>;
33
34/// Trait providing convenience methods for `Counter`.
35pub trait CounterExt {
36    fn guard(&self, status: Status) -> CounterGuard;
37    fn inc(&self, status: Status);
38    fn inc_by(&self, status: Status, n: u64);
39}
40
41impl CounterExt for Counter {
42    /// Create a new CounterGuard with a given status.
43    fn guard(&self, status: Status) -> CounterGuard {
44        CounterGuard {
45            metric: self.clone(),
46            status,
47        }
48    }
49
50    /// Increment the metric with a given status.
51    fn inc(&self, status: Status) {
52        self.get_or_create(&Label { status }).inc();
53    }
54
55    /// Increment the metric with a given status.
56    fn inc_by(&self, status: Status, n: u64) {
57        self.get_or_create(&Label { status }).inc_by(n);
58    }
59}
60
61/// Increments a `Counter` metric when dropped.
62///
63/// Can be used to ensure that counters are incremented regardless of the control flow. For example,
64/// if a function returns early, the metric will still be incremented.
65pub struct CounterGuard {
66    /// The metric to increment.
67    metric: Counter,
68
69    /// The status at which the metric is set to be incremented.
70    status: Status,
71}
72
73impl CounterGuard {
74    /// Modify the status at which the metric will be incremented.
75    pub fn set(&mut self, status: Status) {
76        self.status = status;
77    }
78}
79
80impl Drop for CounterGuard {
81    fn drop(&mut self) {
82        self.metric.inc(self.status);
83    }
84}