Skip to content

Commit b2dbdd9

Browse files
authored
use metrics.RPCClientMetrics in multinode (#97)
* use metrics.RPCClientMetrics in multinode * update * update * address PR comments * update * update * update * update
1 parent be2bc6b commit b2dbdd9

5 files changed

Lines changed: 194 additions & 25 deletions

File tree

metrics/client_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ func TestNewRPCClientMetrics(t *testing.T) {
1818
require.NotNil(t, m)
1919

2020
ctx := context.Background()
21-
const url = "http://localhost:8545"
22-
m.RecordRequest(ctx, url, false, "latest_block", 100*time.Millisecond, nil)
23-
m.RecordRequest(ctx, url, true, "latest_block", 50*time.Millisecond, errors.New("rpc error"))
21+
m.RecordRequest(ctx, "http://localhost:8545", false, "latest_block", 100*time.Millisecond, nil)
22+
m.RecordRequest(ctx, "http://localhost:8545", false, "latest_block", 50*time.Millisecond, errors.New("rpc error"))
2423
}
2524

2625
func TestNoopRPCClientMetrics_RecordRequest(t *testing.T) {

multinode/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/pkg/errors v0.9.1
88
github.com/prometheus/client_model v0.6.2
99
github.com/smartcontractkit/chainlink-common v0.10.1-0.20260305114348-b8bbac30bfc7
10-
github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260310180305-3ee91a6d9ae9
10+
github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260401162955-be2bc6b5264b
1111
github.com/stretchr/testify v1.11.1
1212
go.uber.org/zap v1.27.1
1313
)

multinode/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ github.com/smartcontractkit/chainlink-common v0.10.1-0.20260305114348-b8bbac30bf
8080
github.com/smartcontractkit/chainlink-common v0.10.1-0.20260305114348-b8bbac30bfc7/go.mod h1:0ghbAr7tRO0tT5ZqBXhOyzgUO37tNNe33Yn0hskauVM=
8181
github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 h1:FJAFgXS9oqASnkS03RE1HQwYQQxrO4l46O5JSzxqLgg=
8282
github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10/go.mod h1:oiDa54M0FwxevWwyAX773lwdWvFYYlYHHQV1LQ5HpWY=
83-
github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260310180305-3ee91a6d9ae9 h1:GK+2aFpW/Z5ZnMGCa9NU6o7LKHQ/9xJVZx2yMAMudnc=
84-
github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260310180305-3ee91a6d9ae9/go.mod h1:HG/aei0MgBOpsyRLexdKGtOUO8yjSJO3iUu0Uu8KBm4=
83+
github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260401162955-be2bc6b5264b h1:L1So1EDBDRET3j/TdV1Gjv3qWARoa/NPRaU7k4r30yA=
84+
github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260401162955-be2bc6b5264b/go.mod h1:HG/aei0MgBOpsyRLexdKGtOUO8yjSJO3iUu0Uu8KBm4=
8585
github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e h1:Hv9Mww35LrufCdM9wtS9yVi/rEWGI1UnjHbcKKU0nVY=
8686
github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU=
8787
github.com/smartcontractkit/libocr v0.0.0-20250912173940-f3ab0246e23d h1:LokA9PoCNb8mm8mDT52c3RECPMRsGz1eCQORq+J3n74=

multinode/rpc_client_base.go

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ import (
99

1010
"github.com/smartcontractkit/chainlink-common/pkg/logger"
1111
"github.com/smartcontractkit/chainlink-common/pkg/services"
12+
frameworkmetrics "github.com/smartcontractkit/chainlink-framework/metrics"
13+
)
14+
15+
var errInvalidHead = errors.New("invalid head")
16+
17+
const (
18+
rpcCallNameLatestBlock = "latest_block"
19+
rpcCallNameLatestFinalizedBlock = "latest_finalized_block"
1220
)
1321

1422
type RPCClientBaseConfig interface {
@@ -27,6 +35,8 @@ type RPCClientBase[HEAD Head] struct {
2735
cfg RPCClientBaseConfig
2836
log logger.Logger
2937
ctxTimeout time.Duration
38+
rpcURL string
39+
isSendOnly bool
3040
subsMu sync.RWMutex
3141
subs map[Subscription]struct{}
3242

@@ -46,22 +56,31 @@ type RPCClientBase[HEAD Head] struct {
4656
highestUserObservations ChainInfo
4757
// most recent chain info observed during current lifecycle
4858
latestChainInfo ChainInfo
59+
60+
rpcMetrics frameworkmetrics.RPCClientMetrics
4961
}
5062

5163
func NewRPCClientBase[HEAD Head](
5264
cfg RPCClientBaseConfig, ctxTimeout time.Duration, log logger.Logger,
5365
latestBlock func(ctx context.Context) (HEAD, error),
5466
latestFinalizedBlock func(ctx context.Context) (HEAD, error),
67+
rpcURL string,
68+
isSendOnly bool,
69+
rpcMetrics frameworkmetrics.RPCClientMetrics,
5570
) *RPCClientBase[HEAD] {
56-
return &RPCClientBase[HEAD]{
71+
base := &RPCClientBase[HEAD]{
5772
cfg: cfg,
5873
log: log,
5974
ctxTimeout: ctxTimeout,
75+
rpcURL: rpcURL,
76+
isSendOnly: isSendOnly,
6077
latestBlock: latestBlock,
6178
latestFinalizedBlock: latestFinalizedBlock,
6279
subs: make(map[Subscription]struct{}),
6380
lifeCycleCh: make(chan struct{}),
81+
rpcMetrics: rpcMetrics,
6482
}
83+
return base
6584
}
6685

6786
func (m *RPCClientBase[HEAD]) lenSubs() int {
@@ -155,37 +174,53 @@ func (m *RPCClientBase[HEAD]) LatestBlock(ctx context.Context) (HEAD, error) {
155174
// capture lifeCycleCh to ensure we are not updating chainInfo with observations related to previous life cycle
156175
ctx, cancel, lifeCycleCh := m.AcquireQueryCtx(ctx, m.ctxTimeout)
157176
defer cancel()
177+
start := time.Now()
158178

159179
head, err := m.latestBlock(ctx)
160180
if err != nil {
181+
m.recordRPCRequest(ctx, rpcCallNameLatestBlock, start, err)
161182
return head, err
162183
}
163184

164185
if !head.IsValid() {
165-
return head, errors.New("invalid head")
186+
m.recordRPCRequest(ctx, rpcCallNameLatestBlock, start, errInvalidHead)
187+
return head, errInvalidHead
166188
}
167189

190+
m.recordRPCRequest(ctx, rpcCallNameLatestBlock, start, nil)
168191
m.OnNewHead(ctx, lifeCycleCh, head)
169192
return head, nil
170193
}
171194

172195
func (m *RPCClientBase[HEAD]) LatestFinalizedBlock(ctx context.Context) (HEAD, error) {
173196
ctx, cancel, lifeCycleCh := m.AcquireQueryCtx(ctx, m.ctxTimeout)
174197
defer cancel()
198+
start := time.Now()
175199

176200
head, err := m.latestFinalizedBlock(ctx)
177201
if err != nil {
202+
m.recordRPCRequest(ctx, rpcCallNameLatestFinalizedBlock, start, err)
178203
return head, err
179204
}
180205

181206
if !head.IsValid() {
182-
return head, errors.New("invalid head")
207+
m.recordRPCRequest(ctx, rpcCallNameLatestFinalizedBlock, start, errInvalidHead)
208+
return head, errInvalidHead
183209
}
184210

211+
m.recordRPCRequest(ctx, rpcCallNameLatestFinalizedBlock, start, nil)
185212
m.OnNewFinalizedHead(ctx, lifeCycleCh, head)
186213
return head, nil
187214
}
188215

216+
func (m *RPCClientBase[HEAD]) recordRPCRequest(ctx context.Context, callName string, startedAt time.Time, err error) {
217+
if m.rpcMetrics == nil {
218+
return
219+
}
220+
221+
m.rpcMetrics.RecordRequest(ctx, m.rpcURL, m.isSendOnly, callName, time.Since(startedAt), err)
222+
}
223+
189224
func (m *RPCClientBase[HEAD]) OnNewHead(ctx context.Context, requestCh <-chan struct{}, head HEAD) {
190225
if !head.IsValid() {
191226
return

0 commit comments

Comments
 (0)