metrics/
timer.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5use crate::{
6    histogram::{Histogram, Sample},
7    meter::{register_meter_with_group, Meter},
8    metrics::is_enabled,
9};
10use std::{
11    sync::Arc,
12    time::{Duration, Instant},
13};
14
15pub trait Timer: Send + Sync {
16    fn update(&self, _d: Duration) {}
17
18    fn update_since(&self, start_time: Instant) {
19        self.update(Instant::now().saturating_duration_since(start_time));
20    }
21}
22
23fn register_timer_exp_decay(
24    group: &str, counter_name: &str, time_name: &str,
25) -> Arc<dyn Timer> {
26    if !is_enabled() {
27        Arc::new(NoopTimer)
28    } else {
29        Arc::new(StandardTimer {
30            meter: register_meter_with_group(group, counter_name),
31            histogram: Sample::ExpDecay(0.015)
32                .register_with_group(group, time_name, 1024),
33        })
34    }
35}
36
37pub fn register_timer(name: &str) -> Arc<dyn Timer> {
38    register_timer_exp_decay(name, "counter", "time_expdec")
39}
40
41pub fn register_timer_with_group(group: &str, name: &str) -> Arc<dyn Timer> {
42    let counter_name = format!("{}_counter", name);
43    let time_name = format!("{}_time_expdec", name);
44    register_timer_exp_decay(group, counter_name.as_str(), time_name.as_str())
45}
46
47struct NoopTimer;
48impl Timer for NoopTimer {}
49
50struct StandardTimer {
51    meter: Arc<dyn Meter>,
52    histogram: Arc<dyn Histogram>,
53}
54
55impl Timer for StandardTimer {
56    fn update(&self, d: Duration) {
57        self.meter.mark(1);
58        self.histogram.update(d.as_nanos() as u64);
59    }
60}
61
62pub struct ScopeTimer {
63    timer: Arc<dyn Timer>,
64    start: Instant,
65}
66
67impl ScopeTimer {
68    /// Call this to measure the time to run to the end of the current scope.
69    /// It will update the time from the function called till the returned
70    /// instance is dropped to `timer`.
71    pub fn time_scope(timer: Arc<dyn Timer>) -> Self {
72        Self {
73            timer,
74            start: Instant::now(),
75        }
76    }
77}
78
79impl Drop for ScopeTimer {
80    fn drop(&mut self) { self.timer.update_since(self.start) }
81}