metered/common/
response_time.rs

1//! A module providing the `ResponseTime` metric.
2
3use crate::{
4    clear::Clear,
5    hdr_histogram::AtomicHdrHistogram,
6    metric::{Histogram, Metric},
7    time_source::{Instant, StdInstant},
8};
9use aspect::{Advice, Enter, OnResult};
10use serde::{Serialize, Serializer};
11use std::ops::Deref;
12
13/// A metric measuring the response time of an expression, that is the duration
14/// the expression needed to complete.
15///
16/// Because it retrieves the current time before calling the expression,
17/// computes the elapsed duration and registers it to an histogram, this is a
18/// rather heavy-weight metric better applied at entry-points.
19///
20/// By default, `ResponseTime` uses an atomic hdr histogram and a synchronized
21/// time source, which work better in multithread scenarios. Non-threaded
22/// applications can gain performance by using unsynchronized structures
23/// instead.
24#[derive(Clone)]
25pub struct ResponseTime<H: Histogram = AtomicHdrHistogram, T: Instant = StdInstant>(
26    pub H,
27    std::marker::PhantomData<T>,
28);
29
30impl<H: Histogram, T: Instant> Default for ResponseTime<H, T> {
31    fn default() -> Self {
32        // A HdrHistogram measuring latencies from 1ms to 5minutes
33        // All recordings will be saturating, that is, a value higher than 5 minutes
34        // will be replace by 5 minutes...
35        ResponseTime(H::with_bound(5 * 60 * 1000), std::marker::PhantomData)
36    }
37}
38
39impl<H: Histogram, T: Instant, R> Metric<R> for ResponseTime<H, T> {}
40
41impl<H: Histogram, T: Instant> Enter for ResponseTime<H, T> {
42    type E = T;
43
44    fn enter(&self) -> T {
45        T::now()
46    }
47}
48
49impl<H: Histogram, T: Instant, R> OnResult<R> for ResponseTime<H, T> {
50    fn leave_scope(&self, enter: T) -> Advice {
51        let elapsed = enter.elapsed_time();
52        self.0.record(elapsed);
53        Advice::Return
54    }
55}
56
57impl<H: Histogram, T: Instant> Clear for ResponseTime<H, T> {
58    fn clear(&self) {
59        self.0.clear();
60    }
61}
62
63impl<H: Histogram + Serialize, T: Instant> Serialize for ResponseTime<H, T> {
64    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65    where
66        S: Serializer,
67    {
68        Serialize::serialize(&self.0, serializer)
69    }
70}
71
72use std::{fmt, fmt::Debug};
73impl<H: Histogram + Debug, T: Instant> Debug for ResponseTime<H, T> {
74    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75        write!(f, "{:?}", &self.0)
76    }
77}
78
79impl<H: Histogram, T: Instant> Deref for ResponseTime<H, T> {
80    type Target = H;
81
82    fn deref(&self) -> &Self::Target {
83        &self.0
84    }
85}