metrics/
handles.rs

1use std::{fmt::Debug, sync::Arc};
2
3use crate::IntoF64;
4
5/// A counter handler.
6pub trait CounterFn {
7    /// Increments the counter by the given amount.
8    fn increment(&self, value: u64);
9
10    /// Sets the counter to at least the given amount.
11    ///
12    /// This is intended to support use cases where multiple callers are attempting to synchronize
13    /// this counter with an external counter that they have no control over.  As multiple callers
14    /// may read that external counter, and attempt to set it here, there could be reordering issues
15    /// where a caller attempts to set an older (smaller) value after the counter has been updated to
16    /// the latest (larger) value.
17    ///
18    /// This method must cope with those cases.  An example of doing so atomically can be found in
19    /// `AtomicCounter`.
20    fn absolute(&self, value: u64);
21}
22
23/// A gauge handler.
24pub trait GaugeFn {
25    /// Increments the gauge by the given amount.
26    fn increment(&self, value: f64);
27
28    /// Decrements the gauge by the given amount.
29    fn decrement(&self, value: f64);
30
31    /// Sets the gauge to the given amount.
32    fn set(&self, value: f64);
33}
34
35/// A histogram handler.
36pub trait HistogramFn {
37    /// Records a value into the histogram.
38    fn record(&self, value: f64);
39
40    /// Records a value into the histogram multiple times.
41    fn record_many(&self, value: f64, count: usize) {
42        for _ in 0..count {
43            self.record(value);
44        }
45    }
46}
47
48/// A counter.
49#[derive(Clone)]
50#[must_use = "counters do nothing unless you use them"]
51pub struct Counter {
52    inner: Option<Arc<dyn CounterFn + Send + Sync>>,
53}
54
55impl Debug for Counter {
56    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57        f.debug_struct("Counter").finish_non_exhaustive()
58    }
59}
60
61/// A gauge.
62#[derive(Clone)]
63#[must_use = "gauges do nothing unless you use them"]
64pub struct Gauge {
65    inner: Option<Arc<dyn GaugeFn + Send + Sync>>,
66}
67
68impl Debug for Gauge {
69    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70        f.debug_struct("Gauge").finish_non_exhaustive()
71    }
72}
73
74/// A histogram.
75#[derive(Clone)]
76#[must_use = "histograms do nothing unless you use them"]
77pub struct Histogram {
78    inner: Option<Arc<dyn HistogramFn + Send + Sync>>,
79}
80
81impl Debug for Histogram {
82    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83        f.debug_struct("Histogram").finish_non_exhaustive()
84    }
85}
86
87impl Counter {
88    /// Creates a no-op `Counter` which does nothing.
89    ///
90    /// Suitable when a handle must be provided that does nothing i.e. a no-op recorder or a layer
91    /// that disables specific metrics, and so on.
92    pub fn noop() -> Self {
93        Self { inner: None }
94    }
95
96    /// Creates a `Counter` based on a shared handler.
97    pub fn from_arc<F: CounterFn + Send + Sync + 'static>(a: Arc<F>) -> Self {
98        Self { inner: Some(a) }
99    }
100
101    /// Increments the counter.
102    pub fn increment(&self, value: u64) {
103        if let Some(c) = &self.inner {
104            c.increment(value)
105        }
106    }
107
108    /// Sets the counter to an absolute value.
109    pub fn absolute(&self, value: u64) {
110        if let Some(c) = &self.inner {
111            c.absolute(value)
112        }
113    }
114}
115
116impl Gauge {
117    /// Creates a no-op `Gauge` which does nothing.
118    ///
119    /// Suitable when a handle must be provided that does nothing i.e. a no-op recorder or a layer
120    /// that disables specific metrics, and so on.
121    pub fn noop() -> Self {
122        Self { inner: None }
123    }
124
125    /// Creates a `Gauge` based on a shared handler.
126    pub fn from_arc<F: GaugeFn + Send + Sync + 'static>(a: Arc<F>) -> Self {
127        Self { inner: Some(a) }
128    }
129
130    /// Increments the gauge.
131    pub fn increment<T: IntoF64>(&self, value: T) {
132        if let Some(g) = &self.inner {
133            g.increment(value.into_f64())
134        }
135    }
136
137    /// Decrements the gauge.
138    pub fn decrement<T: IntoF64>(&self, value: T) {
139        if let Some(g) = &self.inner {
140            g.decrement(value.into_f64())
141        }
142    }
143
144    /// Sets the gauge.
145    pub fn set<T: IntoF64>(&self, value: T) {
146        if let Some(g) = &self.inner {
147            g.set(value.into_f64())
148        }
149    }
150}
151
152impl Histogram {
153    /// Creates a no-op `Histogram` which does nothing.
154    ///
155    /// Suitable when a handle must be provided that does nothing i.e. a no-op recorder or a layer
156    /// that disables specific metrics, and so on.
157    pub fn noop() -> Self {
158        Self { inner: None }
159    }
160
161    /// Creates a `Histogram` based on a shared handler.
162    pub fn from_arc<F: HistogramFn + Send + Sync + 'static>(a: Arc<F>) -> Self {
163        Self { inner: Some(a) }
164    }
165
166    /// Records a value into the histogram.
167    pub fn record<T: IntoF64>(&self, value: T) {
168        if let Some(ref inner) = self.inner {
169            inner.record(value.into_f64())
170        }
171    }
172
173    /// Records a value into the histogram multiple times.
174    pub fn record_many<T: IntoF64>(&self, value: T, count: usize) {
175        if let Some(ref inner) = self.inner {
176            inner.record_many(value.into_f64(), count)
177        }
178    }
179}
180
181impl<T> CounterFn for Arc<T>
182where
183    T: CounterFn,
184{
185    fn increment(&self, value: u64) {
186        (**self).increment(value)
187    }
188
189    fn absolute(&self, value: u64) {
190        (**self).absolute(value)
191    }
192}
193impl<T> GaugeFn for Arc<T>
194where
195    T: GaugeFn,
196{
197    fn increment(&self, value: f64) {
198        (**self).increment(value)
199    }
200
201    fn decrement(&self, value: f64) {
202        (**self).decrement(value)
203    }
204
205    fn set(&self, value: f64) {
206        (**self).set(value)
207    }
208}
209
210impl<T> HistogramFn for Arc<T>
211where
212    T: HistogramFn,
213{
214    fn record(&self, value: f64) {
215        (**self).record(value);
216    }
217}
218
219impl<T> From<Arc<T>> for Counter
220where
221    T: CounterFn + Send + Sync + 'static,
222{
223    fn from(inner: Arc<T>) -> Self {
224        Counter::from_arc(inner)
225    }
226}
227
228impl<T> From<Arc<T>> for Gauge
229where
230    T: GaugeFn + Send + Sync + 'static,
231{
232    fn from(inner: Arc<T>) -> Self {
233        Gauge::from_arc(inner)
234    }
235}
236
237impl<T> From<Arc<T>> for Histogram
238where
239    T: HistogramFn + Send + Sync + 'static,
240{
241    fn from(inner: Arc<T>) -> Self {
242        Histogram::from_arc(inner)
243    }
244}