1use prometheus::{Gauge, Registry, Opts};
2
3use crate::Error;
4
5pub struct BitcoinMetrics {
6 pub registry: Registry,
7
8 pub blocks: Gauge,
10 pub headers: Gauge,
11 pub difficulty: Gauge,
12 pub verification_progress: Gauge,
13 pub size_on_disk: Gauge,
14 pub initial_block_download: Gauge,
15 pub chain_pruned: Gauge,
16
17 pub mempool_transactions: Gauge,
19 pub mempool_bytes: Gauge,
20 pub mempool_usage: Gauge,
21 pub mempool_max_bytes: Gauge,
22 pub mempool_min_fee: Gauge,
23 pub mempool_total_fee: Gauge,
24 pub mempool_min_relay_tx_fee: Gauge,
25 pub mempool_incremental_relay_fee: Gauge,
26 pub mempool_unbroadcast_count: Gauge,
27 pub mempool_full_rbf: Gauge,
28
29 pub connections: Gauge,
31 pub connections_in: Gauge,
32 pub connections_out: Gauge,
33 pub network_active: Gauge,
34 pub node_version: Gauge,
35 pub protocol_version: Gauge,
36 pub time_offset: Gauge,
37 pub relay_fee: Gauge,
38 pub incremental_fee: Gauge,
39
40 pub peer_count: Gauge,
42 pub peers_inbound: Gauge,
43 pub peers_outbound: Gauge,
44 pub peers_total_bytes_sent: Gauge,
45 pub peers_total_bytes_received: Gauge,
46 pub peers_avg_ping_seconds: Gauge,
47
48 pub network_hash_ps: Gauge,
50 pub mining_pooled_tx: Gauge,
51
52 pub chain_tx_count: Gauge,
54 pub chain_tx_rate: Gauge,
55 pub chain_tx_window_block_count: Gauge,
56 pub chain_tx_window_tx_count: Gauge,
57 pub chain_tx_window_interval: Gauge,
58
59 pub net_total_bytes_received: Gauge,
61 pub net_total_bytes_sent: Gauge,
62
63 pub fee_estimate_2_blocks: Gauge,
65 pub fee_estimate_6_blocks: Gauge,
66 pub fee_estimate_12_blocks: Gauge,
67 pub fee_estimate_144_blocks: Gauge,
68
69 pub chain_tips_count: Gauge,
71
72 pub node_uptime_seconds: Gauge,
74
75 pub latest_block_txs: Gauge,
77 pub latest_block_size: Gauge,
78 pub latest_block_weight: Gauge,
79 pub latest_block_avg_fee: Gauge,
80 pub latest_block_avg_fee_rate: Gauge,
81 pub latest_block_median_fee: Gauge,
82 pub latest_block_min_fee: Gauge,
83 pub latest_block_max_fee: Gauge,
84 pub latest_block_min_fee_rate: Gauge,
85 pub latest_block_max_fee_rate: Gauge,
86 pub latest_block_total_fee: Gauge,
87 pub latest_block_subsidy: Gauge,
88 pub latest_block_inputs: Gauge,
89 pub latest_block_outputs: Gauge,
90 pub latest_block_segwit_txs: Gauge,
91 pub latest_block_segwit_total_size: Gauge,
92 pub latest_block_segwit_total_weight: Gauge,
93 pub latest_block_total_out: Gauge,
94 pub latest_block_utxo_increase: Gauge,
95 pub latest_block_fee_rate_10th: Gauge,
96 pub latest_block_fee_rate_25th: Gauge,
97 pub latest_block_fee_rate_50th: Gauge,
98 pub latest_block_fee_rate_75th: Gauge,
99 pub latest_block_fee_rate_90th: Gauge,
100
101 pub scrape_duration_seconds: Gauge,
103 pub scrape_error: Gauge,
104}
105
106macro_rules! register_gauge {
107 ($registry:expr, $name:expr, $help:expr) => {{
108 let gauge = Gauge::with_opts(Opts::new($name, $help))?;
109 $registry.register(Box::new(gauge.clone()))?;
110 gauge
111 }};
112}
113
114impl BitcoinMetrics {
115 pub fn new() -> Result<Self, Error> {
116 let registry = Registry::new();
117
118 let blocks = register_gauge!(registry, "bitcoin_blocks", "Current block height");
120 let headers = register_gauge!(registry, "bitcoin_headers", "Current number of headers");
121 let difficulty = register_gauge!(registry, "bitcoin_difficulty", "Current mining difficulty");
122 let verification_progress = register_gauge!(registry, "bitcoin_verification_progress", "Estimate of verification progress [0..1]");
123 let size_on_disk = register_gauge!(registry, "bitcoin_size_on_disk_bytes", "Estimated size of the block and undo files on disk");
124 let initial_block_download = register_gauge!(registry, "bitcoin_initial_block_download", "Whether node is in initial block download (1=true, 0=false)");
125 let chain_pruned = register_gauge!(registry, "bitcoin_chain_pruned", "Whether the blockchain is pruned (1=true, 0=false)");
126
127 let mempool_transactions = register_gauge!(registry, "bitcoin_mempool_transactions", "Current number of transactions in the mempool");
129 let mempool_bytes = register_gauge!(registry, "bitcoin_mempool_bytes", "Sum of all virtual transaction sizes in the mempool");
130 let mempool_usage = register_gauge!(registry, "bitcoin_mempool_usage_bytes", "Total memory usage for the mempool");
131 let mempool_max_bytes = register_gauge!(registry, "bitcoin_mempool_max_bytes", "Maximum memory usage for the mempool");
132 let mempool_min_fee = register_gauge!(registry, "bitcoin_mempool_min_fee_btc_per_kvb", "Minimum fee rate in BTC/kvB for tx to be accepted");
133 let mempool_total_fee = register_gauge!(registry, "bitcoin_mempool_total_fee_btc", "Total fees of all transactions in the mempool in BTC");
134 let mempool_min_relay_tx_fee = register_gauge!(registry, "bitcoin_mempool_min_relay_tx_fee_btc_per_kvb", "Minimum relay transaction fee in BTC/kvB");
135 let mempool_incremental_relay_fee = register_gauge!(registry, "bitcoin_mempool_incremental_relay_fee_btc_per_kvb", "Minimum fee rate increment for mempool limiting or BIP 125 replacement in BTC/kvB");
136 let mempool_unbroadcast_count = register_gauge!(registry, "bitcoin_mempool_unbroadcast_count", "Number of transactions that haven't been broadcast yet");
137 let mempool_full_rbf = register_gauge!(registry, "bitcoin_mempool_full_rbf", "Whether full replace-by-fee is enabled (1=true, 0=false)");
138
139 let connections = register_gauge!(registry, "bitcoin_connections", "Total number of connections");
141 let connections_in = register_gauge!(registry, "bitcoin_connections_in", "Number of inbound connections");
142 let connections_out = register_gauge!(registry, "bitcoin_connections_out", "Number of outbound connections");
143 let network_active = register_gauge!(registry, "bitcoin_network_active", "Whether p2p networking is active (1=true, 0=false)");
144 let node_version = register_gauge!(registry, "bitcoin_version", "Bitcoin node version as integer");
145 let protocol_version = register_gauge!(registry, "bitcoin_protocol_version", "Protocol version number");
146 let time_offset = register_gauge!(registry, "bitcoin_time_offset_seconds", "Time offset from network median in seconds");
147 let relay_fee = register_gauge!(registry, "bitcoin_relay_fee_btc_per_kvb", "Minimum relay fee for transactions in BTC/kvB");
148 let incremental_fee = register_gauge!(registry, "bitcoin_incremental_fee_btc_per_kvb", "Minimum fee increment for mempool limiting in BTC/kvB");
149
150 let peer_count = register_gauge!(registry, "bitcoin_peer_count", "Number of connected peers");
152 let peers_inbound = register_gauge!(registry, "bitcoin_peers_inbound", "Number of inbound peers");
153 let peers_outbound = register_gauge!(registry, "bitcoin_peers_outbound", "Number of outbound peers");
154 let peers_total_bytes_sent = register_gauge!(registry, "bitcoin_peers_total_bytes_sent", "Total bytes sent across all peers");
155 let peers_total_bytes_received = register_gauge!(registry, "bitcoin_peers_total_bytes_received", "Total bytes received across all peers");
156 let peers_avg_ping_seconds = register_gauge!(registry, "bitcoin_peers_avg_ping_seconds", "Average ping time across all peers in seconds");
157
158 let network_hash_ps = register_gauge!(registry, "bitcoin_network_hash_per_second", "Estimated network hashes per second");
160 let mining_pooled_tx = register_gauge!(registry, "bitcoin_mining_pooled_transactions", "Number of transactions in the mining pool");
161
162 let chain_tx_count = register_gauge!(registry, "bitcoin_chain_tx_count", "Total number of transactions in the chain");
164 let chain_tx_rate = register_gauge!(registry, "bitcoin_chain_tx_rate_per_second", "Average transaction rate per second over the window");
165 let chain_tx_window_block_count = register_gauge!(registry, "bitcoin_chain_tx_window_block_count", "Number of blocks in the stats window");
166 let chain_tx_window_tx_count = register_gauge!(registry, "bitcoin_chain_tx_window_tx_count", "Number of transactions in the stats window");
167 let chain_tx_window_interval = register_gauge!(registry, "bitcoin_chain_tx_window_interval_seconds", "Elapsed time of the stats window in seconds");
168
169 let net_total_bytes_received = register_gauge!(registry, "bitcoin_net_total_bytes_received", "Total bytes received since node start");
171 let net_total_bytes_sent = register_gauge!(registry, "bitcoin_net_total_bytes_sent", "Total bytes sent since node start");
172
173 let fee_estimate_2_blocks = register_gauge!(registry, "bitcoin_fee_estimate_2_blocks_btc_per_kvb", "Estimated fee rate for confirmation within 2 blocks in BTC/kvB");
175 let fee_estimate_6_blocks = register_gauge!(registry, "bitcoin_fee_estimate_6_blocks_btc_per_kvb", "Estimated fee rate for confirmation within 6 blocks in BTC/kvB");
176 let fee_estimate_12_blocks = register_gauge!(registry, "bitcoin_fee_estimate_12_blocks_btc_per_kvb", "Estimated fee rate for confirmation within 12 blocks in BTC/kvB");
177 let fee_estimate_144_blocks = register_gauge!(registry, "bitcoin_fee_estimate_144_blocks_btc_per_kvb", "Estimated fee rate for confirmation within 144 blocks in BTC/kvB");
178
179 let chain_tips_count = register_gauge!(registry, "bitcoin_chain_tips_count", "Number of known chain tips (forks)");
181
182 let node_uptime_seconds = register_gauge!(registry, "bitcoin_node_uptime_seconds", "Node uptime in seconds");
184
185 let latest_block_txs = register_gauge!(registry, "bitcoin_latest_block_transactions", "Number of transactions in the latest block");
187 let latest_block_size = register_gauge!(registry, "bitcoin_latest_block_size_bytes", "Total size of the latest block in bytes");
188 let latest_block_weight = register_gauge!(registry, "bitcoin_latest_block_weight", "Total weight of the latest block");
189 let latest_block_avg_fee = register_gauge!(registry, "bitcoin_latest_block_avg_fee_sat", "Average fee per transaction in the latest block in satoshis");
190 let latest_block_avg_fee_rate = register_gauge!(registry, "bitcoin_latest_block_avg_fee_rate_sat_per_vb", "Average fee rate in the latest block in sat/vB");
191 let latest_block_median_fee = register_gauge!(registry, "bitcoin_latest_block_median_fee_sat", "Median fee in the latest block in satoshis");
192 let latest_block_min_fee = register_gauge!(registry, "bitcoin_latest_block_min_fee_sat", "Minimum fee in the latest block in satoshis");
193 let latest_block_max_fee = register_gauge!(registry, "bitcoin_latest_block_max_fee_sat", "Maximum fee in the latest block in satoshis");
194 let latest_block_min_fee_rate = register_gauge!(registry, "bitcoin_latest_block_min_fee_rate_sat_per_vb", "Minimum fee rate in the latest block in sat/vB");
195 let latest_block_max_fee_rate = register_gauge!(registry, "bitcoin_latest_block_max_fee_rate_sat_per_vb", "Maximum fee rate in the latest block in sat/vB");
196 let latest_block_total_fee = register_gauge!(registry, "bitcoin_latest_block_total_fee_sat", "Total fees in the latest block in satoshis");
197 let latest_block_subsidy = register_gauge!(registry, "bitcoin_latest_block_subsidy_sat", "Block subsidy (reward) of the latest block in satoshis");
198 let latest_block_inputs = register_gauge!(registry, "bitcoin_latest_block_inputs", "Number of inputs in the latest block (excluding coinbase)");
199 let latest_block_outputs = register_gauge!(registry, "bitcoin_latest_block_outputs", "Number of outputs in the latest block");
200 let latest_block_segwit_txs = register_gauge!(registry, "bitcoin_latest_block_segwit_transactions", "Number of segwit transactions in the latest block");
201 let latest_block_segwit_total_size = register_gauge!(registry, "bitcoin_latest_block_segwit_total_size_bytes", "Total size of segwit transactions in the latest block");
202 let latest_block_segwit_total_weight = register_gauge!(registry, "bitcoin_latest_block_segwit_total_weight", "Total weight of segwit transactions in the latest block");
203 let latest_block_total_out = register_gauge!(registry, "bitcoin_latest_block_total_out_sat", "Total output value in the latest block in satoshis (excluding coinbase)");
204 let latest_block_utxo_increase = register_gauge!(registry, "bitcoin_latest_block_utxo_increase", "Change in UTXO count from the latest block");
205 let latest_block_fee_rate_10th = register_gauge!(registry, "bitcoin_latest_block_fee_rate_10th_percentile_sat_per_vb", "10th percentile fee rate in the latest block in sat/vB");
206 let latest_block_fee_rate_25th = register_gauge!(registry, "bitcoin_latest_block_fee_rate_25th_percentile_sat_per_vb", "25th percentile fee rate in the latest block in sat/vB");
207 let latest_block_fee_rate_50th = register_gauge!(registry, "bitcoin_latest_block_fee_rate_50th_percentile_sat_per_vb", "50th percentile (median) fee rate in the latest block in sat/vB");
208 let latest_block_fee_rate_75th = register_gauge!(registry, "bitcoin_latest_block_fee_rate_75th_percentile_sat_per_vb", "75th percentile fee rate in the latest block in sat/vB");
209 let latest_block_fee_rate_90th = register_gauge!(registry, "bitcoin_latest_block_fee_rate_90th_percentile_sat_per_vb", "90th percentile fee rate in the latest block in sat/vB");
210
211 let scrape_duration_seconds = register_gauge!(registry, "bitcoin_collector_last_scrape_duration_seconds", "Duration of the last metrics collection in seconds");
213 let scrape_error = register_gauge!(registry, "bitcoin_collector_last_scrape_error", "Whether the last scrape had an error (1=error, 0=ok)");
214
215 Ok(Self {
216 registry,
217 blocks,
218 headers,
219 difficulty,
220 verification_progress,
221 size_on_disk,
222 initial_block_download,
223 chain_pruned,
224 mempool_transactions,
225 mempool_bytes,
226 mempool_usage,
227 mempool_max_bytes,
228 mempool_min_fee,
229 mempool_total_fee,
230 mempool_min_relay_tx_fee,
231 mempool_incremental_relay_fee,
232 mempool_unbroadcast_count,
233 mempool_full_rbf,
234 connections,
235 connections_in,
236 connections_out,
237 network_active,
238 node_version,
239 protocol_version,
240 time_offset,
241 relay_fee,
242 incremental_fee,
243 peer_count,
244 peers_inbound,
245 peers_outbound,
246 peers_total_bytes_sent,
247 peers_total_bytes_received,
248 peers_avg_ping_seconds,
249 network_hash_ps,
250 mining_pooled_tx,
251 chain_tx_count,
252 chain_tx_rate,
253 chain_tx_window_block_count,
254 chain_tx_window_tx_count,
255 chain_tx_window_interval,
256 net_total_bytes_received,
257 net_total_bytes_sent,
258 fee_estimate_2_blocks,
259 fee_estimate_6_blocks,
260 fee_estimate_12_blocks,
261 fee_estimate_144_blocks,
262 chain_tips_count,
263 node_uptime_seconds,
264 latest_block_txs,
265 latest_block_size,
266 latest_block_weight,
267 latest_block_avg_fee,
268 latest_block_avg_fee_rate,
269 latest_block_median_fee,
270 latest_block_min_fee,
271 latest_block_max_fee,
272 latest_block_min_fee_rate,
273 latest_block_max_fee_rate,
274 latest_block_total_fee,
275 latest_block_subsidy,
276 latest_block_inputs,
277 latest_block_outputs,
278 latest_block_segwit_txs,
279 latest_block_segwit_total_size,
280 latest_block_segwit_total_weight,
281 latest_block_total_out,
282 latest_block_utxo_increase,
283 latest_block_fee_rate_10th,
284 latest_block_fee_rate_25th,
285 latest_block_fee_rate_50th,
286 latest_block_fee_rate_75th,
287 latest_block_fee_rate_90th,
288 scrape_duration_seconds,
289 scrape_error,
290 })
291 }
292}