witchcraft_metrics/
timer.rs1use crate::{Clock, ExponentiallyDecayingReservoir, Meter, Reservoir, Snapshot};
15use std::sync::Arc;
16use std::time::{Duration, Instant};
17
18pub struct Timer {
23 meter: Meter,
24 reservoir: Box<dyn Reservoir>,
25 clock: Arc<dyn Clock>,
26}
27
28impl Default for Timer {
29 #[inline]
30 fn default() -> Timer {
31 Timer::new(ExponentiallyDecayingReservoir::new())
32 }
33}
34
35impl Timer {
36 pub fn new<R>(reservoir: R) -> Timer
38 where
39 R: Reservoir,
40 {
41 Timer {
42 meter: Meter::new(),
43 reservoir: Box::new(reservoir),
44 clock: crate::SYSTEM_CLOCK.clone(),
45 }
46 }
47
48 pub fn new_with<R>(reservoir: R, clock: Arc<dyn Clock>) -> Self
50 where
51 R: Reservoir,
52 {
53 Timer {
54 meter: Meter::new_with(clock.clone()),
55 reservoir: Box::new(reservoir),
56 clock,
57 }
58 }
59
60 #[inline]
62 pub fn update(&self, duration: Duration) {
63 self.meter.mark(1);
64 let nanos = duration.as_nanos() as i64;
65 self.reservoir.update(nanos);
66 }
67
68 #[inline]
70 pub fn time(&self) -> Time<'_> {
71 Time {
72 timer: self,
73 start: self.clock.now(),
74 }
75 }
76
77 #[inline]
79 pub fn count(&self) -> i64 {
80 self.meter.count()
81 }
82
83 #[inline]
85 pub fn one_minute_rate(&self) -> f64 {
86 self.meter.one_minute_rate()
87 }
88
89 #[inline]
91 pub fn five_minute_rate(&self) -> f64 {
92 self.meter.five_minute_rate()
93 }
94
95 #[inline]
97 pub fn fifteen_minute_rate(&self) -> f64 {
98 self.meter.fifteen_minute_rate()
99 }
100
101 #[inline]
103 pub fn mean_rate(&self) -> f64 {
104 self.meter.mean_rate()
105 }
106
107 #[inline]
109 pub fn snapshot(&self) -> Box<dyn Snapshot> {
110 self.reservoir.snapshot()
111 }
112}
113
114pub struct Time<'a> {
116 timer: &'a Timer,
117 start: Instant,
118}
119
120impl Drop for Time<'_> {
121 #[inline]
122 fn drop(&mut self) {
123 self.timer.update(self.timer.clock.now() - self.start);
124 }
125}
126
127#[cfg(test)]
128mod test {
129 use crate::Timer;
130 use std::thread;
131 use std::time::Duration;
132
133 #[test]
134 #[allow(clippy::float_cmp)]
135 fn basic() {
136 let timer = Timer::default();
137
138 for _ in 0..15 {
139 timer.update(Duration::from_nanos(0));
140 }
141
142 for _ in 0..5 {
143 timer.update(Duration::from_nanos(5));
144 }
145
146 assert_eq!(timer.count(), 20);
147 assert!(timer.mean_rate() > 0.);
148 assert_eq!(timer.snapshot().value(0.8), 5.)
149 }
150
151 #[test]
152 fn time() {
153 let timer = Timer::default();
154
155 let guard = timer.time();
156 thread::sleep(Duration::from_millis(10));
157 drop(guard);
158
159 assert_eq!(timer.count(), 1);
160 assert!(timer.snapshot().max() >= 10_000_000);
161 }
162}