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