From eb88521b5bff9d81409a86f24eb4c318bba799ec Mon Sep 17 00:00:00 2001 From: Mihir Wadekar Date: Wed, 21 Jan 2026 16:33:12 -0800 Subject: [PATCH 1/2] feat: Collects flashbot metrics during execution We now collect aggregated (by block) flashblock metrics --- runner/clients/baserethnode/metrics.go | 54 +++++++++++++++++++------- runner/clients/reth/metrics.go | 40 +++++++++++++++---- runner/network/types/types.go | 29 +++++++++----- 3 files changed, 92 insertions(+), 31 deletions(-) diff --git a/runner/clients/baserethnode/metrics.go b/runner/clients/baserethnode/metrics.go index 6b13a65..2156736 100644 --- a/runner/clients/baserethnode/metrics.go +++ b/runner/clients/baserethnode/metrics.go @@ -40,14 +40,38 @@ func (r *metricsCollector) GetMetrics() []metrics.BlockMetrics { func (r *metricsCollector) GetMetricTypes() map[string]bool { return map[string]bool{ - "reth_sync_execution_execution_duration": true, - "reth_sync_block_validation_state_root_duration": true, - "reth_sync_state_provider_storage_fetch_latency": true, - "reth_sync_state_provider_account_fetch_latency": true, - "reth_sync_state_provider_code_fetch_latency": true, - "reth_sync_state_provider_total_storage_fetch_latency": true, - "reth_sync_state_provider_total_account_fetch_latency": true, - "reth_sync_state_provider_total_code_fetch_latency": true, + "reth_sync_execution_execution_duration": true, + "reth_sync_block_validation_state_root_duration": true, + "reth_sync_state_provider_storage_fetch_latency": true, + "reth_sync_state_provider_account_fetch_latency": true, + "reth_sync_state_provider_code_fetch_latency": true, + "reth_sync_state_provider_total_storage_fetch_latency": true, + "reth_sync_state_provider_total_account_fetch_latency": true, + "reth_sync_state_provider_total_code_fetch_latency": true, + "reth_reth_flashblocks_upstream_errors": true, + "reth_reth_flashblocks_upstream_messages": true, + "reth_reth_flashblocks_block_processing_duration": true, + "reth_reth_flashblocks_sender_recovery_duration": true, + "reth_reth_flashblocks_unexpected_block_order": true, + "reth_reth_flashblocks_flashblocks_in_block": true, + "reth_reth_flashblocks_block_processing_error": true, + "reth_reth_flashblocks_pending_clear_catchup": true, + "reth_reth_flashblocks_pending_clear_reorg": true, + "reth_reth_flashblocks_pending_snapshot_fb_index": true, + "reth_reth_flashblocks_pending_snapshot_height": true, + "reth_reth_flashblocks_reconnect_attempts": true, + "reth_reth_flashblocks_rpc_get_transaction_count": true, + "reth_reth_flashblocks_rpc_get_transaction_receipt": true, + "reth_reth_flashblocks_rpc_get_transaction_by_hash": true, + "reth_reth_flashblocks_rpc_get_balance": true, + "reth_reth_flashblocks_rpc_get_block_by_number": true, + "reth_reth_flashblocks_rpc_call": true, + "reth_reth_flashblocks_rpc_estimate_gas": true, + "reth_reth_flashblocks_rpc_simulate_v1": true, + "reth_reth_flashblocks_rpc_get_logs": true, + "reth_reth_flashblocks_rpc_get_block_transaction_count_by_number": true, + "reth_reth_flashblocks_bundle_state_clone_duration": true, + "reth_reth_flashblocks_bundle_state_clone_size": true, } } @@ -66,23 +90,25 @@ func (r *metricsCollector) Collect(ctx context.Context, m *metrics.BlockMetrics) } txtParser := expfmt.NewTextParser(model.LegacyValidation) - metrics, err := txtParser.TextToMetricFamilies(bytes.NewReader(body)) + parsedMetrics, err := txtParser.TextToMetricFamilies(bytes.NewReader(body)) if err != nil { return fmt.Errorf("failed to parse metrics: %w", err) } metricTypes := r.GetMetricTypes() - for _, metric := range metrics { + for _, metric := range parsedMetrics { name := metric.GetName() if metricTypes[name] { metricVal := metric.GetMetric() if len(metricVal) != 1 { - r.log.Warn("expected 1 metric, got %d for metric %s", len(metricVal), name) + r.log.Warn("expected 1 metric value", "got", len(metricVal), "metric", name) } - err = m.UpdatePrometheusMetric(name, metricVal[0]) - if err != nil { - r.log.Warn("failed to add metric %s: %s", name, err) + if len(metricVal) > 0 { + err = m.UpdatePrometheusMetric(name, metricVal[0]) + if err != nil { + r.log.Warn("failed to add metric", "name", name, "error", err) + } } } } diff --git a/runner/clients/reth/metrics.go b/runner/clients/reth/metrics.go index 4cf17d2..d64d5e1 100644 --- a/runner/clients/reth/metrics.go +++ b/runner/clients/reth/metrics.go @@ -40,14 +40,38 @@ func (r *metricsCollector) GetMetrics() []metrics.BlockMetrics { func (r *metricsCollector) GetMetricTypes() map[string]bool { return map[string]bool{ - "reth_sync_execution_execution_duration": true, - "reth_sync_block_validation_state_root_duration": true, - "reth_sync_state_provider_storage_fetch_latency": true, - "reth_sync_state_provider_account_fetch_latency": true, - "reth_sync_state_provider_code_fetch_latency": true, - "reth_sync_state_provider_total_storage_fetch_latency": true, - "reth_sync_state_provider_total_account_fetch_latency": true, - "reth_sync_state_provider_total_code_fetch_latency": true, + "reth_sync_execution_execution_duration": true, + "reth_sync_block_validation_state_root_duration": true, + "reth_sync_state_provider_storage_fetch_latency": true, + "reth_sync_state_provider_account_fetch_latency": true, + "reth_sync_state_provider_code_fetch_latency": true, + "reth_sync_state_provider_total_storage_fetch_latency": true, + "reth_sync_state_provider_total_account_fetch_latency": true, + "reth_sync_state_provider_total_code_fetch_latency": true, + "reth_flashblocks_upstream_errors": true, + "reth_flashblocks_upstream_messages": true, + "reth_flashblocks_block_processing_duration": true, + "reth_flashblocks_sender_recovery_duration": true, + "reth_flashblocks_unexpected_block_order": true, + "reth_flashblocks_flashblocks_in_block": true, + "reth_flashblocks_block_processing_error": true, + "reth_flashblocks_pending_clear_catchup": true, + "reth_flashblocks_pending_clear_reorg": true, + "reth_flashblocks_pending_snapshot_fb_index": true, + "reth_flashblocks_pending_snapshot_height": true, + "reth_flashblocks_reconnect_attempts": true, + "reth_flashblocks_rpc_get_transaction_count": true, + "reth_flashblocks_rpc_get_transaction_receipt": true, + "reth_flashblocks_rpc_get_transaction_by_hash": true, + "reth_flashblocks_rpc_get_balance": true, + "reth_flashblocks_rpc_get_block_by_number": true, + "reth_flashblocks_rpc_call": true, + "reth_flashblocks_rpc_estimate_gas": true, + "reth_flashblocks_rpc_simulate_v1": true, + "reth_flashblocks_rpc_get_logs": true, + "reth_flashblocks_rpc_get_block_transaction_count_by_number": true, + "reth_flashblocks_bundle_state_clone_duration": true, + "reth_flashblocks_bundle_state_clone_size": true, } } diff --git a/runner/network/types/types.go b/runner/network/types/types.go index b9f45bd..63f8241 100644 --- a/runner/network/types/types.go +++ b/runner/network/types/types.go @@ -134,13 +134,18 @@ func getAverage(metrics []metrics.BlockMetrics, metricName string) float64 { } const ( - UpdateForkChoiceLatencyMetric = "latency/update_fork_choice" - NewPayloadLatencyMetric = "latency/new_payload" - GetPayloadLatencyMetric = "latency/get_payload" - SendTxsLatencyMetric = "latency/send_txs" - GasPerBlockMetric = "gas/per_block" - GasPerSecondMetric = "gas/per_second" - TransactionsPerBlockMetric = "transactions/per_block" + UpdateForkChoiceLatencyMetric = "latency/update_fork_choice" + NewPayloadLatencyMetric = "latency/new_payload" + GetPayloadLatencyMetric = "latency/get_payload" + SendTxsLatencyMetric = "latency/send_txs" + GasPerBlockMetric = "gas/per_block" + GasPerSecondMetric = "gas/per_second" + TransactionsPerBlockMetric = "transactions/per_block" + FlashblockProcessingDurationMetric = "reth_flashblocks_block_processing_duration" + FlashblockSenderRecoveryMetric = "reth_flashblocks_sender_recovery_duration" + FlashblocksInBlockMetric = "reth_flashblocks_flashblocks_in_block" + FlashblockUpstreamMessagesMetric = "reth_flashblocks_upstream_messages" + FlashblockBundleStateCloneDuration = "reth_flashblocks_bundle_state_clone_duration" ) type SequencerKeyMetrics struct { @@ -152,7 +157,9 @@ type SequencerKeyMetrics struct { type ValidatorKeyMetrics struct { CommonKeyMetrics - AverageNewPayloadLatency float64 `json:"newPayload"` + AverageNewPayloadLatency float64 `json:"newPayload"` + AverageFlashblockProcessingDuration float64 `json:"flashblockProcessingDuration,omitempty"` + AverageFlashblocksInBlock float64 `json:"flashblocksInBlock,omitempty"` } type CommonKeyMetrics struct { @@ -163,9 +170,13 @@ type CommonKeyMetrics struct { func BlockMetricsToValidatorSummary(metrics []metrics.BlockMetrics) *ValidatorKeyMetrics { averageNewPayloadLatency := getAverage(metrics, NewPayloadLatencyMetric) averageGasPerSecond := getAverage(metrics, GasPerSecondMetric) + averageFlashblockProcessingDuration := getAverage(metrics, FlashblockProcessingDurationMetric) + averageFlashblocksInBlock := getAverage(metrics, FlashblocksInBlockMetric) return &ValidatorKeyMetrics{ - AverageNewPayloadLatency: averageNewPayloadLatency, + AverageNewPayloadLatency: averageNewPayloadLatency, + AverageFlashblockProcessingDuration: averageFlashblockProcessingDuration, + AverageFlashblocksInBlock: averageFlashblocksInBlock, CommonKeyMetrics: CommonKeyMetrics{ AverageGasPerSecond: averageGasPerSecond, }, From 39fc43e568a5df80652b38f126ae19df87e560a4 Mon Sep 17 00:00:00 2001 From: Mihir Wadekar Date: Mon, 26 Jan 2026 20:52:37 -0800 Subject: [PATCH 2/2] chore: removes unused flashblock metrics Reth supports flashblocks, but metrics are only available to base-reth-node for now. --- runner/clients/baserethnode/metrics.go | 53 ++++++++++---------------- runner/clients/reth/metrics.go | 40 ++++--------------- 2 files changed, 29 insertions(+), 64 deletions(-) diff --git a/runner/clients/baserethnode/metrics.go b/runner/clients/baserethnode/metrics.go index 2156736..28f2de2 100644 --- a/runner/clients/baserethnode/metrics.go +++ b/runner/clients/baserethnode/metrics.go @@ -40,38 +40,27 @@ func (r *metricsCollector) GetMetrics() []metrics.BlockMetrics { func (r *metricsCollector) GetMetricTypes() map[string]bool { return map[string]bool{ - "reth_sync_execution_execution_duration": true, - "reth_sync_block_validation_state_root_duration": true, - "reth_sync_state_provider_storage_fetch_latency": true, - "reth_sync_state_provider_account_fetch_latency": true, - "reth_sync_state_provider_code_fetch_latency": true, - "reth_sync_state_provider_total_storage_fetch_latency": true, - "reth_sync_state_provider_total_account_fetch_latency": true, - "reth_sync_state_provider_total_code_fetch_latency": true, - "reth_reth_flashblocks_upstream_errors": true, - "reth_reth_flashblocks_upstream_messages": true, - "reth_reth_flashblocks_block_processing_duration": true, - "reth_reth_flashblocks_sender_recovery_duration": true, - "reth_reth_flashblocks_unexpected_block_order": true, - "reth_reth_flashblocks_flashblocks_in_block": true, - "reth_reth_flashblocks_block_processing_error": true, - "reth_reth_flashblocks_pending_clear_catchup": true, - "reth_reth_flashblocks_pending_clear_reorg": true, - "reth_reth_flashblocks_pending_snapshot_fb_index": true, - "reth_reth_flashblocks_pending_snapshot_height": true, - "reth_reth_flashblocks_reconnect_attempts": true, - "reth_reth_flashblocks_rpc_get_transaction_count": true, - "reth_reth_flashblocks_rpc_get_transaction_receipt": true, - "reth_reth_flashblocks_rpc_get_transaction_by_hash": true, - "reth_reth_flashblocks_rpc_get_balance": true, - "reth_reth_flashblocks_rpc_get_block_by_number": true, - "reth_reth_flashblocks_rpc_call": true, - "reth_reth_flashblocks_rpc_estimate_gas": true, - "reth_reth_flashblocks_rpc_simulate_v1": true, - "reth_reth_flashblocks_rpc_get_logs": true, - "reth_reth_flashblocks_rpc_get_block_transaction_count_by_number": true, - "reth_reth_flashblocks_bundle_state_clone_duration": true, - "reth_reth_flashblocks_bundle_state_clone_size": true, + "reth_sync_execution_execution_duration": true, + "reth_sync_block_validation_state_root_duration": true, + "reth_sync_state_provider_storage_fetch_latency": true, + "reth_sync_state_provider_account_fetch_latency": true, + "reth_sync_state_provider_code_fetch_latency": true, + "reth_sync_state_provider_total_storage_fetch_latency": true, + "reth_sync_state_provider_total_account_fetch_latency": true, + "reth_sync_state_provider_total_code_fetch_latency": true, + "reth_reth_flashblocks_upstream_errors": true, + "reth_reth_flashblocks_upstream_messages": true, + "reth_reth_flashblocks_block_processing_duration": true, + "reth_reth_flashblocks_sender_recovery_duration": true, + "reth_reth_flashblocks_unexpected_block_order": true, + "reth_reth_flashblocks_flashblocks_in_block": true, + "reth_reth_flashblocks_block_processing_error": true, + "reth_reth_flashblocks_pending_clear_catchup": true, + "reth_reth_flashblocks_pending_clear_reorg": true, + "reth_reth_flashblocks_pending_snapshot_fb_index": true, + "reth_reth_flashblocks_pending_snapshot_height": true, + "reth_reth_flashblocks_bundle_state_clone_duration": true, + "reth_reth_flashblocks_bundle_state_clone_size": true, } } diff --git a/runner/clients/reth/metrics.go b/runner/clients/reth/metrics.go index d64d5e1..4cf17d2 100644 --- a/runner/clients/reth/metrics.go +++ b/runner/clients/reth/metrics.go @@ -40,38 +40,14 @@ func (r *metricsCollector) GetMetrics() []metrics.BlockMetrics { func (r *metricsCollector) GetMetricTypes() map[string]bool { return map[string]bool{ - "reth_sync_execution_execution_duration": true, - "reth_sync_block_validation_state_root_duration": true, - "reth_sync_state_provider_storage_fetch_latency": true, - "reth_sync_state_provider_account_fetch_latency": true, - "reth_sync_state_provider_code_fetch_latency": true, - "reth_sync_state_provider_total_storage_fetch_latency": true, - "reth_sync_state_provider_total_account_fetch_latency": true, - "reth_sync_state_provider_total_code_fetch_latency": true, - "reth_flashblocks_upstream_errors": true, - "reth_flashblocks_upstream_messages": true, - "reth_flashblocks_block_processing_duration": true, - "reth_flashblocks_sender_recovery_duration": true, - "reth_flashblocks_unexpected_block_order": true, - "reth_flashblocks_flashblocks_in_block": true, - "reth_flashblocks_block_processing_error": true, - "reth_flashblocks_pending_clear_catchup": true, - "reth_flashblocks_pending_clear_reorg": true, - "reth_flashblocks_pending_snapshot_fb_index": true, - "reth_flashblocks_pending_snapshot_height": true, - "reth_flashblocks_reconnect_attempts": true, - "reth_flashblocks_rpc_get_transaction_count": true, - "reth_flashblocks_rpc_get_transaction_receipt": true, - "reth_flashblocks_rpc_get_transaction_by_hash": true, - "reth_flashblocks_rpc_get_balance": true, - "reth_flashblocks_rpc_get_block_by_number": true, - "reth_flashblocks_rpc_call": true, - "reth_flashblocks_rpc_estimate_gas": true, - "reth_flashblocks_rpc_simulate_v1": true, - "reth_flashblocks_rpc_get_logs": true, - "reth_flashblocks_rpc_get_block_transaction_count_by_number": true, - "reth_flashblocks_bundle_state_clone_duration": true, - "reth_flashblocks_bundle_state_clone_size": true, + "reth_sync_execution_execution_duration": true, + "reth_sync_block_validation_state_root_duration": true, + "reth_sync_state_provider_storage_fetch_latency": true, + "reth_sync_state_provider_account_fetch_latency": true, + "reth_sync_state_provider_code_fetch_latency": true, + "reth_sync_state_provider_total_storage_fetch_latency": true, + "reth_sync_state_provider_total_account_fetch_latency": true, + "reth_sync_state_provider_total_code_fetch_latency": true, } }