polkadot_node_core_provisioner/
metrics.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Polkadot is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16
17use crate::disputes::prioritized_selection::PartitionedDisputes;
18use polkadot_node_subsystem_util::metrics::{self, prometheus};
19
20#[derive(Clone)]
21struct MetricsInner {
22	/// Tracks successful/unsuccessful inherent data requests
23	inherent_data_requests: prometheus::CounterVec<prometheus::U64>,
24	/// How much time the `RequestInherentData` processing takes
25	request_inherent_data_duration: prometheus::Histogram,
26	/// How much time `ProvisionableData` processing takes
27	provisionable_data_duration: prometheus::Histogram,
28	/// Bitfields array length in `ProvisionerInherentData` (the result for `RequestInherentData`)
29	inherent_data_response_bitfields: prometheus::Histogram,
30
31	/// The following metrics track how many disputes/votes the runtime will have to process. These
32	/// will count all recent statements meaning every dispute from last sessions: 10 min on
33	/// Rococo, 60 min on Kusama and 4 hours on Polkadot. The metrics are updated only when the
34	/// node authors a block, so values vary across nodes.
35	inherent_data_dispute_statement_sets: prometheus::Counter<prometheus::U64>,
36	inherent_data_dispute_statements: prometheus::CounterVec<prometheus::U64>,
37
38	/// The disputes received from `disputes-coordinator` by partition
39	partitioned_disputes: prometheus::CounterVec<prometheus::U64>,
40
41	/// The disputes fetched from the runtime.
42	fetched_onchain_disputes: prometheus::Counter<prometheus::U64>,
43}
44
45/// Provisioner metrics.
46#[derive(Default, Clone)]
47pub struct Metrics(Option<MetricsInner>);
48
49impl Metrics {
50	/// Creates new dummy `Metrics` instance. Used for testing only.
51	#[cfg(test)]
52	pub fn new_dummy() -> Metrics {
53		Metrics(None)
54	}
55
56	pub(crate) fn on_inherent_data_request(&self, response: Result<(), ()>) {
57		if let Some(metrics) = &self.0 {
58			match response {
59				Ok(()) => metrics.inherent_data_requests.with_label_values(&["succeeded"]).inc(),
60				Err(()) => metrics.inherent_data_requests.with_label_values(&["failed"]).inc(),
61			}
62		}
63	}
64
65	/// Provide a timer for `request_inherent_data` which observes on drop.
66	pub(crate) fn time_request_inherent_data(
67		&self,
68	) -> Option<metrics::prometheus::prometheus::HistogramTimer> {
69		self.0
70			.as_ref()
71			.map(|metrics| metrics.request_inherent_data_duration.start_timer())
72	}
73
74	/// Provide a timer for `provisionable_data` which observes on drop.
75	pub(crate) fn time_provisionable_data(
76		&self,
77	) -> Option<metrics::prometheus::prometheus::HistogramTimer> {
78		self.0.as_ref().map(|metrics| metrics.provisionable_data_duration.start_timer())
79	}
80
81	pub(crate) fn observe_inherent_data_bitfields_count(&self, bitfields_count: usize) {
82		self.0.as_ref().map(|metrics| {
83			metrics.inherent_data_response_bitfields.observe(bitfields_count as f64)
84		});
85	}
86
87	pub(crate) fn inc_valid_statements_by(&self, votes: usize) {
88		if let Some(metrics) = &self.0 {
89			metrics
90				.inherent_data_dispute_statements
91				.with_label_values(&["valid"])
92				.inc_by(votes.try_into().unwrap_or(0));
93		}
94	}
95
96	pub(crate) fn inc_invalid_statements_by(&self, votes: usize) {
97		if let Some(metrics) = &self.0 {
98			metrics
99				.inherent_data_dispute_statements
100				.with_label_values(&["invalid"])
101				.inc_by(votes.try_into().unwrap_or(0));
102		}
103	}
104
105	pub(crate) fn inc_dispute_statement_sets_by(&self, disputes: usize) {
106		if let Some(metrics) = &self.0 {
107			metrics
108				.inherent_data_dispute_statement_sets
109				.inc_by(disputes.try_into().unwrap_or(0));
110		}
111	}
112
113	pub(crate) fn on_partition_recent_disputes(&self, disputes: &PartitionedDisputes) {
114		if let Some(metrics) = &self.0 {
115			let PartitionedDisputes {
116				inactive_unknown_onchain,
117				inactive_unconcluded_onchain: inactive_unconcluded_known_onchain,
118				active_unknown_onchain,
119				active_unconcluded_onchain,
120				active_concluded_onchain,
121				inactive_concluded_onchain: inactive_concluded_known_onchain,
122			} = disputes;
123
124			metrics
125				.partitioned_disputes
126				.with_label_values(&["inactive_unknown_onchain"])
127				.inc_by(inactive_unknown_onchain.len().try_into().unwrap_or(0));
128			metrics
129				.partitioned_disputes
130				.with_label_values(&["inactive_unconcluded_known_onchain"])
131				.inc_by(inactive_unconcluded_known_onchain.len().try_into().unwrap_or(0));
132			metrics
133				.partitioned_disputes
134				.with_label_values(&["active_unknown_onchain"])
135				.inc_by(active_unknown_onchain.len().try_into().unwrap_or(0));
136			metrics
137				.partitioned_disputes
138				.with_label_values(&["active_unconcluded_onchain"])
139				.inc_by(active_unconcluded_onchain.len().try_into().unwrap_or(0));
140			metrics
141				.partitioned_disputes
142				.with_label_values(&["active_concluded_onchain"])
143				.inc_by(active_concluded_onchain.len().try_into().unwrap_or(0));
144			metrics
145				.partitioned_disputes
146				.with_label_values(&["inactive_concluded_known_onchain"])
147				.inc_by(inactive_concluded_known_onchain.len().try_into().unwrap_or(0));
148		}
149	}
150
151	pub(crate) fn on_fetched_onchain_disputes(&self, onchain_count: u64) {
152		if let Some(metrics) = &self.0 {
153			metrics.fetched_onchain_disputes.inc_by(onchain_count);
154		}
155	}
156}
157
158impl metrics::Metrics for Metrics {
159	fn try_register(registry: &prometheus::Registry) -> Result<Self, prometheus::PrometheusError> {
160		let metrics = MetricsInner {
161			inherent_data_requests: prometheus::register(
162				prometheus::CounterVec::new(
163					prometheus::Opts::new(
164						"polkadot_parachain_inherent_data_requests_total",
165						"Number of InherentData requests served by provisioner.",
166					),
167					&["success"],
168				)?,
169				registry,
170			)?,
171			request_inherent_data_duration: prometheus::register(
172				prometheus::Histogram::with_opts(prometheus::HistogramOpts::new(
173					"polkadot_parachain_provisioner_request_inherent_data_time",
174					"Time spent within `provisioner::request_inherent_data`",
175				))?,
176				registry,
177			)?,
178			provisionable_data_duration: prometheus::register(
179				prometheus::Histogram::with_opts(prometheus::HistogramOpts::new(
180					"polkadot_parachain_provisioner_provisionable_data_time",
181					"Time spent within `provisioner::provisionable_data`",
182				))?,
183				registry,
184			)?,
185			inherent_data_dispute_statements: prometheus::register(
186				prometheus::CounterVec::new(
187					prometheus::Opts::new(
188						"polkadot_parachain_inherent_data_dispute_statements",
189						"Number of dispute statements passed to `create_inherent()`.",
190					),
191					&["validity"],
192				)?,
193				&registry,
194			)?,
195			inherent_data_dispute_statement_sets: prometheus::register(
196				prometheus::Counter::new(
197					"polkadot_parachain_inherent_data_dispute_statement_sets",
198					"Number of dispute statements sets passed to `create_inherent()`.",
199				)?,
200				registry,
201			)?,
202			inherent_data_response_bitfields: prometheus::register(
203				prometheus::Histogram::with_opts(
204					prometheus::HistogramOpts::new(
205						"polkadot_parachain_provisioner_inherent_data_response_bitfields_sent",
206						"Number of inherent bitfields sent in response to `ProvisionerMessage::RequestInherentData`.",
207					).buckets(vec![0.0, 25.0, 50.0, 100.0, 150.0, 200.0, 250.0, 300.0, 400.0, 500.0, 600.0]),
208				)?,
209				registry,
210			)?,
211			partitioned_disputes: prometheus::register(
212				prometheus::CounterVec::new(
213					prometheus::Opts::new(
214						"polkadot_parachain_provisioner_partitioned_disputes",
215						"Number of disputes partitioned by type.",
216					),
217					&["partition"],
218				)?,
219				&registry,
220			)?,
221			fetched_onchain_disputes: prometheus::register(
222				prometheus::Counter::new("polkadot_parachain_fetched_onchain_disputes", "Number of disputes fetched from the runtime"
223				)?,
224				&registry,
225			)?,
226		};
227		Ok(Metrics(Some(metrics)))
228	}
229}