@@ -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
1422type 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
5163func 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
6786func (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
172195func (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+
189224func (m * RPCClientBase [HEAD ]) OnNewHead (ctx context.Context , requestCh <- chan struct {}, head HEAD ) {
190225 if ! head .IsValid () {
191226 return
0 commit comments