diff --git a/pkg/exporters/drift/drift.go b/pkg/exporters/drift/drift.go index 58799da..9384352 100644 --- a/pkg/exporters/drift/drift.go +++ b/pkg/exporters/drift/drift.go @@ -61,6 +61,9 @@ func (e exporter) ExportMetrics(ctx context.Context, m *metrics.Metrics) error { m.RecordEndpointAvailability(e.chainID, e.referenceNode, true) m.RecordReferenceBlockHeight(e.chainID, e.referenceNode, refHeight) + // Also update time since last block metric when we see new blocks via polling + // This ensures the metric stays accurate even if WebSocket subscription fails + m.UpdateLastBlockTime(e.chainID, time.Now()) e.logger.Info().Uint64("height", refHeight).Str("endpoint", e.referenceNode).Msg("recorded reference node height") // get each full node height and calculate drift @@ -77,6 +80,10 @@ func (e exporter) ExportMetrics(ctx context.Context, m *metrics.Metrics) error { m.RecordCurrentBlockHeight(e.chainID, fullNode, currentHeight) m.RecordBlockHeightDrift(e.chainID, fullNode, refHeight, currentHeight) + // Also update time since last block metric when we see new blocks via polling + // This ensures the metric stays accurate even if WebSocket subscription fails + m.UpdateLastBlockTime(e.chainID, time.Now()) + drift := int64(refHeight) - int64(currentHeight) e.logger.Info(). Uint64("ref_height", refHeight). diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index 6c7c885..4de801e 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -562,6 +562,21 @@ func (m *Metrics) RecordBlockTime(chainID string, arrivalTime time.Time) { } } + m.updateLastBlockTimeUnsafe(chainID, arrivalTime) +} + +// UpdateLastBlockTime updates the last block arrival time and resets time since last block metric +// without recording block time histogram. This is used by pollers that can't measure inter-block time. +func (m *Metrics) UpdateLastBlockTime(chainID string, arrivalTime time.Time) { + m.mu.Lock() + defer m.mu.Unlock() + m.updateLastBlockTimeUnsafe(chainID, arrivalTime) +} + +// updateLastBlockTimeUnsafe is an unexported helper that updates the last block arrival time +// and resets the time since last block gauge. +// This function is not thread-safe and should be called with a lock held. +func (m *Metrics) updateLastBlockTimeUnsafe(chainID string, arrivalTime time.Time) { // update last seen arrival time m.lastBlockArrivalTime[chainID] = arrivalTime // reset time since last block to 0