reth_network/metrics.rs
1use metrics::Histogram;
2use reth_eth_wire::DisconnectReason;
3use reth_ethereum_primitives::TxType;
4use reth_metrics::{
5 metrics::{Counter, Gauge},
6 Metrics,
7};
8
9/// Scope for monitoring transactions sent from the manager to the tx manager
10pub(crate) const NETWORK_POOL_TRANSACTIONS_SCOPE: &str = "network.pool.transactions";
11
12/// Metrics for the entire network, handled by `NetworkManager`
13#[derive(Metrics)]
14#[metrics(scope = "network")]
15pub struct NetworkMetrics {
16 /// Number of currently connected peers
17 pub(crate) connected_peers: Gauge,
18
19 /// Number of currently backed off peers
20 pub(crate) backed_off_peers: Gauge,
21
22 /// Number of peers known to the node
23 pub(crate) tracked_peers: Gauge,
24
25 /// Number of active incoming connections
26 pub(crate) incoming_connections: Gauge,
27
28 /// Number of active outgoing connections
29 pub(crate) outgoing_connections: Gauge,
30
31 /// Number of currently pending outgoing connections
32 pub(crate) pending_outgoing_connections: Gauge,
33
34 /// Total number of pending connections, incoming and outgoing.
35 pub(crate) total_pending_connections: Gauge,
36
37 /// Total Number of incoming connections handled
38 pub(crate) total_incoming_connections: Counter,
39
40 /// Total Number of outgoing connections established
41 pub(crate) total_outgoing_connections: Counter,
42
43 /// Number of invalid/malformed messages received from peers
44 pub(crate) invalid_messages_received: Counter,
45
46 /// Number of Eth Requests dropped due to channel being at full capacity
47 pub(crate) total_dropped_eth_requests_at_full_capacity: Counter,
48
49 /* ================ POLL DURATION ================ */
50
51 /* -- Total poll duration of `NetworksManager` future -- */
52 /// Duration in seconds of call to
53 /// [`NetworkManager`](crate::NetworkManager)'s poll function.
54 ///
55 /// True duration of this call, should be sum of the accumulated durations of calling nested
56 // items.
57 pub(crate) duration_poll_network_manager: Gauge,
58
59 /* -- Poll duration of items nested in `NetworkManager` future -- */
60 /// Time spent streaming messages sent over the [`NetworkHandle`](crate::NetworkHandle), which
61 /// can be cloned and shared via [`NetworkManager::handle`](crate::NetworkManager::handle), in
62 /// one call to poll the [`NetworkManager`](crate::NetworkManager) future. At least
63 /// [`TransactionsManager`](crate::transactions::TransactionsManager) holds this handle.
64 ///
65 /// Duration in seconds.
66 pub(crate) acc_duration_poll_network_handle: Gauge,
67 /// Time spent polling [`Swarm`](crate::swarm::Swarm), in one call to poll the
68 /// [`NetworkManager`](crate::NetworkManager) future.
69 ///
70 /// Duration in seconds.
71 pub(crate) acc_duration_poll_swarm: Gauge,
72}
73
74/// Metrics for closed sessions, split by direction.
75#[derive(Debug)]
76pub struct ClosedSessionsMetrics {
77 /// Sessions closed from active (established) connections.
78 pub active: Counter,
79 /// Sessions closed from incoming pending connections.
80 pub incoming_pending: Counter,
81 /// Sessions closed from outgoing pending connections.
82 pub outgoing_pending: Counter,
83}
84
85impl Default for ClosedSessionsMetrics {
86 fn default() -> Self {
87 Self {
88 active: metrics::counter!("network_closed_sessions", "direction" => "active"),
89 incoming_pending: metrics::counter!("network_closed_sessions", "direction" => "incoming_pending"),
90 outgoing_pending: metrics::counter!("network_closed_sessions", "direction" => "outgoing_pending"),
91 }
92 }
93}
94
95/// Metrics for pending session failures, split by direction.
96#[derive(Debug)]
97pub struct PendingSessionFailureMetrics {
98 /// Failures on incoming pending sessions.
99 pub inbound: Counter,
100 /// Failures on outgoing pending sessions.
101 pub outbound: Counter,
102}
103
104impl Default for PendingSessionFailureMetrics {
105 fn default() -> Self {
106 Self {
107 inbound: metrics::counter!("network_pending_session_failures", "direction" => "inbound"),
108 outbound: metrics::counter!("network_pending_session_failures", "direction" => "outbound"),
109 }
110 }
111}
112
113/// Metrics for backed off peers, split by reason.
114#[derive(Metrics)]
115#[metrics(scope = "network.backed_off_peers")]
116pub struct BackedOffPeersMetrics {
117 /// Peers backed off because they reported too many peers.
118 pub too_many_peers: Counter,
119 /// Peers backed off after a graceful session close.
120 pub graceful_close: Counter,
121 /// Peers backed off due to connection or protocol errors.
122 pub connection_error: Counter,
123}
124
125impl BackedOffPeersMetrics {
126 /// Increments the counter for the given backoff reason.
127 pub fn increment_for_reason(&self, reason: crate::peers::BackoffReason) {
128 match reason {
129 crate::peers::BackoffReason::TooManyPeers => self.too_many_peers.increment(1),
130 crate::peers::BackoffReason::GracefulClose => self.graceful_close.increment(1),
131 crate::peers::BackoffReason::ConnectionError => self.connection_error.increment(1),
132 }
133 }
134}
135
136/// Metrics for `SessionManager`
137#[derive(Metrics)]
138#[metrics(scope = "network")]
139pub struct SessionManagerMetrics {
140 /// Number of successful outgoing dial attempts.
141 pub(crate) total_dial_successes: Counter,
142 /// Number of dropped outgoing peer messages.
143 pub(crate) total_outgoing_peer_messages_dropped: Counter,
144 /// Number of queued outgoing messages
145 pub(crate) queued_outgoing_messages: Gauge,
146 /// Total number of broadcast messages sent via the unbounded overflow channel.
147 pub(crate) total_unbounded_broadcast_msgs: Counter,
148}
149
150/// Metrics for the [`TransactionsManager`](crate::transactions::TransactionsManager).
151#[derive(Metrics)]
152#[metrics(scope = "network")]
153pub struct TransactionsManagerMetrics {
154 /* ================ BROADCAST ================ */
155 /// Total number of propagated transactions
156 pub(crate) propagated_transactions: Counter,
157 /// Total number of reported bad transactions
158 pub(crate) reported_bad_transactions: Counter,
159
160 /* -- Freq txns already marked as seen by peer -- */
161 /// Total number of messages from a peer, announcing transactions that have already been
162 /// marked as seen by that peer.
163 pub(crate) messages_with_hashes_already_seen_by_peer: Counter,
164 /// Total number of messages from a peer, with transaction that have already been marked as
165 /// seen by that peer.
166 pub(crate) messages_with_transactions_already_seen_by_peer: Counter,
167 /// Total number of occurrences, of a peer announcing a transaction that has already been
168 /// marked as seen by that peer.
169 pub(crate) occurrences_hash_already_seen_by_peer: Counter,
170 /// Total number of times a transaction is seen from a peer, that has already been marked as
171 /// seen by that peer.
172 pub(crate) occurrences_of_transaction_already_seen_by_peer: Counter,
173
174 /* -- Freq txns already in pool -- */
175 /// Total number of times a hash is announced that is already in the local pool.
176 pub(crate) occurrences_hashes_already_in_pool: Counter,
177 /// Total number of times a transaction is sent that is already in the local pool.
178 pub(crate) occurrences_transactions_already_in_pool: Counter,
179
180 /* ================ POOL IMPORTS ================ */
181 /// Number of transactions about to be imported into the pool.
182 pub(crate) pending_pool_imports: Gauge,
183 /// Total number of bad imports, imports that fail because the transaction is badly formed
184 /// (i.e. have no chance of passing validation, unlike imports that fail due to e.g. nonce
185 /// gaps).
186 pub(crate) bad_imports: Counter,
187 /// Number of inflight requests at which the
188 /// [`TransactionPool`](reth_transaction_pool::TransactionPool) is considered to be at
189 /// capacity. Note, this is not a limit to the number of inflight requests, but a health
190 /// measure.
191 pub(crate) capacity_pending_pool_imports: Counter,
192 /// Total number of transactions ignored because pending pool imports are at capacity.
193 pub(crate) skipped_transactions_pending_pool_imports_at_capacity: Counter,
194 /// The time it took to prepare transactions for import. This is mostly sender recovery.
195 pub(crate) pool_import_prepare_duration: Histogram,
196
197 /* ================ POLL DURATION ================ */
198
199 /* -- Total poll duration of `TransactionsManager` future -- */
200 /// Duration in seconds of call to
201 /// [`TransactionsManager`](crate::transactions::TransactionsManager)'s poll function.
202 ///
203 /// Updating metrics could take time, so the true duration of this call could
204 /// be longer than the sum of the accumulated durations of polling nested items.
205 pub(crate) duration_poll_tx_manager: Gauge,
206
207 /* -- Poll duration of items nested in `TransactionsManager` future -- */
208 /// Accumulated time spent streaming session updates and updating peers accordingly, in
209 /// one call to poll the [`TransactionsManager`](crate::transactions::TransactionsManager)
210 /// future.
211 ///
212 /// Duration in seconds.
213 pub(crate) acc_duration_poll_network_events: Gauge,
214 /// Accumulated time spent flushing the queue of batched pending pool imports into pool, in
215 /// one call to poll the [`TransactionsManager`](crate::transactions::TransactionsManager)
216 /// future.
217 ///
218 /// Duration in seconds.
219 pub(crate) acc_duration_poll_pending_pool_imports: Gauge,
220 /// Accumulated time spent streaming transaction and announcement broadcast, queueing for
221 /// pool import or requesting respectively, in one call to poll the
222 /// [`TransactionsManager`](crate::transactions::TransactionsManager) future.
223 ///
224 /// Duration in seconds.
225 pub(crate) acc_duration_poll_transaction_events: Gauge,
226 /// Accumulated time spent streaming fetch events, queueing for pool import on successful
227 /// fetch, in one call to poll the
228 /// [`TransactionsManager`](crate::transactions::TransactionsManager) future.
229 ///
230 /// Duration in seconds.
231 pub(crate) acc_duration_poll_fetch_events: Gauge,
232 /// Accumulated time spent streaming and propagating transactions that were successfully
233 /// imported into the pool, in one call to poll the
234 /// [`TransactionsManager`](crate::transactions::TransactionsManager) future.
235 ///
236 /// Duration in seconds.
237 pub(crate) acc_duration_poll_imported_transactions: Gauge,
238 /// Accumulated time spent assembling and sending requests for hashes fetching pending, in
239 /// one call to poll the [`TransactionsManager`](crate::transactions::TransactionsManager)
240 /// future.
241 ///
242 /// Duration in seconds.
243 pub(crate) acc_duration_fetch_pending_hashes: Gauge,
244 /// Accumulated time spent streaming commands and propagating, fetching and serving
245 /// transactions accordingly, in one call to poll the
246 /// [`TransactionsManager`](crate::transactions::TransactionsManager) future.
247 ///
248 /// Duration in seconds.
249 pub(crate) acc_duration_poll_commands: Gauge,
250}
251
252/// Metrics for the [`TransactionsManager`](crate::transactions::TransactionsManager).
253#[derive(Metrics)]
254#[metrics(scope = "network")]
255pub struct TransactionFetcherMetrics {
256 /// Currently active outgoing [`GetPooledTransactions`](reth_eth_wire::GetPooledTransactions)
257 /// requests.
258 pub(crate) inflight_transaction_requests: Gauge,
259 /// Number of inflight requests at which the
260 /// [`TransactionFetcher`](crate::transactions::TransactionFetcher) is considered to be at
261 /// capacity. Note, this is not a limit to the number of inflight requests, but a health
262 /// measure.
263 pub(crate) capacity_inflight_requests: Counter,
264 /// Hashes in currently active outgoing
265 /// [`GetPooledTransactions`](reth_eth_wire::GetPooledTransactions) requests.
266 pub(crate) hashes_inflight_transaction_requests: Gauge,
267 /// How often we failed to send a request to the peer because the channel was full.
268 pub(crate) egress_peer_channel_full: Counter,
269 /// Total number of hashes pending fetch.
270 pub(crate) hashes_pending_fetch: Gauge,
271 /// Total number of fetched transactions.
272 pub(crate) fetched_transactions: Counter,
273 /// Total number of transactions that were received in
274 /// [`PooledTransactions`](reth_eth_wire::PooledTransactions) responses, that weren't
275 /// requested.
276 pub(crate) unsolicited_transactions: Counter,
277 /* ================ SEARCH DURATION ================ */
278 /// Time spent searching for an idle peer in call to
279 /// [`TransactionFetcher::find_any_idle_fallback_peer_for_any_pending_hash`](crate::transactions::TransactionFetcher::find_any_idle_fallback_peer_for_any_pending_hash).
280 ///
281 /// Duration in seconds.
282 pub(crate) duration_find_idle_fallback_peer_for_any_pending_hash: Gauge,
283
284 /// Time spent searching for hashes pending fetch, announced by a given peer in
285 /// [`TransactionFetcher::fill_request_from_hashes_pending_fetch`](crate::transactions::TransactionFetcher::fill_request_from_hashes_pending_fetch).
286 ///
287 /// Duration in seconds.
288 pub(crate) duration_fill_request_from_hashes_pending_fetch: Gauge,
289}
290
291/// Measures the duration of executing the given code block. The duration is added to the given
292/// accumulator value passed as a mutable reference.
293#[macro_export]
294macro_rules! duration_metered_exec {
295 ($code:expr, $acc:expr) => {{
296 let start = std::time::Instant::now();
297
298 let res = $code;
299
300 $acc += start.elapsed();
301
302 res
303 }};
304}
305
306/// Direction-aware wrapper for disconnect metrics.
307///
308/// Tracks disconnect reasons for inbound and outbound connections separately, in addition to
309/// the combined (legacy) counters.
310#[derive(Debug, Default)]
311pub(crate) struct DirectionalDisconnectMetrics {
312 /// Combined disconnect metrics (all directions).
313 pub(crate) total: DisconnectMetrics,
314 /// Disconnect metrics for inbound connections only.
315 pub(crate) inbound: InboundDisconnectMetrics,
316 /// Disconnect metrics for outbound connections only.
317 pub(crate) outbound: OutboundDisconnectMetrics,
318}
319
320impl DirectionalDisconnectMetrics {
321 /// Increments disconnect counters for an inbound connection.
322 pub(crate) fn increment_inbound(&self, reason: DisconnectReason) {
323 self.total.increment(reason);
324 self.inbound.increment(reason);
325 }
326
327 /// Increments disconnect counters for an outbound connection.
328 pub(crate) fn increment_outbound(&self, reason: DisconnectReason) {
329 self.total.increment(reason);
330 self.outbound.increment(reason);
331 }
332}
333
334/// Metrics for Disconnection types
335///
336/// These are just counters, and ideally we would implement these metrics on a peer-by-peer basis,
337/// in that we do not double-count peers for `TooManyPeers` if we make an outgoing connection and
338/// get disconnected twice
339#[derive(Metrics)]
340#[metrics(scope = "network")]
341pub struct DisconnectMetrics {
342 /// Number of peer disconnects due to `DisconnectRequested` (0x00)
343 pub(crate) disconnect_requested: Counter,
344
345 /// Number of peer disconnects due to `TcpSubsystemError` (0x01)
346 pub(crate) tcp_subsystem_error: Counter,
347
348 /// Number of peer disconnects due to `ProtocolBreach` (0x02)
349 pub(crate) protocol_breach: Counter,
350
351 /// Number of peer disconnects due to `UselessPeer` (0x03)
352 pub(crate) useless_peer: Counter,
353
354 /// Number of peer disconnects due to `TooManyPeers` (0x04)
355 pub(crate) too_many_peers: Counter,
356
357 /// Number of peer disconnects due to `AlreadyConnected` (0x05)
358 pub(crate) already_connected: Counter,
359
360 /// Number of peer disconnects due to `IncompatibleP2PProtocolVersion` (0x06)
361 pub(crate) incompatible: Counter,
362
363 /// Number of peer disconnects due to `NullNodeIdentity` (0x07)
364 pub(crate) null_node_identity: Counter,
365
366 /// Number of peer disconnects due to `ClientQuitting` (0x08)
367 pub(crate) client_quitting: Counter,
368
369 /// Number of peer disconnects due to `UnexpectedHandshakeIdentity` (0x09)
370 pub(crate) unexpected_identity: Counter,
371
372 /// Number of peer disconnects due to `ConnectedToSelf` (0x0a)
373 pub(crate) connected_to_self: Counter,
374
375 /// Number of peer disconnects due to `PingTimeout` (0x0b)
376 pub(crate) ping_timeout: Counter,
377
378 /// Number of peer disconnects due to `SubprotocolSpecific` (0x10)
379 pub(crate) subprotocol_specific: Counter,
380}
381
382impl DisconnectMetrics {
383 /// Increments the proper counter for the given disconnect reason
384 pub(crate) fn increment(&self, reason: DisconnectReason) {
385 match reason {
386 DisconnectReason::DisconnectRequested => self.disconnect_requested.increment(1),
387 DisconnectReason::TcpSubsystemError => self.tcp_subsystem_error.increment(1),
388 DisconnectReason::ProtocolBreach => self.protocol_breach.increment(1),
389 DisconnectReason::UselessPeer => self.useless_peer.increment(1),
390 DisconnectReason::TooManyPeers => self.too_many_peers.increment(1),
391 DisconnectReason::AlreadyConnected => self.already_connected.increment(1),
392 DisconnectReason::IncompatibleP2PProtocolVersion => self.incompatible.increment(1),
393 DisconnectReason::NullNodeIdentity => self.null_node_identity.increment(1),
394 DisconnectReason::ClientQuitting => self.client_quitting.increment(1),
395 DisconnectReason::UnexpectedHandshakeIdentity => self.unexpected_identity.increment(1),
396 DisconnectReason::ConnectedToSelf => self.connected_to_self.increment(1),
397 DisconnectReason::PingTimeout => self.ping_timeout.increment(1),
398 DisconnectReason::SubprotocolSpecific => self.subprotocol_specific.increment(1),
399 }
400 }
401}
402
403/// Disconnect metrics scoped to inbound connections only.
404///
405/// These counters track disconnect reasons exclusively for sessions that were initiated by
406/// remote peers connecting to this node. This helps operators distinguish between being rejected
407/// by remote peers (outbound) vs rejecting incoming peers (inbound).
408#[derive(Metrics)]
409#[metrics(scope = "network.inbound")]
410pub struct InboundDisconnectMetrics {
411 /// Number of inbound peer disconnects due to `DisconnectRequested` (0x00)
412 pub(crate) disconnect_requested: Counter,
413
414 /// Number of inbound peer disconnects due to `TcpSubsystemError` (0x01)
415 pub(crate) tcp_subsystem_error: Counter,
416
417 /// Number of inbound peer disconnects due to `ProtocolBreach` (0x02)
418 pub(crate) protocol_breach: Counter,
419
420 /// Number of inbound peer disconnects due to `UselessPeer` (0x03)
421 pub(crate) useless_peer: Counter,
422
423 /// Number of inbound peer disconnects due to `TooManyPeers` (0x04)
424 pub(crate) too_many_peers: Counter,
425
426 /// Number of inbound peer disconnects due to `AlreadyConnected` (0x05)
427 pub(crate) already_connected: Counter,
428
429 /// Number of inbound peer disconnects due to `IncompatibleP2PProtocolVersion` (0x06)
430 pub(crate) incompatible: Counter,
431
432 /// Number of inbound peer disconnects due to `NullNodeIdentity` (0x07)
433 pub(crate) null_node_identity: Counter,
434
435 /// Number of inbound peer disconnects due to `ClientQuitting` (0x08)
436 pub(crate) client_quitting: Counter,
437
438 /// Number of inbound peer disconnects due to `UnexpectedHandshakeIdentity` (0x09)
439 pub(crate) unexpected_identity: Counter,
440
441 /// Number of inbound peer disconnects due to `ConnectedToSelf` (0x0a)
442 pub(crate) connected_to_self: Counter,
443
444 /// Number of inbound peer disconnects due to `PingTimeout` (0x0b)
445 pub(crate) ping_timeout: Counter,
446
447 /// Number of inbound peer disconnects due to `SubprotocolSpecific` (0x10)
448 pub(crate) subprotocol_specific: Counter,
449}
450
451impl InboundDisconnectMetrics {
452 /// Increments the proper counter for the given disconnect reason
453 pub(crate) fn increment(&self, reason: DisconnectReason) {
454 match reason {
455 DisconnectReason::DisconnectRequested => self.disconnect_requested.increment(1),
456 DisconnectReason::TcpSubsystemError => self.tcp_subsystem_error.increment(1),
457 DisconnectReason::ProtocolBreach => self.protocol_breach.increment(1),
458 DisconnectReason::UselessPeer => self.useless_peer.increment(1),
459 DisconnectReason::TooManyPeers => self.too_many_peers.increment(1),
460 DisconnectReason::AlreadyConnected => self.already_connected.increment(1),
461 DisconnectReason::IncompatibleP2PProtocolVersion => self.incompatible.increment(1),
462 DisconnectReason::NullNodeIdentity => self.null_node_identity.increment(1),
463 DisconnectReason::ClientQuitting => self.client_quitting.increment(1),
464 DisconnectReason::UnexpectedHandshakeIdentity => self.unexpected_identity.increment(1),
465 DisconnectReason::ConnectedToSelf => self.connected_to_self.increment(1),
466 DisconnectReason::PingTimeout => self.ping_timeout.increment(1),
467 DisconnectReason::SubprotocolSpecific => self.subprotocol_specific.increment(1),
468 }
469 }
470}
471
472/// Disconnect metrics scoped to outbound connections only.
473///
474/// These counters track disconnect reasons exclusively for sessions that this node initiated
475/// by dialing out to remote peers. A high `too_many_peers` count here indicates remote peers
476/// are rejecting our connection attempts because they are full.
477#[derive(Metrics)]
478#[metrics(scope = "network.outbound")]
479pub struct OutboundDisconnectMetrics {
480 /// Number of outbound peer disconnects due to `DisconnectRequested` (0x00)
481 pub(crate) disconnect_requested: Counter,
482
483 /// Number of outbound peer disconnects due to `TcpSubsystemError` (0x01)
484 pub(crate) tcp_subsystem_error: Counter,
485
486 /// Number of outbound peer disconnects due to `ProtocolBreach` (0x02)
487 pub(crate) protocol_breach: Counter,
488
489 /// Number of outbound peer disconnects due to `UselessPeer` (0x03)
490 pub(crate) useless_peer: Counter,
491
492 /// Number of outbound peer disconnects due to `TooManyPeers` (0x04)
493 pub(crate) too_many_peers: Counter,
494
495 /// Number of outbound peer disconnects due to `AlreadyConnected` (0x05)
496 pub(crate) already_connected: Counter,
497
498 /// Number of outbound peer disconnects due to `IncompatibleP2PProtocolVersion` (0x06)
499 pub(crate) incompatible: Counter,
500
501 /// Number of outbound peer disconnects due to `NullNodeIdentity` (0x07)
502 pub(crate) null_node_identity: Counter,
503
504 /// Number of outbound peer disconnects due to `ClientQuitting` (0x08)
505 pub(crate) client_quitting: Counter,
506
507 /// Number of outbound peer disconnects due to `UnexpectedHandshakeIdentity` (0x09)
508 pub(crate) unexpected_identity: Counter,
509
510 /// Number of outbound peer disconnects due to `ConnectedToSelf` (0x0a)
511 pub(crate) connected_to_self: Counter,
512
513 /// Number of outbound peer disconnects due to `PingTimeout` (0x0b)
514 pub(crate) ping_timeout: Counter,
515
516 /// Number of outbound peer disconnects due to `SubprotocolSpecific` (0x10)
517 pub(crate) subprotocol_specific: Counter,
518}
519
520impl OutboundDisconnectMetrics {
521 /// Increments the proper counter for the given disconnect reason
522 pub(crate) fn increment(&self, reason: DisconnectReason) {
523 match reason {
524 DisconnectReason::DisconnectRequested => self.disconnect_requested.increment(1),
525 DisconnectReason::TcpSubsystemError => self.tcp_subsystem_error.increment(1),
526 DisconnectReason::ProtocolBreach => self.protocol_breach.increment(1),
527 DisconnectReason::UselessPeer => self.useless_peer.increment(1),
528 DisconnectReason::TooManyPeers => self.too_many_peers.increment(1),
529 DisconnectReason::AlreadyConnected => self.already_connected.increment(1),
530 DisconnectReason::IncompatibleP2PProtocolVersion => self.incompatible.increment(1),
531 DisconnectReason::NullNodeIdentity => self.null_node_identity.increment(1),
532 DisconnectReason::ClientQuitting => self.client_quitting.increment(1),
533 DisconnectReason::UnexpectedHandshakeIdentity => self.unexpected_identity.increment(1),
534 DisconnectReason::ConnectedToSelf => self.connected_to_self.increment(1),
535 DisconnectReason::PingTimeout => self.ping_timeout.increment(1),
536 DisconnectReason::SubprotocolSpecific => self.subprotocol_specific.increment(1),
537 }
538 }
539}
540
541/// Metrics for the `EthRequestHandler`
542#[derive(Metrics)]
543#[metrics(scope = "network")]
544pub struct EthRequestHandlerMetrics {
545 /// Number of `GetBlockHeaders` requests received
546 pub(crate) eth_headers_requests_received_total: Counter,
547
548 /// Number of `GetReceipts` requests received
549 pub(crate) eth_receipts_requests_received_total: Counter,
550
551 /// Number of `GetBlockBodies` requests received
552 pub(crate) eth_bodies_requests_received_total: Counter,
553
554 /// Number of `GetNodeData` requests received
555 pub(crate) eth_node_data_requests_received_total: Counter,
556
557 /// Duration in seconds of call to poll
558 /// [`EthRequestHandler`](crate::eth_requests::EthRequestHandler).
559 pub(crate) acc_duration_poll_eth_req_handler: Gauge,
560}
561
562/// Eth67 announcement metrics, track entries by `TxType`
563#[derive(Metrics)]
564#[metrics(scope = "network.transaction_fetcher")]
565pub struct AnnouncedTxTypesMetrics {
566 /// Histogram for tracking frequency of legacy transaction type
567 pub(crate) legacy: Histogram,
568
569 /// Histogram for tracking frequency of EIP-2930 transaction type
570 pub(crate) eip2930: Histogram,
571
572 /// Histogram for tracking frequency of EIP-1559 transaction type
573 pub(crate) eip1559: Histogram,
574
575 /// Histogram for tracking frequency of EIP-4844 transaction type
576 pub(crate) eip4844: Histogram,
577
578 /// Histogram for tracking frequency of EIP-7702 transaction type
579 pub(crate) eip7702: Histogram,
580}
581
582/// Counts the number of transactions by their type in a block or collection.
583///
584/// This struct keeps track of the count of different transaction types
585/// as defined by various Ethereum Improvement Proposals (EIPs).
586#[derive(Debug, Default)]
587pub struct TxTypesCounter {
588 /// Count of legacy transactions (pre-EIP-2718).
589 pub(crate) legacy: usize,
590
591 /// Count of transactions conforming to EIP-2930 (Optional access lists).
592 pub(crate) eip2930: usize,
593
594 /// Count of transactions conforming to EIP-1559 (Fee market change).
595 pub(crate) eip1559: usize,
596
597 /// Count of transactions conforming to EIP-4844 (Shard Blob Transactions).
598 pub(crate) eip4844: usize,
599
600 /// Count of transactions conforming to EIP-7702 (Restricted Storage Windows).
601 pub(crate) eip7702: usize,
602}
603
604impl TxTypesCounter {
605 pub(crate) const fn increase_by_tx_type(&mut self, tx_type: TxType) {
606 match tx_type {
607 TxType::Legacy => {
608 self.legacy += 1;
609 }
610 TxType::Eip2930 => {
611 self.eip2930 += 1;
612 }
613 TxType::Eip1559 => {
614 self.eip1559 += 1;
615 }
616 TxType::Eip4844 => {
617 self.eip4844 += 1;
618 }
619 TxType::Eip7702 => {
620 self.eip7702 += 1;
621 }
622 }
623 }
624}
625
626impl AnnouncedTxTypesMetrics {
627 /// Update metrics during announcement validation, by examining each announcement entry based on
628 /// `TxType`
629 pub(crate) fn update_eth68_announcement_metrics(&self, tx_types_counter: TxTypesCounter) {
630 self.legacy.record(tx_types_counter.legacy as f64);
631 self.eip2930.record(tx_types_counter.eip2930 as f64);
632 self.eip1559.record(tx_types_counter.eip1559 as f64);
633 self.eip4844.record(tx_types_counter.eip4844 as f64);
634 self.eip7702.record(tx_types_counter.eip7702 as f64);
635 }
636}