1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use histogram::Histogram;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, Mutex, MutexGuard, PoisonError};
const ORDER_TYPE: Ordering = Ordering::Relaxed;
#[derive(Debug)]
pub enum MetricsError<'a> {
Poison(PoisonError<MutexGuard<'a, Histogram>>),
Histogram(&'static str),
}
impl<'a> From<PoisonError<MutexGuard<'a, Histogram>>> for MetricsError<'a> {
fn from(err: PoisonError<MutexGuard<'_, Histogram>>) -> MetricsError {
MetricsError::Poison(err)
}
}
impl From<&'static str> for MetricsError<'_> {
fn from(err: &'static str) -> MetricsError {
MetricsError::Histogram(err)
}
}
impl std::fmt::Display for MetricsError<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
#[derive(Default, Debug)]
pub struct Metrics {
errors_num: AtomicU64,
queries_num: AtomicU64,
errors_iter_num: AtomicU64,
queries_iter_num: AtomicU64,
retries_num: AtomicU64,
histogram: Arc<Mutex<Histogram>>,
}
impl Metrics {
pub fn new() -> Self {
Self {
errors_num: AtomicU64::new(0),
queries_num: AtomicU64::new(0),
errors_iter_num: AtomicU64::new(0),
queries_iter_num: AtomicU64::new(0),
retries_num: AtomicU64::new(0),
histogram: Arc::new(Mutex::new(Histogram::new())),
}
}
pub(crate) fn inc_failed_nonpaged_queries(&self) {
self.errors_num.fetch_add(1, ORDER_TYPE);
}
pub(crate) fn inc_total_nonpaged_queries(&self) {
self.queries_num.fetch_add(1, ORDER_TYPE);
}
pub(crate) fn inc_failed_paged_queries(&self) {
self.errors_iter_num.fetch_add(1, ORDER_TYPE);
}
pub(crate) fn inc_total_paged_queries(&self) {
self.queries_iter_num.fetch_add(1, ORDER_TYPE);
}
pub(crate) fn inc_retries_num(&self) {
self.retries_num.fetch_add(1, ORDER_TYPE);
}
pub(crate) fn log_query_latency(&self, latency: u64) -> Result<(), MetricsError> {
let mut histogram_unlocked = self.histogram.lock().unwrap();
histogram_unlocked.increment(latency)?;
Ok(())
}
pub fn get_latency_avg_ms(&self) -> Result<u64, MetricsError> {
let histogram_unlocked = self.histogram.lock().unwrap();
Ok(histogram_unlocked.mean()?)
}
pub fn get_latency_percentile_ms(&self, percentile: f64) -> Result<u64, MetricsError> {
let histogram_unlocked = self.histogram.lock().unwrap();
Ok(histogram_unlocked.percentile(percentile)?)
}
pub fn get_errors_num(&self) -> u64 {
self.errors_num.load(ORDER_TYPE)
}
pub fn get_queries_num(&self) -> u64 {
self.queries_num.load(ORDER_TYPE)
}
pub fn get_errors_iter_num(&self) -> u64 {
self.errors_iter_num.load(ORDER_TYPE)
}
pub fn get_queries_iter_num(&self) -> u64 {
self.queries_iter_num.load(ORDER_TYPE)
}
pub fn get_retries_num(&self) -> u64 {
self.retries_num.load(ORDER_TYPE)
}
}