1use prometheus_endpoint::{
21 exponential_buckets,
22 prometheus::{core::Collector, HistogramTimer},
23 CounterVec, GaugeVec, HistogramOpts, HistogramVec, Opts, PrometheusError, Registry, U64,
24};
25
26fn register<T: Clone + Collector + 'static>(
28 metric: T,
29 registry: &Registry,
30) -> Result<T, PrometheusError> {
31 registry.register(Box::new(metric.clone()))?;
32 Ok(metric)
33}
34
35#[derive(Clone)]
39pub struct Metrics {
40 shared_update_duration: HistogramVec,
42 shared_hits: CounterVec<U64>,
44 shared_fetch_attempts: CounterVec<U64>,
46 local_hits: CounterVec<U64>,
48 local_fetch_attempts: CounterVec<U64>,
50 local_cache_lengths: HistogramVec,
52 shared_cache_inline_size: GaugeVec<U64>,
54 shared_cache_heap_size: GaugeVec<U64>,
56}
57
58impl Metrics {
59 pub(crate) fn register(registry: &Registry) -> Result<Self, PrometheusError> {
61 Ok(Self {
62 shared_update_duration: register(
63 HistogramVec::new(
64 HistogramOpts {
65 common_opts: Opts::new(
66 "trie_cache_shared_update_duration",
67 "Duration in seconds to update the shared trie caches from local cache to shared cache",
68 ),
69 buckets: exponential_buckets(0.001, 4.0, 9)
70 .expect("function parameters are constant and always valid; qed"),
71 },
72 &["cache_type"], )?,
74 registry,
75 )?,
76 shared_hits: register(
77 CounterVec::new(
78 Opts::new(
79 "trie_cache_shared_hits",
80 "Number of attempts hitting the shared trie cache",
81 ),
82 &["cache_type"], )?,
84 registry,
85 )?,
86 shared_fetch_attempts: register(
87 CounterVec::new(
88 Opts::new(
89 "trie_cache_shared_fetch_attempts",
90 "Number of attempts to the shared trie cache",
91 ),
92 &["cache_type"],
93 )?,
94 registry,
95 )?,
96 local_hits: register(
97 CounterVec::new(
98 Opts::new(
99 "trie_cache_local_hits",
100 "Number of attempts hitting the local trie cache",
101 ),
102 &["cache_type"],
103 )?,
104 registry,
105 )?,
106 local_fetch_attempts: register(
107 CounterVec::new(
108 Opts::new(
109 "trie_cache_local_fetch_attempts",
110 "Number of attempts to the local cache",
111 ),
112 &["cache_type"],
113 )?,
114 registry,
115 )?,
116 local_cache_lengths: register(
117 HistogramVec::new(
118 HistogramOpts {
119 common_opts: Opts::new(
120 "trie_cache_local_cache_lengths",
121 "Histogram of length of the local cache",
122 ),
123 buckets: exponential_buckets(1.0, 4.0, 9)
124 .expect("function parameters are constant and always valid; qed"),
125 },
126 &["cache_type"],
127 )?,
128 registry,
129 )?,
130 shared_cache_inline_size: register(
131 GaugeVec::new(
132 Opts::new(
133 "trie_cache_shared_cache_inline_size",
134 "The inline size of the shared caches",
135 ),
136 &["cache_type"],
137 )?,
138 registry,
139 )?,
140 shared_cache_heap_size: register(
141 GaugeVec::new(
142 Opts::new(
143 "trie_cache_shared_cache_heap_size",
144 "The heap size of the shared caches",
145 ),
146 &["cache_type"],
147 )?,
148 registry,
149 )?,
150 })
151 }
152
153 pub(crate) fn start_shared_node_update_timer(&self) -> HistogramTimer {
155 self.shared_update_duration.with_label_values(&["node"]).start_timer()
156 }
157
158 pub(crate) fn start_shared_value_update_timer(&self) -> HistogramTimer {
160 self.shared_update_duration.with_label_values(&["value"]).start_timer()
161 }
162
163 pub(crate) fn observe_local_node_cache_length(&self, node_cache_len: usize) {
165 self.local_cache_lengths
166 .with_label_values(&["node"])
167 .observe(node_cache_len as f64);
168 }
169
170 pub(crate) fn observe_local_value_cache_length(&self, value_cache_len: usize) {
172 self.local_cache_lengths
173 .with_label_values(&["value"])
174 .observe(value_cache_len as f64);
175 }
176
177 pub(crate) fn observe_node_cache_inline_size(&self, cache_size: usize) {
179 self.shared_cache_inline_size
180 .with_label_values(&["node"])
181 .set(cache_size as u64);
182 }
183
184 pub(crate) fn observe_value_cache_inline_size(&self, cache_size: usize) {
186 self.shared_cache_inline_size
187 .with_label_values(&["value"])
188 .set(cache_size as u64);
189 }
190
191 pub(crate) fn observe_node_cache_heap_size(&self, cache_size: usize) {
193 self.shared_cache_heap_size.with_label_values(&["node"]).set(cache_size as u64);
194 }
195
196 pub(crate) fn observe_value_cache_heap_size(&self, cache_size: usize) {
198 self.shared_cache_heap_size.with_label_values(&["value"]).set(cache_size as u64);
199 }
200
201 pub(crate) fn observe_hits_stats(&self, stats: &TrieHitStatsSnapshot) {
203 self.shared_hits
204 .with_label_values(&["node"])
205 .inc_by(stats.node_cache.shared_hits);
206 self.shared_fetch_attempts
207 .with_label_values(&["node"])
208 .inc_by(stats.node_cache.shared_fetch_attempts);
209 self.local_hits.with_label_values(&["node"]).inc_by(stats.node_cache.local_hits);
210 self.local_fetch_attempts
211 .with_label_values(&["node"])
212 .inc_by(stats.node_cache.local_fetch_attempts);
213
214 self.shared_hits
215 .with_label_values(&["value"])
216 .inc_by(stats.value_cache.shared_hits);
217 self.shared_fetch_attempts
218 .with_label_values(&["value"])
219 .inc_by(stats.value_cache.shared_fetch_attempts);
220 self.local_hits
221 .with_label_values(&["value"])
222 .inc_by(stats.value_cache.local_hits);
223 self.local_fetch_attempts
224 .with_label_values(&["value"])
225 .inc_by(stats.value_cache.local_fetch_attempts);
226 }
227}
228
229#[derive(Default, Copy, Clone, Debug)]
231pub(crate) struct HitStatsSnapshot {
232 pub(crate) shared_hits: u64,
233 pub(crate) shared_fetch_attempts: u64,
234 pub(crate) local_hits: u64,
235 pub(crate) local_fetch_attempts: u64,
236}
237
238impl std::fmt::Display for HitStatsSnapshot {
239 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
240 let shared_hits = self.shared_hits;
241 let shared_fetch_attempts = self.shared_fetch_attempts;
242 let local_hits = self.local_hits;
243 let local_fetch_attempts = self.local_fetch_attempts;
244
245 if shared_fetch_attempts == 0 && local_hits == 0 {
246 write!(fmt, "empty")
247 } else {
248 let percent_local = (local_hits as f32 / local_fetch_attempts as f32) * 100.0;
249 let percent_shared = (shared_hits as f32 / shared_fetch_attempts as f32) * 100.0;
250 write!(
251 fmt,
252 "local hit rate = {}% [{}/{}], shared hit rate = {}% [{}/{}]",
253 percent_local as u32,
254 local_hits,
255 local_fetch_attempts,
256 percent_shared as u32,
257 shared_hits,
258 shared_fetch_attempts
259 )
260 }
261 }
262}
263
264#[derive(Default, Debug, Clone, Copy)]
266pub(crate) struct TrieHitStatsSnapshot {
267 pub(crate) node_cache: HitStatsSnapshot,
268 pub(crate) value_cache: HitStatsSnapshot,
269}