Skip to content

Commit e20a6b2

Browse files
authored
fix: ensure time_since_last_block accuracy with polling fallback (#28)
1 parent 16d54d6 commit e20a6b2

2 files changed

Lines changed: 22 additions & 0 deletions

File tree

pkg/exporters/drift/drift.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ func (e exporter) ExportMetrics(ctx context.Context, m *metrics.Metrics) error {
6161

6262
m.RecordEndpointAvailability(e.chainID, e.referenceNode, true)
6363
m.RecordReferenceBlockHeight(e.chainID, e.referenceNode, refHeight)
64+
// Also update time since last block metric when we see new blocks via polling
65+
// This ensures the metric stays accurate even if WebSocket subscription fails
66+
m.UpdateLastBlockTime(e.chainID, time.Now())
6467
e.logger.Info().Uint64("height", refHeight).Str("endpoint", e.referenceNode).Msg("recorded reference node height")
6568

6669
// get each full node height and calculate drift
@@ -77,6 +80,10 @@ func (e exporter) ExportMetrics(ctx context.Context, m *metrics.Metrics) error {
7780
m.RecordCurrentBlockHeight(e.chainID, fullNode, currentHeight)
7881
m.RecordBlockHeightDrift(e.chainID, fullNode, refHeight, currentHeight)
7982

83+
// Also update time since last block metric when we see new blocks via polling
84+
// This ensures the metric stays accurate even if WebSocket subscription fails
85+
m.UpdateLastBlockTime(e.chainID, time.Now())
86+
8087
drift := int64(refHeight) - int64(currentHeight)
8188
e.logger.Info().
8289
Uint64("ref_height", refHeight).

pkg/metrics/metrics.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,21 @@ func (m *Metrics) RecordBlockTime(chainID string, arrivalTime time.Time) {
562562
}
563563
}
564564

565+
m.updateLastBlockTimeUnsafe(chainID, arrivalTime)
566+
}
567+
568+
// UpdateLastBlockTime updates the last block arrival time and resets time since last block metric
569+
// without recording block time histogram. This is used by pollers that can't measure inter-block time.
570+
func (m *Metrics) UpdateLastBlockTime(chainID string, arrivalTime time.Time) {
571+
m.mu.Lock()
572+
defer m.mu.Unlock()
573+
m.updateLastBlockTimeUnsafe(chainID, arrivalTime)
574+
}
575+
576+
// updateLastBlockTimeUnsafe is an unexported helper that updates the last block arrival time
577+
// and resets the time since last block gauge.
578+
// This function is not thread-safe and should be called with a lock held.
579+
func (m *Metrics) updateLastBlockTimeUnsafe(chainID string, arrivalTime time.Time) {
565580
// update last seen arrival time
566581
m.lastBlockArrivalTime[chainID] = arrivalTime
567582
// reset time since last block to 0

0 commit comments

Comments
 (0)