referrerpolicy=no-referrer-when-downgrade
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.

//! The Metrics for Approval Voting Parallel Subsystem.

use std::collections::HashMap;

use polkadot_node_metrics::{metered::Meter, metrics};
use polkadot_overseer::prometheus;

#[derive(Default, Clone)]
pub struct Metrics(Option<MetricsInner>);

/// Approval Voting parallel metrics.
#[derive(Clone)]
pub struct MetricsInner {
	// The inner metrics of the approval distribution workers.
	approval_distribution: polkadot_approval_distribution::metrics::Metrics,
	// The inner metrics of the approval voting workers.
	approval_voting: polkadot_node_core_approval_voting::Metrics,

	// Time of flight metrics for bounded channels.
	to_worker_bounded_tof: prometheus::HistogramVec,
	// Number of elements sent to the worker's bounded queue.
	to_worker_bounded_sent: prometheus::GaugeVec<prometheus::U64>,
	// Number of elements received by the worker's bounded queue.
	to_worker_bounded_received: prometheus::GaugeVec<prometheus::U64>,
	// Number of times senders blocked while sending messages to the worker.
	to_worker_bounded_blocked: prometheus::GaugeVec<prometheus::U64>,
	// Time of flight metrics for unbounded channels.
	to_worker_unbounded_tof: prometheus::HistogramVec,
	// Number of elements sent to the worker's unbounded queue.
	to_worker_unbounded_sent: prometheus::GaugeVec<prometheus::U64>,
	// Number of elements received by the worker's unbounded queue.
	to_worker_unbounded_received: prometheus::GaugeVec<prometheus::U64>,
}

impl Metrics {
	/// Get the approval distribution metrics.
	pub fn approval_distribution_metrics(
		&self,
	) -> polkadot_approval_distribution::metrics::Metrics {
		self.0
			.as_ref()
			.map(|metrics_inner| metrics_inner.approval_distribution.clone())
			.unwrap_or_default()
	}

	/// Get the approval voting metrics.
	pub fn approval_voting_metrics(&self) -> polkadot_node_core_approval_voting::Metrics {
		self.0
			.as_ref()
			.map(|metrics_inner| metrics_inner.approval_voting.clone())
			.unwrap_or_default()
	}
}

