Skip to content

Commit af1cd71

Browse files
chore(metrics): dual-export on-chain OCR2 gauges via OpenTelemetry
Emit the same series as Prometheus through beholder.GetMeter() with matching attribute keys (DF-21989).
1 parent 86a737f commit af1cd71

2 files changed

Lines changed: 65 additions & 2 deletions

File tree

core/services/relay/evm/median.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func (oc *medianContract) LatestTransmissionDetails(ctx context.Context) (ocrtyp
9494
}
9595
updatedAt := time.Unix(int64(result.LatestTimestamp), 0)
9696
if oc.onchainViewMetrics != nil {
97-
oc.onchainViewMetrics.record(result.LatestAnswer, result.Epoch, result.Round, updatedAt)
97+
oc.onchainViewMetrics.record(ctx, result.LatestAnswer, result.Epoch, result.Round, updatedAt)
9898
}
9999
return result.ConfigDigest, result.Epoch, result.Round, result.LatestAnswer, updatedAt, nil
100100
}

core/services/relay/evm/median_onchain_view_metrics.go

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
package evm
22

33
import (
4+
"context"
45
"math/big"
6+
"sync"
57
"time"
68

79
"github.com/prometheus/client_golang/prometheus"
810
"github.com/prometheus/client_golang/prometheus/promauto"
11+
"go.opentelemetry.io/otel/attribute"
12+
"go.opentelemetry.io/otel/metric"
13+
14+
"github.com/smartcontractkit/chainlink-common/pkg/beholder"
915
)
1016

1117
// Prometheus gauges for the node's view of on-chain OCR2 median aggregator state (DF-22676).
@@ -29,6 +35,47 @@ var (
2935
}, []string{"chain_id", "contract_address", "transmitter_id"})
3036
)
3137

38+
type medianOnchainOtelInstruments struct {
39+
latestAnswer metric.Float64Gauge
40+
latestTimestampUnix metric.Float64Gauge
41+
epoch metric.Int64Gauge
42+
round metric.Int64Gauge
43+
}
44+
45+
var (
46+
medianOnchainOtelInst *medianOnchainOtelInstruments
47+
medianOnchainOtelOnce sync.Once
48+
)
49+
50+
func loadMedianOnchainOtel() *medianOnchainOtelInstruments {
51+
medianOnchainOtelOnce.Do(func() {
52+
m := beholder.GetMeter()
53+
latestAnswer, err := m.Float64Gauge("ocr2_onchain_transmission_latest_answer")
54+
if err != nil {
55+
return
56+
}
57+
latestTimestampUnix, err := m.Float64Gauge("ocr2_onchain_transmission_latest_timestamp_unix")
58+
if err != nil {
59+
return
60+
}
61+
epoch, err := m.Int64Gauge("ocr2_onchain_transmission_epoch")
62+
if err != nil {
63+
return
64+
}
65+
round, err := m.Int64Gauge("ocr2_onchain_transmission_round")
66+
if err != nil {
67+
return
68+
}
69+
medianOnchainOtelInst = &medianOnchainOtelInstruments{
70+
latestAnswer: latestAnswer,
71+
latestTimestampUnix: latestTimestampUnix,
72+
epoch: epoch,
73+
round: round,
74+
}
75+
})
76+
return medianOnchainOtelInst
77+
}
78+
3279
type medianOnchainViewMetrics struct {
3380
chainID string
3481
contract string
@@ -46,12 +93,28 @@ func newMedianOnchainViewMetrics(chainID, contractAddress, transmitterID string)
4693
}
4794
}
4895

49-
func (m *medianOnchainViewMetrics) record(latestAnswer *big.Int, epoch uint32, round uint8, updatedAt time.Time) {
96+
func (m *medianOnchainViewMetrics) onchainAttrs() metric.MeasurementOption {
97+
return metric.WithAttributes(
98+
attribute.String("chain_id", m.chainID),
99+
attribute.String("contract_address", m.contract),
100+
attribute.String("transmitter_id", m.transmitterID),
101+
)
102+
}
103+
104+
func (m *medianOnchainViewMetrics) record(ctx context.Context, latestAnswer *big.Int, epoch uint32, round uint8, updatedAt time.Time) {
50105
lv := bigIntToPromGaugeValue(latestAnswer)
51106
promOCR2OnchainLatestAnswer.WithLabelValues(m.chainID, m.contract, m.transmitterID).Set(lv)
52107
promOCR2OnchainLatestTimestampUnix.WithLabelValues(m.chainID, m.contract, m.transmitterID).Set(float64(updatedAt.Unix()))
53108
promOCR2OnchainEpoch.WithLabelValues(m.chainID, m.contract, m.transmitterID).Set(float64(epoch))
54109
promOCR2OnchainRound.WithLabelValues(m.chainID, m.contract, m.transmitterID).Set(float64(round))
110+
111+
if ot := loadMedianOnchainOtel(); ot != nil {
112+
opts := m.onchainAttrs()
113+
ot.latestAnswer.Record(ctx, lv, opts)
114+
ot.latestTimestampUnix.Record(ctx, float64(updatedAt.Unix()), opts)
115+
ot.epoch.Record(ctx, int64(epoch), opts)
116+
ot.round.Record(ctx, int64(round), opts)
117+
}
55118
}
56119

57120
func bigIntToPromGaugeValue(i *big.Int) float64 {

0 commit comments

Comments
 (0)