amareleo_node_metrics/
lib.rs1mod names;
17
18pub use names::*;
20
21pub use snarkvm::metrics::*;
23
24#[cfg(not(feature = "serial"))]
25use rayon::prelude::*;
26
27#[cfg(feature = "locktick")]
28use locktick::parking_lot::Mutex;
29#[cfg(not(feature = "locktick"))]
30use parking_lot::Mutex;
31use snarkvm::{
32 ledger::narwhal::TransmissionID,
33 prelude::{Block, Network, cfg_iter},
34};
35use std::{
36 collections::HashMap,
37 net::SocketAddr,
38 sync::{
39 Arc,
40 atomic::{AtomicUsize, Ordering},
41 },
42};
43use time::OffsetDateTime;
44
45pub fn initialize_metrics(ip: Option<SocketAddr>) {
47 let builder = metrics_exporter_prometheus::PrometheusBuilder::new();
49 if let Some(ip) = ip { builder.with_http_listener(ip) } else { builder }
50 .install()
51 .expect("can't build the prometheus exporter");
52
53 snarkvm::metrics::register_metrics();
55
56 for name in crate::names::GAUGE_NAMES {
58 register_gauge(name);
59 }
60 for name in crate::names::COUNTER_NAMES {
61 register_counter(name);
62 }
63 for name in crate::names::HISTOGRAM_NAMES {
64 register_histogram(name);
65 }
66}
67
68pub fn update_block_metrics<N: Network>(block: &Block<N>) {
69 use snarkvm::ledger::ConfirmedTransaction;
70
71 let accepted_deploy = AtomicUsize::new(0);
72 let accepted_execute = AtomicUsize::new(0);
73 let rejected_deploy = AtomicUsize::new(0);
74 let rejected_execute = AtomicUsize::new(0);
75
76 cfg_iter!(block.transactions()).for_each(|tx| match tx {
78 ConfirmedTransaction::AcceptedDeploy(_, _, _) => {
79 accepted_deploy.fetch_add(1, Ordering::Relaxed);
80 }
81 ConfirmedTransaction::AcceptedExecute(_, _, _) => {
82 accepted_execute.fetch_add(1, Ordering::Relaxed);
83 }
84 ConfirmedTransaction::RejectedDeploy(_, _, _, _) => {
85 rejected_deploy.fetch_add(1, Ordering::Relaxed);
86 }
87 ConfirmedTransaction::RejectedExecute(_, _, _, _) => {
88 rejected_execute.fetch_add(1, Ordering::Relaxed);
89 }
90 });
91
92 increment_gauge(blocks::ACCEPTED_DEPLOY, accepted_deploy.load(Ordering::Relaxed) as f64);
93 increment_gauge(blocks::ACCEPTED_EXECUTE, accepted_execute.load(Ordering::Relaxed) as f64);
94 increment_gauge(blocks::REJECTED_DEPLOY, rejected_deploy.load(Ordering::Relaxed) as f64);
95 increment_gauge(blocks::REJECTED_EXECUTE, rejected_execute.load(Ordering::Relaxed) as f64);
96
97 increment_gauge(blocks::ABORTED_TRANSACTIONS, block.aborted_transaction_ids().len() as f64);
99 increment_gauge(blocks::ABORTED_SOLUTIONS, block.aborted_solution_ids().len() as f64);
100}
101
102pub fn add_transmission_latency_metric<N: Network>(
103 transmissions_queue_timestamps: &Arc<Mutex<HashMap<TransmissionID<N>, i64>>>,
104 block: &Block<N>,
105) {
106 const AGE_THRESHOLD_SECONDS: i32 = 30 * 60; let solution_ids: std::collections::HashSet<_> =
110 block.solutions().solution_ids().chain(block.aborted_solution_ids()).collect();
111
112 let transaction_ids: std::collections::HashSet<_> =
114 block.transaction_ids().chain(block.aborted_transaction_ids()).collect();
115
116 let mut transmission_queue_timestamps = transmissions_queue_timestamps.lock();
117 let ts_now = OffsetDateTime::now_utc().unix_timestamp();
118
119 let keys_to_remove = cfg_iter!(transmission_queue_timestamps)
121 .flat_map(|(key, timestamp)| {
122 let elapsed_time = std::time::Duration::from_secs((ts_now - *timestamp) as u64);
123
124 if elapsed_time.as_secs() > AGE_THRESHOLD_SECONDS as u64 {
125 increment_counter(consensus::STALE_UNCONFIRMED_TRANSMISSIONS);
127 Some(*key)
128 } else {
129 let transmission_type = match key {
130 TransmissionID::Solution(solution_id, _) if solution_ids.contains(solution_id) => Some("solution"),
131 TransmissionID::Transaction(transaction_id, _) if transaction_ids.contains(transaction_id) => {
132 Some("transaction")
133 }
134 _ => None,
135 };
136
137 if let Some(transmission_type_string) = transmission_type {
138 histogram_label(
139 consensus::TRANSMISSION_LATENCY,
140 "transmission_type",
141 transmission_type_string.to_owned(),
142 elapsed_time.as_secs_f64(),
143 );
144 Some(*key)
145 } else {
146 None
147 }
148 }
149 })
150 .collect::<Vec<_>>();
151
152 for key in keys_to_remove {
154 transmission_queue_timestamps.remove(&key);
155 }
156}