raft_engine/
metrics.rs

1// Copyright 2021 TiKV Project Authors. Licensed under Apache-2.0.
2
3use std::{
4    cell::{RefCell, RefMut},
5    ops::AddAssign,
6    time::{Duration, Instant},
7};
8
9use prometheus::*;
10use prometheus_static_metric::*;
11
12use crate::util::InstantExt;
13
14pub struct StopWatch<M: TimeMetric> {
15    metric: M,
16    start: Instant,
17}
18
19impl<M: TimeMetric> StopWatch<M> {
20    #[inline]
21    pub fn new(metric: M) -> Self {
22        Self {
23            metric,
24            start: Instant::now(),
25        }
26    }
27
28    #[inline]
29    pub fn new_with(metric: M, start: Instant) -> Self {
30        Self { metric, start }
31    }
32}
33
34impl<M: TimeMetric> Drop for StopWatch<M> {
35    fn drop(&mut self) {
36        self.metric.observe(self.start.saturating_elapsed());
37    }
38}
39
40/// PerfContext records cumulative performance statistics of operations.
41///
42/// Raft Engine will update the data in the thread-local PerfContext whenever
43/// an opeartion is performed.
44#[derive(Debug, Clone, Default)]
45pub struct PerfContext {
46    /// Time spent encoding and compressing log entries.
47    pub log_populating_duration: Duration,
48
49    /// Time spent waiting for the write group to form and get processed.
50    pub write_wait_duration: Duration,
51
52    /// Time spent writing the logs to files.
53    pub log_write_duration: Duration,
54
55    /// Time spent rotating the active log file.
56    pub log_rotate_duration: Duration,
57
58    // Time spent synchronizing logs to the disk.
59    pub log_sync_duration: Duration,
60
61    // Time spent applying the appended logs.
62    pub apply_duration: Duration,
63}
64
65impl AddAssign<&'_ PerfContext> for PerfContext {
66    fn add_assign(&mut self, rhs: &PerfContext) {
67        self.log_populating_duration += rhs.log_populating_duration;
68        self.write_wait_duration += rhs.write_wait_duration;
69        self.log_write_duration += rhs.log_write_duration;
70        self.log_rotate_duration += rhs.log_rotate_duration;
71        self.log_sync_duration += rhs.log_sync_duration;
72        self.apply_duration += rhs.apply_duration;
73    }
74}
75
76thread_local! {
77    static TLS_PERF_CONTEXT: RefCell<PerfContext> = RefCell::new(PerfContext::default());
78}
79
80/// Gets a copy of the thread-local PerfContext.
81pub fn get_perf_context() -> PerfContext {
82    TLS_PERF_CONTEXT.with(|c| c.borrow().clone())
83}
84
85/// Resets the thread-local PerfContext and takes its old value.
86pub fn take_perf_context() -> PerfContext {
87    TLS_PERF_CONTEXT.with(|c| c.take())
88}
89
90/// Sets the value of the thread-local PerfContext.
91pub fn set_perf_context(perf_context: PerfContext) {
92    TLS_PERF_CONTEXT.with(|c| *c.borrow_mut() = perf_context);
93}
94
95pub(crate) struct PerfContextField<P> {
96    projector: P,
97}
98
99impl<P> PerfContextField<P>
100where
101    P: Fn(&mut PerfContext) -> &mut Duration,
102{
103    pub fn new(projector: P) -> Self {
104        PerfContextField { projector }
105    }
106}
107
108#[macro_export]
109macro_rules! perf_context {
110    ($field: ident) => {
111        $crate::metrics::PerfContextField::new(|perf_context| &mut perf_context.$field)
112    };
113}
114
115pub trait TimeMetric {
116    fn observe(&self, duration: Duration);
117
118    fn observe_since(&self, earlier: Instant) -> Duration {
119        let dur = earlier.saturating_elapsed();
120        self.observe(dur);
121        dur
122    }
123}
124
125impl<'a> TimeMetric for &'a Histogram {
126    fn observe(&self, duration: Duration) {
127        Histogram::observe(self, duration.as_secs_f64());
128    }
129}
130
131impl<P> TimeMetric for PerfContextField<P>
132where
133    P: Fn(&mut PerfContext) -> &mut Duration,
134{
135    fn observe(&self, duration: Duration) {
136        TLS_PERF_CONTEXT.with(|perf_context| {
137            *RefMut::map(perf_context.borrow_mut(), &self.projector) += duration;
138        })
139    }
140}
141
142impl<M1, M2> TimeMetric for (M1, M2)
143where
144    M1: TimeMetric,
145    M2: TimeMetric,
146{
147    fn observe(&self, duration: Duration) {
148        self.0.observe(duration);
149        self.1.observe(duration);
150    }
151}
152
153make_static_metric! {
154    pub label_enum LogQueueKind {
155        rewrite,
156        append,
157    }
158
159    pub struct LogQueueHistogramVec: Histogram {
160        "type" => LogQueueKind,
161    }
162
163    pub struct LogQueueCounterVec: IntCounter {
164        "type" => LogQueueKind,
165    }
166
167    pub struct LogQueueGaugeVec: IntGauge {
168        "type" => LogQueueKind,
169    }
170}
171
172lazy_static! {
173    // Write path.
174    pub static ref ENGINE_WRITE_DURATION_HISTOGRAM: Histogram = register_histogram!(
175        "raft_engine_write_duration_seconds",
176        "Bucketed histogram of Raft Engine write duration",
177        exponential_buckets(0.00005, 1.8, 26).unwrap()
178    )
179    .unwrap();
180    pub static ref ENGINE_WRITE_PREPROCESS_DURATION_HISTOGRAM: Histogram = register_histogram!(
181        "raft_engine_write_preprocess_duration_seconds",
182        "Bucketed histogram of Raft Engine write preprocess duration",
183        exponential_buckets(0.00005, 1.8, 26).unwrap()
184    )
185    .unwrap();
186    pub static ref ENGINE_WRITE_LEADER_DURATION_HISTOGRAM: Histogram = register_histogram!(
187        "raft_engine_write_leader_duration_seconds",
188        "Bucketed histogram of Raft Engine write leader duration",
189        exponential_buckets(0.00005, 1.8, 26).unwrap()
190    )
191    .unwrap();
192    pub static ref ENGINE_WRITE_APPLY_DURATION_HISTOGRAM: Histogram = register_histogram!(
193        "raft_engine_write_apply_duration_seconds",
194        "Bucketed histogram of Raft Engine write apply duration",
195        exponential_buckets(0.00005, 1.8, 26).unwrap()
196    )
197    .unwrap();
198    pub static ref ENGINE_WRITE_SIZE_HISTOGRAM: Histogram = register_histogram!(
199        "raft_engine_write_size",
200        "Bucketed histogram of Raft Engine write size",
201        exponential_buckets(256.0, 1.8, 22).unwrap()
202    )
203    .unwrap();
204    pub static ref LOG_ALLOCATE_DURATION_HISTOGRAM: Histogram = register_histogram!(
205        "raft_engine_allocate_log_duration_seconds",
206        "Bucketed histogram of Raft Engine allocate log duration",
207        exponential_buckets(0.00005, 1.8, 26).unwrap()
208    )
209    .unwrap();
210    pub static ref LOG_SYNC_DURATION_HISTOGRAM: Histogram = register_histogram!(
211        "raft_engine_sync_log_duration_seconds",
212        "Bucketed histogram of Raft Engine sync log duration",
213        exponential_buckets(0.00005, 1.8, 26).unwrap()
214    )
215    .unwrap();
216    pub static ref LOG_ROTATE_DURATION_HISTOGRAM: Histogram = register_histogram!(
217        "raft_engine_rotate_log_duration_seconds",
218        "Bucketed histogram of Raft Engine rotate log duration",
219        exponential_buckets(0.00005, 1.8, 26).unwrap()
220    )
221    .unwrap();
222    // Read path.
223    pub static ref ENGINE_READ_ENTRY_DURATION_HISTOGRAM: Histogram = register_histogram!(
224        "raft_engine_read_entry_duration_seconds",
225        "Bucketed histogram of Raft Engine read entry duration",
226        exponential_buckets(0.00005, 1.8, 26).unwrap()
227    )
228    .unwrap();
229    pub static ref ENGINE_READ_ENTRY_COUNT_HISTOGRAM: Histogram = register_histogram!(
230        "raft_engine_read_entry_count",
231        "Bucketed histogram of Raft Engine read entry count",
232        exponential_buckets(1.0, 1.8, 22).unwrap()
233    )
234    .unwrap();
235    pub static ref ENGINE_READ_MESSAGE_DURATION_HISTOGRAM: Histogram = register_histogram!(
236        "raft_engine_read_message_duration_seconds",
237        "Bucketed histogram of Raft Engine read message duration",
238        exponential_buckets(0.00005, 1.8, 26).unwrap()
239    )
240    .unwrap();
241    // Misc.
242    pub static ref ENGINE_PURGE_DURATION_HISTOGRAM: Histogram = register_histogram!(
243        "raft_engine_purge_duration_seconds",
244        "Bucketed histogram of Raft Engine purge expired files duration",
245        exponential_buckets(0.001, 1.8, 22).unwrap()
246    )
247    .unwrap();
248    pub static ref ENGINE_REWRITE_APPEND_DURATION_HISTOGRAM: Histogram = register_histogram!(
249        "raft_engine_rewrite_append_duration_seconds",
250        "Bucketed histogram of Raft Engine rewrite append queue duration",
251        exponential_buckets(0.001, 1.8, 22).unwrap()
252    )
253    .unwrap();
254    pub static ref ENGINE_REWRITE_REWRITE_DURATION_HISTOGRAM: Histogram = register_histogram!(
255        "raft_engine_rewrite_rewrite_duration_seconds",
256        "Bucketed histogram of Raft Engine rewrite rewrite queue duration",
257        exponential_buckets(0.001, 1.8, 22).unwrap()
258    )
259    .unwrap();
260    pub static ref BACKGROUND_REWRITE_BYTES: LogQueueHistogramVec = register_static_histogram_vec!(
261        LogQueueHistogramVec,
262        "raft_engine_background_rewrite_bytes",
263        "Bucketed histogram of bytes written during background rewrite",
264        &["type"],
265        exponential_buckets(256.0, 1.8, 22).unwrap()
266    )
267    .unwrap();
268    pub static ref LOG_FILE_COUNT: LogQueueGaugeVec = register_static_int_gauge_vec!(
269        LogQueueGaugeVec,
270        "raft_engine_log_file_count",
271        "Amount of log files in Raft engine",
272        &["type"]
273    )
274    .unwrap();
275    pub static ref RECYCLED_FILE_COUNT: LogQueueGaugeVec = register_static_int_gauge_vec!(
276        LogQueueGaugeVec,
277        "raft_engine_recycled_file_count",
278        "Amount of recycled files in Raft engine",
279        &["type"]
280    )
281    .unwrap();
282    pub static ref SWAP_FILE_COUNT: IntGauge = register_int_gauge!(
283        "raft_engine_swap_file_count",
284        "Amount of swap files in Raft engine"
285    )
286    .unwrap();
287    pub static ref LOG_ENTRY_COUNT: LogQueueGaugeVec = register_static_int_gauge_vec!(
288        LogQueueGaugeVec,
289        "raft_engine_log_entry_count",
290        "Number of log entries in Raft engine",
291        &["type"]
292    )
293    .unwrap();
294    pub static ref MEMORY_USAGE: IntGauge = register_int_gauge!(
295        "raft_engine_memory_usage",
296        "Memory in bytes used by Raft engine",
297    )
298    .unwrap();
299}