prometheus/
auto_flush.rs

1use crate::core::Atomic;
2use crate::counter::{CounterWithValueType, GenericLocalCounter};
3use crate::histogram::{Instant, LocalHistogram};
4use crate::metrics::MayFlush;
5use crate::timer;
6use parking_lot::Mutex;
7use std::thread::LocalKey;
8
9/// Delegator for auto flush-able local counter
10pub trait CounterDelegator<T: 'static + MayFlush, V: CounterWithValueType> {
11    /// Get the root local metric for delegate
12    fn get_root_metric(&self) -> &'static LocalKey<T>;
13
14    /// Get the final counter for delegate
15    fn get_local<'a>(&self, root_metric: &'a T) -> &'a GenericLocalCounter<V::ValueType>;
16}
17
18/// Delegator for auto flush-able local counter
19pub trait HistogramDelegator<T: 'static + MayFlush> {
20    /// Get the root local metric for delegate
21    fn get_root_metric(&self) -> &'static LocalKey<T>;
22
23    /// Get the final counter for delegate
24    fn get_local<'a>(&self, root_metric: &'a T) -> &'a LocalHistogram;
25}
26
27/// Auto flush-able local counter
28#[derive(Debug)]
29pub struct AFLocalCounter<T: 'static + MayFlush, V: CounterWithValueType, D: CounterDelegator<T, V>>
30{
31    /// Delegator to get thread local metric
32    delegator: D,
33    /// Phantomdata marker
34    _p: std::marker::PhantomData<(Mutex<T>, Mutex<V>)>,
35}
36
37impl<T: 'static + MayFlush, V: CounterWithValueType, D: CounterDelegator<T, V>>
38    AFLocalCounter<T, V, D>
39{
40    /// Construct a new AFLocalCounter from delegator.
41    pub fn new(delegator: D) -> AFLocalCounter<T, V, D> {
42        timer::ensure_updater();
43        AFLocalCounter {
44            delegator,
45            _p: std::marker::PhantomData,
46        }
47    }
48}
49
50/// Auto flush-able local counter
51impl<T: 'static + MayFlush, V: CounterWithValueType, D: CounterDelegator<T, V>>
52    AFLocalCounter<T, V, D>
53{
54    #[inline]
55    /// Get the root local metric for delegate
56    fn get_root_metric(&self) -> &'static LocalKey<T> {
57        self.delegator.get_root_metric()
58    }
59
60    #[inline]
61    /// Get the final counter for delegate
62    fn get_counter<'a>(&self, root_metric: &'a T) -> &'a GenericLocalCounter<V::ValueType> {
63        self.delegator.get_local(root_metric)
64    }
65
66    /// Increase the given value to the local counter,
67    /// and try to flush to global
68    /// # Panics
69    ///
70    /// Panics in debug build if the value is < 0.
71    #[inline]
72    pub fn inc_by(&self, v: <V::ValueType as Atomic>::T) {
73        self.get_root_metric().with(|m| {
74            let counter = self.get_counter(m);
75            counter.inc_by(v);
76            m.may_flush();
77        })
78    }
79
80    /// Increase the local counter by 1,
81    /// and try to flush to global.
82    #[inline]
83    pub fn inc(&self) {
84        self.get_root_metric().with(|m| {
85            let counter = self.get_counter(m);
86            counter.inc();
87            m.may_flush();
88        })
89    }
90
91    /// Return the local counter value.
92    #[inline]
93    pub fn get(&self) -> <V::ValueType as Atomic>::T {
94        self.get_root_metric().with(|m| {
95            let counter = self.get_counter(m);
96            counter.get()
97        })
98    }
99
100    /// Restart the counter, resetting its value back to 0.
101    #[inline]
102    pub fn reset(&self) {
103        self.get_root_metric().with(|m| {
104            let counter = self.get_counter(m);
105            counter.reset();
106        })
107    }
108
109    /// trigger flush of LocalKey<T>
110    #[inline]
111    pub fn flush(&self) {
112        self.get_root_metric().with(|m| m.flush())
113    }
114}
115
116/// Auto flush-able local counter
117#[derive(Debug)]
118pub struct AFLocalHistogram<T: 'static + MayFlush, D: HistogramDelegator<T>> {
119    /// Delegator to get thread local metric
120    delegator: D,
121    /// Phantomdata marker
122    _p: std::marker::PhantomData<Mutex<T>>,
123}
124
125impl<T: 'static + MayFlush, D: HistogramDelegator<T>> AFLocalHistogram<T, D> {
126    /// Construct a new AFLocalHistogram from delegator
127    pub fn new(delegator: D) -> AFLocalHistogram<T, D> {
128        timer::ensure_updater();
129        AFLocalHistogram {
130            delegator,
131            _p: std::marker::PhantomData,
132        }
133    }
134}
135
136impl<M: 'static + MayFlush, D: HistogramDelegator<M>> AFLocalHistogram<M, D> {
137    /// Add a single observation to the [`Histogram`](crate::Histogram).
138    pub fn observe(&self, v: f64) {
139        self.delegator.get_root_metric().with(|m| {
140            let local = self.delegator.get_local(m);
141            local.observe(v);
142            m.may_flush();
143        })
144    }
145
146    /// Observe execution time of a closure, in second.
147    pub fn observe_closure_duration<F, T>(&self, f: F) -> T
148    where
149        F: FnOnce() -> T,
150    {
151        let instant = Instant::now();
152        let res = f();
153        let elapsed = instant.elapsed_sec();
154        self.observe(elapsed);
155        res
156    }
157
158    /// Observe execution time of a closure, in second.
159    #[cfg(feature = "nightly")]
160    pub fn observe_closure_duration_coarse<F, T>(&self, f: F) -> T
161    where
162        F: FnOnce() -> T,
163    {
164        let instant = Instant::now_coarse();
165        let res = f();
166        let elapsed = instant.elapsed_sec();
167        self.observe(elapsed);
168        res
169    }
170
171    /// Clear the local metric.
172    pub fn clear(&self) {
173        self.delegator
174            .get_root_metric()
175            .with(|m| self.delegator.get_local(m).clear())
176    }
177
178    /// Flush the local metrics to the [`Histogram`](crate::Histogram) metric.
179    pub fn flush(&self) {
180        self.delegator
181            .get_root_metric()
182            .with(|m| self.delegator.get_local(m).flush());
183    }
184
185    /// Return accumulated sum of local samples.
186    pub fn get_sample_sum(&self) -> f64 {
187        self.delegator
188            .get_root_metric()
189            .with(|m| self.delegator.get_local(m).get_sample_sum())
190    }
191
192    /// Return count of local samples.
193    pub fn get_sample_count(&self) -> u64 {
194        self.delegator
195            .get_root_metric()
196            .with(|m| self.delegator.get_local(m).get_sample_count())
197    }
198}