referrerpolicy=no-referrer-when-downgrade

sc_consensus_beefy/
metrics.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! BEEFY Prometheus metrics definition
20
21use crate::LOG_TARGET;
22use log::{debug, error};
23use prometheus_endpoint::{register, Counter, Gauge, PrometheusError, Registry, U64};
24
25/// Helper trait for registering BEEFY metrics to Prometheus registry.
26pub(crate) trait PrometheusRegister<T: Sized = Self>: Sized {
27	const DESCRIPTION: &'static str;
28	fn register(registry: &Registry) -> Result<Self, PrometheusError>;
29}
30
31/// BEEFY voting-related metrics exposed through Prometheus
32#[derive(Clone, Debug)]
33pub struct VoterMetrics {
34	/// Current active validator set id
35	pub beefy_validator_set_id: Gauge<U64>,
36	/// Total number of votes sent by this node
37	pub beefy_votes_sent: Counter<U64>,
38	/// Best block finalized by BEEFY
39	pub beefy_best_block: Gauge<U64>,
40	/// Best block BEEFY voted on
41	pub beefy_best_voted: Gauge<U64>,
42	/// Next block BEEFY should vote on
43	pub beefy_should_vote_on: Gauge<U64>,
44	/// Number of sessions with lagging signed commitment on mandatory block
45	pub beefy_lagging_sessions: Counter<U64>,
46	/// Number of times no Authority public key found in store
47	pub beefy_no_authority_found_in_store: Counter<U64>,
48	/// Number of good votes successfully handled
49	pub beefy_good_votes_processed: Counter<U64>,
50	/// Number of equivocation votes received
51	pub beefy_equivocation_votes: Counter<U64>,
52	/// Number of invalid votes received
53	pub beefy_invalid_votes: Counter<U64>,
54	/// Number of valid but stale votes received
55	pub beefy_stale_votes: Counter<U64>,
56	/// Number of currently buffered justifications
57	pub beefy_buffered_justifications: Gauge<U64>,
58	/// Number of valid but stale justifications received
59	pub beefy_stale_justifications: Counter<U64>,
60	/// Number of valid justifications successfully imported
61	pub beefy_imported_justifications: Counter<U64>,
62	/// Number of justifications dropped due to full buffers
63	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/// BEEFY block-import-related metrics exposed through Prometheus
165#[derive(Clone, Debug)]
166pub struct BlockImportMetrics {
167	/// Number of Good Justification imports
168	pub beefy_good_justification_imports: Counter<U64>,
169	/// Number of Bad Justification imports
170	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/// BEEFY on-demand-justifications-related metrics exposed through Prometheus
196#[derive(Clone, Debug)]
197pub struct OnDemandIncomingRequestsMetrics {
198	/// Number of Successful Justification responses
199	pub beefy_successful_justification_responses: Counter<U64>,
200	/// Number of Failed Justification responses
201	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/// BEEFY on-demand-justifications-related metrics exposed through Prometheus
227#[derive(Clone, Debug)]
228pub struct OnDemandOutgoingRequestsMetrics {
229	/// Number of times there was no good peer to request justification from
230	pub beefy_on_demand_justification_no_peer_to_request_from: Counter<U64>,
231	/// Number of on-demand justification peer refused valid requests
232	pub beefy_on_demand_justification_peer_refused: Counter<U64>,
233	/// Number of on-demand justification peer error
234	pub beefy_on_demand_justification_peer_error: Counter<U64>,
235	/// Number of on-demand justification invalid proof
236	pub beefy_on_demand_justification_invalid_proof: Counter<U64>,
237	/// Number of on-demand justification good proof
238	pub beefy_on_demand_justification_good_proof: Counter<U64>,
239	/// Number of live beefy peers available for requests.
240	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// Note: we use the `format` macro to convert an expr into a `u64`. This will fail,
314// if expr does not derive `Display`.
315#[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}