1use 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#[derive(Debug, Clone, Default)]
45pub struct PerfContext {
46 pub log_populating_duration: Duration,
48
49 pub write_wait_duration: Duration,
51
52 pub log_write_duration: Duration,
54
55 pub log_rotate_duration: Duration,
57
58 pub log_sync_duration: Duration,
60
61 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
80pub fn get_perf_context() -> PerfContext {
82 TLS_PERF_CONTEXT.with(|c| c.borrow().clone())
83}
84
85pub fn take_perf_context() -> PerfContext {
87 TLS_PERF_CONTEXT.with(|c| c.take())
88}
89
90pub 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 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 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 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}