diff --git a/pkg/txm/metrics.go b/pkg/txm/metrics.go index d47de2cd5e..800250ca34 100644 --- a/pkg/txm/metrics.go +++ b/pkg/txm/metrics.go @@ -40,6 +40,10 @@ var ( Name: "txm_time_until_tx_confirmed", Help: "The amount of time elapsed from a transaction being broadcast to being included in a block.", }, []string{"chainID"}) + promRPCNonce = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "txm_rpc_nonce", + Help: "The latest confirmed nonce reported by the RPC node for a given address.", + }, []string{"chainID", "address"}) ) type txmMetrics struct { @@ -50,6 +54,7 @@ type txmMetrics struct { numNonceGaps metric.Int64Counter reachedMaxAttempts metric.Int64Gauge timeUntilTxConfirmed metric.Float64Histogram + rpcNonce metric.Int64Gauge } func NewTxmMetrics(chainID *big.Int) (*txmMetrics, error) { @@ -78,6 +83,11 @@ func NewTxmMetrics(chainID *big.Int) (*txmMetrics, error) { return nil, fmt.Errorf("failed to register max attempts indicator: %w", err) } + rpcNonce, err := beholder.GetMeter().Int64Gauge("txm_rpc_nonce") + if err != nil { + return nil, fmt.Errorf("failed to register rpc nonce gauge: %w", err) + } + return &txmMetrics{ chainID: chainID, Labeler: metrics.NewLabeler().With("chainID", chainID.String()), @@ -86,6 +96,7 @@ func NewTxmMetrics(chainID *big.Int) (*txmMetrics, error) { numNonceGaps: numNonceGaps, reachedMaxAttempts: reachedMaxAttempts, timeUntilTxConfirmed: timeUntilTxConfirmed, + rpcNonce: rpcNonce, }, nil } @@ -118,6 +129,11 @@ func (m *txmMetrics) RecordTimeUntilTxConfirmed(ctx context.Context, duration fl m.timeUntilTxConfirmed.Record(ctx, duration) } +func (m *txmMetrics) SetRPCNonce(ctx context.Context, address common.Address, nonce uint64) { + promRPCNonce.WithLabelValues(m.chainID.String(), address.String()).Set(float64(nonce)) + m.rpcNonce.Record(ctx, int64(nonce)) +} + func (m *txmMetrics) EmitTxMessage(ctx context.Context, txHash common.Hash, fromAddress common.Address, tx *types.Transaction) error { meta, err := tx.GetMeta() if err != nil { diff --git a/pkg/txm/metrics_test.go b/pkg/txm/metrics_test.go index 15faa1d895..338c2247cf 100644 --- a/pkg/txm/metrics_test.go +++ b/pkg/txm/metrics_test.go @@ -132,3 +132,20 @@ func TestReachedMaxAttempts(t *testing.T) { value = testutil.ToFloat64(promReachedMaxAttempts.WithLabelValues(testutils.FixtureChainID.String())) require.InDelta(t, float64(0), value, 0.00001) } + +func TestSetRPCNonce(t *testing.T) { + ctx := t.Context() + chainID := testutils.FixtureChainID + address := testutils.NewAddress() + + m, err := NewTxmMetrics(chainID) + require.NoError(t, err) + + m.SetRPCNonce(ctx, address, 10) + value := testutil.ToFloat64(promRPCNonce.WithLabelValues(chainID.String(), address.String())) + assert.InDelta(t, float64(10), value, 0.00001) + + m.SetRPCNonce(ctx, address, 25) + value = testutil.ToFloat64(promRPCNonce.WithLabelValues(chainID.String(), address.String())) + assert.InDelta(t, float64(25), value, 0.00001) +} diff --git a/pkg/txm/txm.go b/pkg/txm/txm.go index 8ce3da1087..65dfab8019 100644 --- a/pkg/txm/txm.go +++ b/pkg/txm/txm.go @@ -361,6 +361,9 @@ func (t *Txm) BackfillTransactions(ctx context.Context, address common.Address) if err != nil { return err } + if t.Metrics != nil { + t.Metrics.SetRPCNonce(ctx, address, latestNonce) + } confirmedTransactions, unconfirmedTransactionIDs, err := t.txStore.MarkConfirmedAndReorgedTransactions(ctx, latestNonce, address) if err != nil {