impl metrics::Metrics for Metrics {
	/// Try to register the metrics.
	fn try_register(
		registry: &prometheus::Registry,
	) -> std::result::Result<Self, prometheus::PrometheusError> {
		Ok(Metrics(Some(MetricsInner {
			approval_distribution: polkadot_approval_distribution::metrics::Metrics::try_register(
				registry,
			)?,
			approval_voting: polkadot_node_core_approval_voting::Metrics::try_register(registry)?,
			to_worker_bounded_tof: prometheus::register(
				prometheus::HistogramVec::new(
					prometheus::HistogramOpts::new(
						"polkadot_approval_voting_parallel_worker_bounded_tof",
						"Duration spent in a particular approval voting worker channel from entrance to removal",
					)
					.buckets(vec![
						0.0001, 0.0004, 0.0016, 0.0064, 0.0256, 0.1024, 0.4096, 1.6384, 3.2768,
						4.9152, 6.5536,
					]),
					&["worker_name"],
				)?,
				registry,
			)?,
			to_worker_bounded_sent: prometheus::register(
				prometheus::GaugeVec::<prometheus::U64>::new(
					prometheus::Opts::new(
						"polkadot_approval_voting_parallel_worker_bounded_sent",
						"Number of elements sent to approval voting workers' bounded queues",
					),
					&["worker_name"],
				)?,
				registry,
			)?,
			to_worker_bounded_received: prometheus::register(
				prometheus::GaugeVec::<prometheus::U64>::new(
					prometheus::Opts::new(
						"polkadot_approval_voting_parallel_worker_bounded_received",
						"Number of elements received by approval voting workers' bounded queues",
					),
					&["worker_name"],
				)?,
				registry,
			)?,
			to_worker_bounded_blocked: prometheus::register(
				prometheus::GaugeVec::<prometheus::U64>::new(
					prometheus::Opts::new(
						"polkadot_approval_voting_parallel_worker_bounded_blocked",
						"Number of times approval voting workers blocked while sending messages to a subsystem",
					),
					&["worker_name"],
				)?,
				registry,
			)?,
			to_worker_unbounded_tof: prometheus::register(
				prometheus::HistogramVec::new(
					prometheus::HistogramOpts::new(
						"polkadot_approval_voting_parallel_worker_unbounded_tof",
						"Duration spent in a particular approval voting worker channel from entrance to removal",
					)
					.buckets(vec![
						0.0001, 0.0004, 0.0016, 0.0064, 0.0256, 0.1024, 0.4096, 1.6384, 3.2768,
						4.9152, 6.5536,
					]),
					&["worker_name"],
				)?,
				registry,
			)?,
			to_worker_unbounded_sent: prometheus::register(
				prometheus::GaugeVec::<prometheus::U64>::new(
					prometheus::Opts::new(
						"polkadot_approval_voting_parallel_worker_unbounded_sent",
						"Number of elements sent to approval voting workers' unbounded queues",
					),
					&["worker_name"],
				)?,
				registry,
			)?,
			to_worker_unbounded_received: prometheus::register(
				prometheus::GaugeVec::<prometheus::U64>::new(
					prometheus::Opts::new(
						"polkadot_approval_voting_parallel_worker_unbounded_received",
						"Number of elements received by approval voting workers' unbounded queues",
					),
					&["worker_name"],
				)?,
				registry,
			)?,
		})))
	}
}

/// The meters to watch.
#[derive(Clone)]
pub struct Meters {
	bounded: Meter,
	unbounded: Meter,
}

impl Meters {
	pub fn new(bounded: &Meter, unbounded: &Meter) -> Self {
		Self { bounded: bounded.clone(), unbounded: unbounded.clone() }
	}
}

/// A metrics watcher that watches the meters and updates the metrics.
pub struct MetricsWatcher {
	to_watch: HashMap<String, Meters>,
	metrics: Metrics,
}

impl MetricsWatcher {
	/// Create a new metrics watcher.
	pub fn new(metrics: Metrics) -> Self {
		Self { to_watch: HashMap::new(), metrics }
	}

	/// Watch the meters of a worker with this name.
	pub fn watch(&mut self, worker_name: String, meters: Meters) {
		self.to_watch.insert(worker_name, meters);
	}

	/// Collect all the metrics.
	pub fn collect_metrics(&self) {
		for (name, meter) in &self.to_watch {
			let bounded_readouts = meter.bounded.read();
			let unbounded_readouts = meter.unbounded.read();
			if let Some(metrics) = self.metrics.0.as_ref() {
				metrics
					.to_worker_bounded_sent
					.with_label_values(&[name])
					.set(bounded_readouts.sent as u64);

				metrics
					.to_worker_bounded_received
					.with_label_values(&[name])
					.set(bounded_readouts.received as u64);

				metrics
					.to_worker_bounded_blocked
					.with_label_values(&[name])
					.set(bounded_readouts.blocked as u64);

				metrics
					.to_worker_unbounded_sent
					.with_label_values(&[name])
					.set(unbounded_readouts.sent as u64);

				metrics
					.to_worker_unbounded_received
					.with_label_values(&[name])
					.set(unbounded_readouts.received as u64);

				let hist_bounded = metrics.to_worker_bounded_tof.with_label_values(&[name]);
				for tof in bounded_readouts.tof {
					hist_bounded.observe(tof.as_f64());
				}

				let hist_unbounded = metrics.to_worker_unbounded_tof.with_label_values(&[name]);
				for tof in unbounded_readouts.tof {
					hist_unbounded.observe(tof.as_f64());
				}
			}
		}
	}
}