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}
147
148/// Metrics for the [`TransactionsManager`](crate::transactions::TransactionsManager).
149#[derive(Metrics)]
150#[metrics(scope = "network")]
151pub struct TransactionsManagerMetrics {
152 /* ================ BROADCAST ================ */
153 /// Total number of propagated transactions
154 pub(crate) propagated_transactions: Counter,
155 /// Total number of reported bad transactions
156 pub(crate) reported_bad_transactions: Counter,
157
158 /* -- Freq txns already marked as seen by peer -- */
159 /// Total number of messages from a peer, announcing transactions that have already been
160 /// marked as seen by that peer.
161 pub(crate) messages_with_hashes_already_seen_by_peer: Counter,
162 /// Total number of messages from a peer, with transaction that have already been marked as
163 /// seen by that peer.
164 pub(crate) messages_with_transactions_already_seen_by_peer: Counter,
165 /// Total number of occurrences, of a peer announcing a transaction that has already been
166 /// marked as seen by that peer.
167 pub(crate) occurrences_hash_already_seen_by_peer: Counter,
168 /// Total number of times a transaction is seen from a peer, that has already been marked as
169 /// seen by that peer.
170 pub(crate) occurrences_of_transaction_already_seen_by_peer: Counter,
171
172 /* -- Freq txns already in pool -- */
173 /// Total number of times a hash is announced that is already in the local pool.
174 pub(crate) occurrences_hashes_already_in_pool: Counter,
175 /// Total number of times a transaction is sent that is already in the local pool.
176 pub(crate) occurrences_transactions_already_in_pool: Counter,
177
178 /* ================ POOL IMPORTS ================ */
179 /// Number of transactions about to be imported into the pool.
180 pub(crate) pending_pool_imports: Gauge,
181 /// Total number of bad imports, imports that fail because the transaction is badly formed
182 /// (i.e. have no chance of passing validation, unlike imports that fail due to e.g. nonce
183 /// gaps).
184 pub(crate) bad_imports: Counter,
185 /// Number of inflight requests at which the
186 /// [`TransactionPool`](reth_transaction_pool::TransactionPool) is considered to be at
187 /// capacity. Note, this is not a limit to the number of inflight requests, but a health
188 /// measure.
189 pub(crate) capacity_pending_pool_imports: Counter,
190 /// Total number of transactions ignored because pending pool imports are at capacity.
191 pub(crate) skipped_transactions_pending_pool_imports_at_capacity: Counter,
192 /// The time it took to prepare transactions for import. This is mostly sender recovery.
193 pub(crate) pool_import_prepare_duration: Histogram,
194
195 /* ================ POLL DURATION ================ */
196
197 /* -- Total poll duration of `TransactionsManager` future -- */
198 /// Duration in seconds of call to
199 /// [`TransactionsManager`](crate::transactions::TransactionsManager)'s poll function.
200 ///
201 /// Updating metrics could take time, so the true duration of this call could
202 /// be longer than the sum of the accumulated durations of polling nested items.
203 pub(crate) duration_poll_tx_manager: Gauge,
204
205 /* -- Poll duration of items nested in `TransactionsManager` future -- */
206 /// Accumulated time spent streaming session updates and updating peers accordingly, in
207 /// one call to poll the [`TransactionsManager`](crate::transactions::TransactionsManager)
208 /// future.
209 ///
210 /// Duration in seconds.
211 pub(crate) acc_duration_poll_network_events: Gauge,
212 /// Accumulated time spent flushing the queue of batched pending pool imports into pool, in
213 /// one call to poll the [`TransactionsManager`](crate::transactions::TransactionsManager)
214 /// future.
215 ///
216 /// Duration in seconds.
217 pub(crate) acc_duration_poll_pending_pool_imports: Gauge,
218 /// Accumulated time spent streaming transaction and announcement broadcast, queueing for
219 /// pool import or requesting respectively, in one call to poll the
220 /// [`TransactionsManager`](crate::transactions::TransactionsManager) future.
221 ///
222 /// Duration in seconds.
223 pub(crate) acc_duration_poll_transaction_events: Gauge,
224 /// Accumulated time spent streaming fetch events, queueing for pool import on successful
225 /// fetch, in one call to poll the
226 /// [`TransactionsManager`](crate::transactions::TransactionsManager) future.
227 ///
228 /// Duration in seconds.
229 pub(crate) acc_duration_poll_fetch_events: Gauge,
230 /// Accumulated time spent streaming and propagating transactions that were successfully
231 /// imported into the pool, in one call to poll the
232 /// [`TransactionsManager`](crate::transactions::TransactionsManager) future.
233 ///
234 /// Duration in seconds.
235 pub(crate) acc_duration_poll_imported_transactions: Gauge,
236 /// Accumulated time spent assembling and sending requests for hashes fetching pending, in
237 /// one call to poll the [`TransactionsManager`](crate::transactions::TransactionsManager)
238 /// future.
239 ///
240 /// Duration in seconds.
241 pub(crate) acc_duration_fetch_pending_hashes: Gauge,
242 /// Accumulated time spent streaming commands and propagating, fetching and serving
243 /// transactions accordingly, in one call to poll the
244 /// [`TransactionsManager`](crate::transactions::TransactionsManager) future.
245 ///
246 /// Duration in seconds.
247 pub(crate) acc_duration_poll_commands: Gauge,
248}
249
250/// Metrics for the [`TransactionsManager`](crate::transactions::TransactionsManager).
251#[derive(Metrics)]
252#[metrics(scope = "network")]
253pub struct TransactionFetcherMetrics {
254 /// Currently active outgoing [`GetPooledTransactions`](reth_eth_wire::GetPooledTransactions)
255 /// requests.
256 pub(crate) inflight_transaction_requests: Gauge,
257 /// Number of inflight requests at which the
258 /// [`TransactionFetcher`](crate::transactions::TransactionFetcher) is considered to be at
259 /// capacity. Note, this is not a limit to the number of inflight requests, but a health
260 /// measure.
261 pub(crate) capacity_inflight_requests: Counter,
262 /// Hashes in currently active outgoing
263 /// [`GetPooledTransactions`](reth_eth_wire::GetPooledTransactions) requests.
264 pub(crate) hashes_inflight_transaction_requests: Gauge,
265 /// How often we failed to send a request to the peer because the channel was full.
266 pub(crate) egress_peer_channel_full: Counter,
267 /// Total number of hashes pending fetch.
268 pub(crate) hashes_pending_fetch: Gauge,
269 /// Total number of fetched transactions.
270 pub(crate) fetched_transactions: Counter,
271 /// Total number of transactions that were received in
272 /// [`PooledTransactions`](reth_eth_wire::PooledTransactions) responses, that weren't
273 /// requested.
274 pub(crate) unsolicited_transactions: Counter,
275 /* ================ SEARCH DURATION ================ */
276 /// Time spent searching for an idle peer in call to
277 /// [`TransactionFetcher::find_any_idle_fallback_peer_for_any_pending_hash`](crate::transactions::TransactionFetcher::find_any_idle_fallback_peer_for_any_pending_hash).
278 ///
279 /// Duration in seconds.
280 pub(crate) duration_find_idle_fallback_peer_for_any_pending_hash: Gauge,
281
282 /// Time spent searching for hashes pending fetch, announced by a given peer in
283 /// [`TransactionFetcher::fill_request_from_hashes_pending_fetch`](crate::transactions::TransactionFetcher::fill_request_from_hashes_pending_fetch).
284 ///
285 /// Duration in seconds.
286 pub(crate) duration_fill_request_from_hashes_pending_fetch: Gauge,
287}
288
289/// Measures the duration of executing the given code block. The duration is added to the given
290/// accumulator value passed as a mutable reference.
291#[macro_export]
292macro_rules! duration_metered_exec {
293 ($code:expr, $acc:expr) => {{
294 let start = std::time::Instant::now();
295
296 let res = $code;
297
298 $acc += start.elapsed();
299
300 res
301 }};
302}
303
304/// Direction-aware wrapper for disconnect metrics.
305///
306/// Tracks disconnect reasons for inbound and outbound connections separately, in addition to
307/// the combined (legacy) counters.
308#[derive(Debug, Default)]
309pub(crate) struct DirectionalDisconnectMetrics {
310 /// Combined disconnect metrics (all directions).
311 pub(crate) total: DisconnectMetrics,
312 /// Disconnect metrics for inbound connections only.
313 pub(crate) inbound: InboundDisconnectMetrics,
314 /// Disconnect metrics for outbound connections only.
315 pub(crate) outbound: OutboundDisconnectMetrics,
316}
317
318impl DirectionalDisconnectMetrics {
319 /// Increments disconnect counters for an inbound connection.
320 pub(crate) fn increment_inbound(&self, reason: DisconnectReason) {
321 self.total.increment(reason);
322 self.inbound.increment(reason);
323 }
324
325 /// Increments disconnect counters for an outbound connection.
326 pub(crate) fn increment_outbound(&self, reason: DisconnectReason) {
327 self.total.increment(reason);
328 self.outbound.increment(reason);
329 }
330}
331
332/// Metrics for Disconnection types
333///
334/// These are just counters, and ideally we would implement these metrics on a peer-by-peer basis,
335/// in that we do not double-count peers for `TooManyPeers` if we make an outgoing connection and
336/// get disconnected twice
337#[derive(Metrics)]
338#[metrics(scope = "network")]
339pub struct DisconnectMetrics {
340 /// Number of peer disconnects due to `DisconnectRequested` (0x00)
341 pub(crate) disconnect_requested: Counter,
342
343 /// Number of peer disconnects due to `TcpSubsystemError` (0x01)
344 pub(crate) tcp_subsystem_error: Counter,
345
346 /// Number of peer disconnects due to `ProtocolBreach` (0x02)
347 pub(crate) protocol_breach: Counter,
348
349 /// Number of peer disconnects due to `UselessPeer` (0x03)
350 pub(crate) useless_peer: Counter,
351
352 /// Number of peer disconnects due to `TooManyPeers` (0x04)
353 pub(crate) too_many_peers: Counter,
354
355 /// Number of peer disconnects due to `AlreadyConnected` (0x05)
356 pub(crate) already_connected: Counter,
357
358 /// Number of peer disconnects due to `IncompatibleP2PProtocolVersion` (0x06)
359 pub(crate) incompatible: Counter,
360
361 /// Number of peer disconnects due to `NullNodeIdentity` (0x07)
362 pub(crate) null_node_identity: Counter,
363
364 /// Number of peer disconnects due to `ClientQuitting` (0x08)
365 pub(crate) client_quitting: Counter,
366
367 /// Number of peer disconnects due to `UnexpectedHandshakeIdentity` (0x09)
368 pub(crate) unexpected_identity: Counter,
369
370 /// Number of peer disconnects due to `ConnectedToSelf` (0x0a)
371 pub(crate) connected_to_self: Counter,
372
373 /// Number of peer disconnects due to `PingTimeout` (0x0b)
374 pub(crate) ping_timeout: Counter,
375
376 /// Number of peer disconnects due to `SubprotocolSpecific` (0x10)
377 pub(crate) subprotocol_specific: Counter,
378}
379
380impl DisconnectMetrics {
381 /// Increments the proper counter for the given disconnect reason
382 pub(crate) fn increment(&self, reason: DisconnectReason) {
383 match reason {
384 DisconnectReason::DisconnectRequested => self.disconnect_requested.increment(1),
385 DisconnectReason::TcpSubsystemError => self.tcp_subsystem_error.increment(1),
386 DisconnectReason::ProtocolBreach => self.protocol_breach.increment(1),
387 DisconnectReason::UselessPeer => self.useless_peer.increment(1),
388 DisconnectReason::TooManyPeers => self.too_many_peers.increment(1),
389 DisconnectReason::AlreadyConnected => self.already_connected.increment(1),
390 DisconnectReason::IncompatibleP2PProtocolVersion => self.incompatible.increment(1),
391 DisconnectReason::NullNodeIdentity => self.null_node_identity.increment(1),
392 DisconnectReason::ClientQuitting => self.client_quitting.increment(1),
393 DisconnectReason::UnexpectedHandshakeIdentity => self.unexpected_identity.increment(1),
394 DisconnectReason::ConnectedToSelf => self.connected_to_self.increment(1),
395 DisconnectReason::PingTimeout => self.ping_timeout.increment(1),
396 DisconnectReason::SubprotocolSpecific => self.subprotocol_specific.increment(1),
397 }
398 }
399}
400
401/// Disconnect metrics scoped to inbound connections only.
402///
403/// These counters track disconnect reasons exclusively for sessions that were initiated by
404/// remote peers connecting to this node. This helps operators distinguish between being rejected
405/// by remote peers (outbound) vs rejecting incoming peers (inbound).
406#[derive(Metrics)]
407#[metrics(scope = "network.inbound")]
408pub struct InboundDisconnectMetrics {
409 /// Number of inbound peer disconnects due to `DisconnectRequested` (0x00)
410 pub(crate) disconnect_requested: Counter,
411
412 /// Number of inbound peer disconnects due to `TcpSubsystemError` (0x01)
413 pub(crate) tcp_subsystem_error: Counter,
414
415 /// Number of inbound peer disconnects due to `ProtocolBreach` (0x02)
416 pub(crate) protocol_breach: Counter,
417
418 /// Number of inbound peer disconnects due to `UselessPeer` (0x03)
419 pub(crate) useless_peer: Counter,
420
421 /// Number of inbound peer disconnects due to `TooManyPeers` (0x04)
422 pub(crate) too_many_peers: Counter,
423
424 /// Number of inbound peer disconnects due to `AlreadyConnected` (0x05)
425 pub(crate) already_connected: Counter,
426
427 /// Number of inbound peer disconnects due to `IncompatibleP2PProtocolVersion` (0x06)
428 pub(crate) incompatible: Counter,
429
430 /// Number of inbound peer disconnects due to `NullNodeIdentity` (0x07)
431 pub(crate) null_node_identity: Counter,
432
433 /// Number of inbound peer disconnects due to `ClientQuitting` (0x08)
434 pub(crate) client_quitting: Counter,
435
436 /// Number of inbound peer disconnects due to `UnexpectedHandshakeIdentity` (0x09)
437 pub(crate) unexpected_identity: Counter,
438
439 /// Number of inbound peer disconnects due to `ConnectedToSelf` (0x0a)
440 pub(crate) connected_to_self: Counter,
441
442 /// Number of inbound peer disconnects due to `PingTimeout` (0x0b)
443 pub(crate) ping_timeout: Counter,
444
445 /// Number of inbound peer disconnects due to `SubprotocolSpecific` (0x10)
446 pub(crate) subprotocol_specific: Counter,
447}
448
449impl InboundDisconnectMetrics {
450 /// Increments the proper counter for the given disconnect reason
451 pub(crate) fn increment(&self, reason: DisconnectReason) {
452 match reason {
453 DisconnectReason::DisconnectRequested => self.disconnect_requested.increment(1),
454 DisconnectReason::TcpSubsystemError => self.tcp_subsystem_error.increment(1),
455 DisconnectReason::ProtocolBreach => self.protocol_breach.increment(1),
456 DisconnectReason::UselessPeer => self.useless_peer.increment(1),
457 DisconnectReason::TooManyPeers => self.too_many_peers.increment(1),
458 DisconnectReason::AlreadyConnected => self.already_connected.increment(1),
459 DisconnectReason::IncompatibleP2PProtocolVersion => self.incompatible.increment(1),
460 DisconnectReason::NullNodeIdentity => self.null_node_identity.increment(1),
461 DisconnectReason::ClientQuitting => self.client_quitting.increment(1),
462 DisconnectReason::UnexpectedHandshakeIdentity => self.unexpected_identity.increment(1),
463 DisconnectReason::ConnectedToSelf => self.connected_to_self.increment(1),
464 DisconnectReason::PingTimeout => self.ping_timeout.increment(1),
465 DisconnectReason::SubprotocolSpecific => self.subprotocol_specific.increment(1),
466 }
467 }
468}
469
470/// Disconnect metrics scoped to outbound connections only.
471///
472/// These counters track disconnect reasons exclusively for sessions that this node initiated
473/// by dialing out to remote peers. A high `too_many_peers` count here indicates remote peers
474/// are rejecting our connection attempts because they are full.
475#[derive(Metrics)]
476#[metrics(scope = "network.outbound")]
477pub struct OutboundDisconnectMetrics {
478 /// Number of outbound peer disconnects due to `DisconnectRequested` (0x00)
479 pub(crate) disconnect_requested: Counter,
480
481 /// Number of outbound peer disconnects due to `TcpSubsystemError` (0x01)
482 pub(crate) tcp_subsystem_error: Counter,
483
484 /// Number of outbound peer disconnects due to `ProtocolBreach` (0x02)
485 pub(crate) protocol_breach: Counter,
486
487 /// Number of outbound peer disconnects due to `UselessPeer` (0x03)
488 pub(crate) useless_peer: Counter,
489
490 /// Number of outbound peer disconnects due to `TooManyPeers` (0x04)
491 pub(crate) too_many_peers: Counter,
492
493 /// Number of outbound peer disconnects due to `AlreadyConnected` (0x05)
494 pub(crate) already_connected: Counter,
495
496 /// Number of outbound peer disconnects due to `IncompatibleP2PProtocolVersion` (0x06)
497 pub(crate) incompatible: Counter,
498
499 /// Number of outbound peer disconnects due to `NullNodeIdentity` (0x07)
500 pub(crate) null_node_identity: Counter,
501
502 /// Number of outbound peer disconnects due to `ClientQuitting` (0x08)
503 pub(crate) client_quitting: Counter,
504
505 /// Number of outbound peer disconnects due to `UnexpectedHandshakeIdentity` (0x09)
506 pub(crate) unexpected_identity: Counter,
507
508 /// Number of outbound peer disconnects due to `ConnectedToSelf` (0x0a)
509 pub(crate) connected_to_self: Counter,
510
511 /// Number of outbound peer disconnects due to `PingTimeout` (0x0b)
512 pub(crate) ping_timeout: Counter,
513
514 /// Number of outbound peer disconnects due to `SubprotocolSpecific` (0x10)
515 pub(crate) subprotocol_specific: Counter,
516}
517
518impl OutboundDisconnectMetrics {
519 /// Increments the proper counter for the given disconnect reason
520 pub(crate) fn increment(&self, reason: DisconnectReason) {
521 match reason {
522 DisconnectReason::DisconnectRequested => self.disconnect_requested.increment(1),
523 DisconnectReason::TcpSubsystemError => self.tcp_subsystem_error.increment(1),
524 DisconnectReason::ProtocolBreach => self.protocol_breach.increment(1),
525 DisconnectReason::UselessPeer => self.useless_peer.increment(1),
526 DisconnectReason::TooManyPeers => self.too_many_peers.increment(1),
527 DisconnectReason::AlreadyConnected => self.already_connected.increment(1),
528 DisconnectReason::IncompatibleP2PProtocolVersion => self.incompatible.increment(1),
529 DisconnectReason::NullNodeIdentity => self.null_node_identity.increment(1),
530 DisconnectReason::ClientQuitting => self.client_quitting.increment(1),
531 DisconnectReason::UnexpectedHandshakeIdentity => self.unexpected_identity.increment(1),
532 DisconnectReason::ConnectedToSelf => self.connected_to_self.increment(1),
533 DisconnectReason::PingTimeout => self.ping_timeout.increment(1),
534 DisconnectReason::SubprotocolSpecific => self.subprotocol_specific.increment(1),
535 }
536 }
537}
538
539/// Metrics for the `EthRequestHandler`
540#[derive(Metrics)]
541#[metrics(scope = "network")]
542pub struct EthRequestHandlerMetrics {
543 /// Number of `GetBlockHeaders` requests received
544 pub(crate) eth_headers_requests_received_total: Counter,
545
546 /// Number of `GetReceipts` requests received
547 pub(crate) eth_receipts_requests_received_total: Counter,
548
549 /// Number of `GetBlockBodies` requests received
550 pub(crate) eth_bodies_requests_received_total: Counter,
551
552 /// Number of `GetNodeData` requests received
553 pub(crate) eth_node_data_requests_received_total: Counter,
554
555 /// Duration in seconds of call to poll
556 /// [`EthRequestHandler`](crate::eth_requests::EthRequestHandler).
557 pub(crate) acc_duration_poll_eth_req_handler: Gauge,
558}
559
560/// Eth67 announcement metrics, track entries by `TxType`
561#[derive(Metrics)]
562#[metrics(scope = "network.transaction_fetcher")]
563pub struct AnnouncedTxTypesMetrics {
564 /// Histogram for tracking frequency of legacy transaction type
565 pub(crate) legacy: Histogram,
566
567 /// Histogram for tracking frequency of EIP-2930 transaction type
568 pub(crate) eip2930: Histogram,
569
570 /// Histogram for tracking frequency of EIP-1559 transaction type
571 pub(crate) eip1559: Histogram,
572
573 /// Histogram for tracking frequency of EIP-4844 transaction type
574 pub(crate) eip4844: Histogram,
575
576 /// Histogram for tracking frequency of EIP-7702 transaction type
577 pub(crate) eip7702: Histogram,
578}
579
580/// Counts the number of transactions by their type in a block or collection.
581///
582/// This struct keeps track of the count of different transaction types
583/// as defined by various Ethereum Improvement Proposals (EIPs).
584#[derive(Debug, Default)]
585pub struct TxTypesCounter {
586 /// Count of legacy transactions (pre-EIP-2718).
587 pub(crate) legacy: usize,
588
589 /// Count of transactions conforming to EIP-2930 (Optional access lists).
590 pub(crate) eip2930: usize,
591
592 /// Count of transactions conforming to EIP-1559 (Fee market change).
593 pub(crate) eip1559: usize,
594
595 /// Count of transactions conforming to EIP-4844 (Shard Blob Transactions).
596 pub(crate) eip4844: usize,
597
598 /// Count of transactions conforming to EIP-7702 (Restricted Storage Windows).
599 pub(crate) eip7702: usize,
600}
601
602impl TxTypesCounter {
603 pub(crate) const fn increase_by_tx_type(&mut self, tx_type: TxType) {
604 match tx_type {
605 TxType::Legacy => {
606 self.legacy += 1;
607 }
608 TxType::Eip2930 => {
609 self.eip2930 += 1;
610 }
611 TxType::Eip1559 => {
612 self.eip1559 += 1;
613 }
614 TxType::Eip4844 => {
615 self.eip4844 += 1;
616 }
617 TxType::Eip7702 => {
618 self.eip7702 += 1;
619 }
620 }
621 }
622}
623
624impl AnnouncedTxTypesMetrics {
625 /// Update metrics during announcement validation, by examining each announcement entry based on
626 /// `TxType`
627 pub(crate) fn update_eth68_announcement_metrics(&self, tx_types_counter: TxTypesCounter) {
628 self.legacy.record(tx_types_counter.legacy as f64);
629 self.eip2930.record(tx_types_counter.eip2930 as f64);
630 self.eip1559.record(tx_types_counter.eip1559 as f64);
631 self.eip4844.record(tx_types_counter.eip4844 as f64);
632 self.eip7702.record(tx_types_counter.eip7702 as f64);
633 }
634}