1use crate::LOG_TARGET;
22use log::{debug, error};
23use prometheus_endpoint::{register, Counter, Gauge, PrometheusError, Registry, U64};
24
25pub(crate) trait PrometheusRegister<T: Sized = Self>: Sized {
27 const DESCRIPTION: &'static str;
28 fn register(registry: &Registry) -> Result<Self, PrometheusError>;
29}
30
31#[derive(Clone, Debug)]
33pub struct VoterMetrics {
34 pub beefy_validator_set_id: Gauge<U64>,
36 pub beefy_votes_sent: Counter<U64>,
38 pub beefy_best_block: Gauge<U64>,
40 pub beefy_best_voted: Gauge<U64>,
42 pub beefy_should_vote_on: Gauge<U64>,
44 pub beefy_lagging_sessions: Counter<U64>,
46 pub beefy_no_authority_found_in_store: Counter<U64>,
48 pub beefy_good_votes_processed: Counter<U64>,
50 pub beefy_equivocation_votes: Counter<U64>,
52 pub beefy_invalid_votes: Counter<U64>,
54 pub beefy_stale_votes: Counter<U64>,
56 pub beefy_buffered_justifications: Gauge<U64>,
58 pub beefy_stale_justifications: Counter<U64>,
60 pub beefy_imported_justifications: Counter<U64>,
62 pub beefy_buffered_justifications_dropped: Counter<U64>,
64}
65
66impl PrometheusRegister for VoterMetrics {
67 const DESCRIPTION: &'static str = "voter";
68 fn register(registry: &Registry) -> Result<Self, PrometheusError> {
69 Ok(Self {
70 beefy_validator_set_id: register(
71 Gauge::new(
72 "substrate_beefy_validator_set_id",
73 "Current BEEFY active validator set id.",
74 )?,
75 registry,
76 )?,
77 beefy_votes_sent: register(
78 Counter::new("substrate_beefy_votes_sent", "Number of votes sent by this node")?,
79 registry,
80 )?,
81 beefy_best_block: register(
82 Gauge::new("substrate_beefy_best_block", "Best block finalized by BEEFY")?,
83 registry,
84 )?,
85 beefy_best_voted: register(
86 Gauge::new("substrate_beefy_best_voted", "Best block voted on by BEEFY")?,
87 registry,
88 )?,
89 beefy_should_vote_on: register(
90 Gauge::new("substrate_beefy_should_vote_on", "Next block, BEEFY should vote on")?,
91 registry,
92 )?,
93 beefy_lagging_sessions: register(
94 Counter::new(
95 "substrate_beefy_lagging_sessions",
96 "Number of sessions with lagging signed commitment on mandatory block",
97 )?,
98 registry,
99 )?,
100 beefy_no_authority_found_in_store: register(
101 Counter::new(
102 "substrate_beefy_no_authority_found_in_store",
103 "Number of times no Authority public key found in store",
104 )?,
105 registry,
106 )?,
107 beefy_good_votes_processed: register(
108 Counter::new(
109 "substrate_beefy_successful_handled_votes",
110 "Number of good votes successfully handled",
111 )?,
112 registry,
113 )?,
114 beefy_equivocation_votes: register(
115 Counter::new(
116 "substrate_beefy_equivocation_votes",
117 "Number of equivocation votes received",
118 )?,
119 registry,
120 )?,
121 beefy_invalid_votes: register(
122 Counter::new("substrate_beefy_invalid_votes", "Number of invalid votes received")?,
123 registry,
124 )?,
125 beefy_stale_votes: register(
126 Counter::new(
127 "substrate_beefy_stale_votes",
128 "Number of valid but stale votes received",
129 )?,
130 registry,
131 )?,
132 beefy_buffered_justifications: register(
133 Gauge::new(
134 "substrate_beefy_buffered_justifications",
135 "Number of currently buffered justifications",
136 )?,
137 registry,
138 )?,
139 beefy_stale_justifications: register(
140 Counter::new(
141 "substrate_beefy_stale_justifications",
142 "Number of valid but stale justifications received",
143 )?,
144 registry,
145 )?,
146 beefy_imported_justifications: register(
147 Counter::new(
148 "substrate_beefy_imported_justifications",
149 "Number of valid justifications successfully imported",
150 )?,
151 registry,
152 )?,
153 beefy_buffered_justifications_dropped: register(
154 Counter::new(
155 "substrate_beefy_buffered_justifications_dropped",
156 "Number of justifications dropped due to full buffers",
157 )?,
158 registry,
159 )?,
160 })
161 }
162}
163
164#[derive(Clone, Debug)]
166pub struct BlockImportMetrics {
167 pub beefy_good_justification_imports: Counter<U64>,
169 pub beefy_bad_justification_imports: Counter<U64>,
171}
172
173impl PrometheusRegister for BlockImportMetrics {
174 const DESCRIPTION: &'static str = "block-import";
175 fn register(registry: &Registry) -> Result<Self, PrometheusError> {
176 Ok(Self {
177 beefy_good_justification_imports: register(
178 Counter::new(
179 "substrate_beefy_good_justification_imports",
180 "Number of good justifications on block-import",
181 )?,
182 registry,
183 )?,
184 beefy_bad_justification_imports: register(
185 Counter::new(
186 "substrate_beefy_bad_justification_imports",
187 "Number of bad justifications on block-import",
188 )?,
189 registry,
190 )?,
191 })
192 }
193}
194
195#[derive(Clone, Debug)]
197pub struct OnDemandIncomingRequestsMetrics {
198 pub beefy_successful_justification_responses: Counter<U64>,
200 pub beefy_failed_justification_responses: Counter<U64>,
202}
203
204impl PrometheusRegister for OnDemandIncomingRequestsMetrics {
205 const DESCRIPTION: &'static str = "on-demand incoming justification requests";
206 fn register(registry: &Registry) -> Result<Self, PrometheusError> {
207 Ok(Self {
208 beefy_successful_justification_responses: register(
209 Counter::new(
210 "substrate_beefy_successful_justification_responses",
211 "Number of Successful Justification responses",
212 )?,
213 registry,
214 )?,
215 beefy_failed_justification_responses: register(
216 Counter::new(
217 "substrate_beefy_failed_justification_responses",
218 "Number of Failed Justification responses",
219 )?,
220 registry,
221 )?,
222 })
223 }
224}
225
226#[derive(Clone, Debug)]
228pub struct OnDemandOutgoingRequestsMetrics {
229 pub beefy_on_demand_justification_no_peer_to_request_from: Counter<U64>,
231 pub beefy_on_demand_justification_peer_refused: Counter<U64>,
233 pub beefy_on_demand_justification_peer_error: Counter<U64>,
235 pub beefy_on_demand_justification_invalid_proof: Counter<U64>,
237 pub beefy_on_demand_justification_good_proof: Counter<U64>,
239 pub beefy_on_demand_live_peers: Gauge<U64>,
241}
242
243impl PrometheusRegister for OnDemandOutgoingRequestsMetrics {
244 const DESCRIPTION: &'static str = "on-demand outgoing justification requests";
245 fn register(registry: &Registry) -> Result<Self, PrometheusError> {
246 Ok(Self {
247 beefy_on_demand_justification_no_peer_to_request_from: register(
248 Counter::new(
249 "substrate_beefy_on_demand_justification_no_peer_to_request_from",
250 "Number of times there was no good peer to request justification from",
251 )?,
252 registry,
253 )?,
254 beefy_on_demand_justification_peer_refused: register(
255 Counter::new(
256 "beefy_on_demand_justification_peer_refused",
257 "Number of on-demand justification peer refused valid requests",
258 )?,
259 registry,
260 )?,
261 beefy_on_demand_justification_peer_error: register(
262 Counter::new(
263 "substrate_beefy_on_demand_justification_peer_error",
264 "Number of on-demand justification peer error",
265 )?,
266 registry,
267 )?,
268 beefy_on_demand_justification_invalid_proof: register(
269 Counter::new(
270 "substrate_beefy_on_demand_justification_invalid_proof",
271 "Number of on-demand justification invalid proof",
272 )?,
273 registry,
274 )?,
275 beefy_on_demand_justification_good_proof: register(
276 Counter::new(
277 "substrate_beefy_on_demand_justification_good_proof",
278 "Number of on-demand justification good proof",
279 )?,
280 registry,
281 )?,
282 beefy_on_demand_live_peers: register(
283 Gauge::new(
284 "substrate_beefy_on_demand_live_peers",
285 "Number of live beefy peers available for requests.",
286 )?,
287 registry,
288 )?,
289 })
290 }
291}
292
293pub(crate) fn register_metrics<T: PrometheusRegister>(
294 prometheus_registry: Option<prometheus_endpoint::Registry>,
295) -> Option<T> {
296 prometheus_registry.as_ref().map(T::register).and_then(|result| match result {
297 Ok(metrics) => {
298 debug!(target: LOG_TARGET, "🥩 Registered {} metrics", T::DESCRIPTION);
299 Some(metrics)
300 },
301 Err(err) => {
302 error!(
303 target: LOG_TARGET,
304 "🥩 Failed to register {} metrics: {:?}",
305 T::DESCRIPTION,
306 err
307 );
308 None
309 },
310 })
311}
312
313#[macro_export]
316macro_rules! metric_set {
317 ($metrics:expr, $m:ident, $v:expr) => {{
318 let val: u64 = format!("{}", $v).parse().unwrap();
319
320 if let Some(metrics) = $metrics.as_ref() {
321 metrics.$m.set(val);
322 }
323 }};
324}
325
326#[macro_export]
327macro_rules! metric_inc {
328 ($metrics:expr, $m:ident) => {{
329 if let Some(metrics) = $metrics.as_ref() {
330 metrics.$m.inc();
331 }
332 }};
333}
334
335#[macro_export]
336macro_rules! metric_get {
337 ($metrics:expr, $m:ident) => {{
338 $metrics.as_ref().map(|metrics| metrics.$m.clone())
339 }};
340}
341
342#[cfg(test)]
343pub(crate) mod tests {
344 use super::*;
345
346 #[test]
347 fn should_register_metrics() {
348 let registry = Some(Registry::new());
349 assert!(register_metrics::<VoterMetrics>(registry.clone()).is_some());
350 assert!(register_metrics::<BlockImportMetrics>(registry.clone()).is_some());
351 assert!(register_metrics::<OnDemandIncomingRequestsMetrics>(registry.clone()).is_some());
352 assert!(register_metrics::<OnDemandOutgoingRequestsMetrics>(registry.clone()).is_some());
353 }
354}