commonware_runtime/telemetry/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}
28
29/// A counter metric with a status label.
30pub type Counter = Family<Label, DefaultCounter>;
31
32/// Trait providing convenience methods for `Counter`.
33pub trait CounterExt {
34 fn guard(&self, status: Status) -> CounterGuard;
35 fn inc(&self, status: Status);
36}
37
38impl CounterExt for Counter {
39 /// Create a new CounterGuard with a given status.
40 fn guard(&self, status: Status) -> CounterGuard {
41 CounterGuard {
42 metric: self.clone(),
43 status,
44 }
45 }
46
47 /// Increment the metric with a given status.
48 fn inc(&self, status: Status) {
49 self.get_or_create(&Label { status }).inc();
50 }
51}
52
53/// Increments a `Counter` metric when dropped.
54///
55/// Can be used to ensure that counters are incremented regardless of the control flow. For example,
56/// if a function returns early, the metric will still be incremented.
57pub struct CounterGuard {
58 /// The metric to increment.
59 metric: Counter,
60
61 /// The status at which the metric is set to be incremented.
62 status: Status,
63}
64
65impl CounterGuard {
66 /// Modify the status at which the metric will be incremented.
67 pub fn set(&mut self, status: Status) {
68 self.status = status;
69 }
70}
71
72impl Drop for CounterGuard {
73 fn drop(&mut self) {
74 self.metric.inc(self.status);
75 }
76}