cat_gateway/metrics/chain_follower/
mod.rs1use std::{
4 sync::atomic::{AtomicBool, Ordering},
5 thread,
6};
7
8use cardano_blockchain_types::Network;
9use cardano_chain_follower::Statistics;
10
11use crate::settings::Settings;
12
13mod reporter;
14
15static IS_INITIALIZED: AtomicBool = AtomicBool::new(false);
17
18pub(crate) fn init_metrics_reporter() {
23 if IS_INITIALIZED.swap(true, Ordering::SeqCst) {
24 return;
25 }
26
27 let api_host_names = Settings::api_host_names().join(",");
28 let service_id = Settings::service_id();
29 let network = Settings::cardano_network();
30
31 let network_idx = match network {
34 Network::Mainnet => 0,
35 Network::Preprod => 1,
36 Network::Preview => 2,
37 };
38
39 thread::spawn(move || {
40 loop {
41 {
42 let follower_stats = Statistics::new(network);
43
44 report_mithril(
45 &follower_stats,
46 &api_host_names,
47 service_id,
48 network,
49 network_idx,
50 );
51 report_live(
52 &follower_stats,
53 &api_host_names,
54 service_id,
55 network,
56 network_idx,
57 );
58 }
59
60 thread::sleep(Settings::metrics_follower_interval());
61 }
62 });
63}
64
65#[allow(clippy::indexing_slicing)]
67fn report_mithril(
68 stats: &Statistics,
69 api_host_names: &str,
70 service_id: &str,
71 network: Network,
72 net_idx: usize,
74) {
75 let stats = &stats.mithril;
76 let network = network.to_string();
77
78 reporter::MITHRIL_UPDATES[net_idx]
79 .with_label_values(&[api_host_names, service_id, &network])
80 .set(i64::try_from(stats.updates).unwrap_or(-1));
81 reporter::MITHRIL_TIP[net_idx]
82 .with_label_values(&[api_host_names, service_id, &network])
83 .set(i64::try_from(u64::from(stats.tip)).unwrap_or(-1));
84 reporter::MITHRIL_DL_START[net_idx]
85 .with_label_values(&[api_host_names, service_id, &network])
86 .set(stats.dl_start.timestamp());
87 reporter::MITHRIL_DL_END[net_idx]
88 .with_label_values(&[api_host_names, service_id, &network])
89 .set(stats.dl_end.timestamp());
90 reporter::MITHRIL_DL_FAILURES[net_idx]
91 .with_label_values(&[api_host_names, service_id, &network])
92 .set(i64::try_from(stats.dl_failures).unwrap_or(-1));
93 reporter::MITHRIL_LAST_DL_DURATION[net_idx]
94 .with_label_values(&[api_host_names, service_id, &network])
95 .set(i64::try_from(stats.last_dl_duration).unwrap_or(-1));
96 reporter::MITHRIL_DL_SIZE[net_idx]
97 .with_label_values(&[api_host_names, service_id, &network])
98 .set(i64::try_from(stats.dl_size).unwrap_or(-1));
99 reporter::MITHRIL_EXTRACT_START[net_idx]
100 .with_label_values(&[api_host_names, service_id, &network])
101 .set(stats.extract_start.timestamp());
102 reporter::MITHRIL_EXTRACT_END[net_idx]
103 .with_label_values(&[api_host_names, service_id, &network])
104 .set(stats.extract_end.timestamp());
105 reporter::MITHRIL_EXTRACT_FAILURES[net_idx]
106 .with_label_values(&[api_host_names, service_id, &network])
107 .set(i64::try_from(stats.extract_failures).unwrap_or(-1));
108 reporter::MITHRIL_EXTRACT_SIZE[net_idx]
109 .with_label_values(&[api_host_names, service_id, &network])
110 .set(i64::try_from(stats.extract_size).unwrap_or(-1));
111 reporter::MITHRIL_DEDUPLICATED_SIZE[net_idx]
112 .with_label_values(&[api_host_names, service_id, &network])
113 .set(i64::try_from(stats.deduplicated_size).unwrap_or(-1));
114 reporter::MITHRIL_DEDUPLICATED[net_idx]
115 .with_label_values(&[api_host_names, service_id, &network])
116 .set(i64::try_from(stats.deduplicated).unwrap_or(-1));
117 reporter::MITHRIL_CHANGED[net_idx]
118 .with_label_values(&[api_host_names, service_id, &network])
119 .set(i64::try_from(stats.changed).unwrap_or(-1));
120 reporter::MITHRIL_NEW[net_idx]
121 .with_label_values(&[api_host_names, service_id, &network])
122 .set(i64::try_from(stats.new).unwrap_or(-1));
123 reporter::MITHRIL_VALIDATE_START[net_idx]
124 .with_label_values(&[api_host_names, service_id, &network])
125 .set(stats.validate_start.timestamp());
126 reporter::MITHRIL_VALIDATE_END[net_idx]
127 .with_label_values(&[api_host_names, service_id, &network])
128 .set(stats.validate_end.timestamp());
129 reporter::MITHRIL_VALIDATE_FAILURES[net_idx]
130 .with_label_values(&[api_host_names, service_id, &network])
131 .set(i64::try_from(stats.validate_failures).unwrap_or(-1));
132 reporter::MITHRIL_INVALID_BLOCKS[net_idx]
133 .with_label_values(&[api_host_names, service_id, &network])
134 .set(i64::try_from(stats.invalid_blocks).unwrap_or(-1));
135 reporter::MITHRIL_DOWNLOAD_OR_VALIDATION_FAILED[net_idx]
136 .with_label_values(&[api_host_names, service_id, &network])
137 .set(i64::try_from(stats.download_or_validation_failed).unwrap_or(-1));
138 reporter::MITHRIL_FAILED_TO_GET_TIP[net_idx]
139 .with_label_values(&[api_host_names, service_id, &network])
140 .set(i64::try_from(stats.failed_to_get_tip).unwrap_or(-1));
141 reporter::MITHRIL_TIP_DID_NOT_ADVANCE[net_idx]
142 .with_label_values(&[api_host_names, service_id, &network])
143 .set(i64::try_from(stats.tip_did_not_advance).unwrap_or(-1));
144 reporter::MITHRIL_TIP_FAILED_TO_SEND_TO_UPDATER[net_idx]
145 .with_label_values(&[api_host_names, service_id, &network])
146 .set(i64::try_from(stats.tip_failed_to_send_to_updater).unwrap_or(-1));
147 reporter::MITHRIL_FAILED_TO_ACTIVATE_NEW_SNAPSHOT[net_idx]
148 .with_label_values(&[api_host_names, service_id, &network])
149 .set(i64::try_from(stats.failed_to_activate_new_snapshot).unwrap_or(-1));
150}
151
152#[allow(clippy::indexing_slicing)]
154fn report_live(
155 stats: &Statistics,
156 api_host_names: &str,
157 service_id: &str,
158 network: Network,
159 net_idx: usize,
161) {
162 let stats = &stats.live;
163 let network = network.to_string();
164
165 reporter::LIVE_SYNC_START[net_idx]
166 .with_label_values(&[api_host_names, service_id, &network])
167 .set(stats.sync_start.timestamp());
168 reporter::LIVE_SYNC_END[net_idx]
169 .with_label_values(&[api_host_names, service_id, &network])
170 .set(stats.sync_end.map_or(0, |s| s.timestamp()));
171 reporter::LIVE_BACKFILL_START[net_idx]
172 .with_label_values(&[api_host_names, service_id, &network])
173 .set(stats.backfill_start.map_or(0, |s| s.timestamp()));
174 reporter::LIVE_BACKFILL_SIZE[net_idx]
175 .with_label_values(&[api_host_names, service_id, &network])
176 .set(i64::try_from(stats.backfill_size).unwrap_or(-1));
177 reporter::LIVE_BACKFILL_END[net_idx]
178 .with_label_values(&[api_host_names, service_id, &network])
179 .set(stats.backfill_end.map_or(0, |s| s.timestamp()));
180 reporter::LIVE_BACKFILL_FAILURES[net_idx]
181 .with_label_values(&[api_host_names, service_id, &network])
182 .set(i64::try_from(stats.backfill_failures).unwrap_or(-1));
183 reporter::LIVE_BACKFILL_FAILURE_TIME[net_idx]
184 .with_label_values(&[api_host_names, service_id, &network])
185 .set(stats.backfill_failure_time.map_or(0, |s| s.timestamp()));
186 reporter::LIVE_BLOCKS[net_idx]
187 .with_label_values(&[api_host_names, service_id, &network])
188 .set(i64::try_from(stats.blocks).unwrap_or(-1));
189 reporter::LIVE_HEAD_SLOT[net_idx]
190 .with_label_values(&[api_host_names, service_id, &network])
191 .set(i64::try_from(u64::from(stats.head_slot)).unwrap_or(-1));
192 reporter::LIVE_TIP[net_idx]
193 .with_label_values(&[api_host_names, service_id, &network])
194 .set(i64::try_from(u64::from(stats.tip)).unwrap_or(-1));
195 reporter::LIVE_RECONNECTS[net_idx]
196 .with_label_values(&[api_host_names, service_id, &network])
197 .set(i64::try_from(stats.reconnects).unwrap_or(-1));
198 reporter::LIVE_LAST_CONNECT[net_idx]
199 .with_label_values(&[api_host_names, service_id, &network])
200 .set(stats.last_connect.timestamp());
201 reporter::LIVE_LAST_DISCONNECT[net_idx]
202 .with_label_values(&[api_host_names, service_id, &network])
203 .set(stats.last_disconnect.timestamp());
204 reporter::LIVE_CONNECTED[net_idx]
205 .with_label_values(&[api_host_names, service_id, &network])
206 .set(i64::from(stats.connected));
207 reporter::LIVE_ROLLBACKS_LIVE_COUNT[net_idx]
208 .with_label_values(&[api_host_names, service_id, &network])
209 .set(i64::try_from(stats.rollbacks.live.len()).unwrap_or(-1));
210 reporter::LIVE_ROLLBACKS_PEER_COUNT[net_idx]
211 .with_label_values(&[api_host_names, service_id, &network])
212 .set(i64::try_from(stats.rollbacks.peer.len()).unwrap_or(-1));
213 reporter::LIVE_ROLLBACKS_FOLLOWER_COUNT[net_idx]
214 .with_label_values(&[api_host_names, service_id, &network])
215 .set(i64::try_from(stats.rollbacks.follower.len()).unwrap_or(-1));
216 reporter::LIVE_NEW_BLOCKS[net_idx]
217 .with_label_values(&[api_host_names, service_id, &network])
218 .set(i64::try_from(stats.new_blocks).unwrap_or(-1));
219 reporter::LIVE_INVALID_BLOCKS[net_idx]
220 .with_label_values(&[api_host_names, service_id, &network])
221 .set(i64::try_from(stats.invalid_blocks).unwrap_or(-1));
222 reporter::LIVE_FOLLOWER_COUNT[net_idx]
223 .with_label_values(&[api_host_names, service_id, &network])
224 .set(i64::try_from(stats.follower.len()).unwrap_or(-1));
225}