-
Notifications
You must be signed in to change notification settings - Fork 32
/
otel.go
123 lines (105 loc) · 3.98 KB
/
otel.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package listener
import (
"context"
"fmt"
"time"
"github.com/synapsecns/sanguine/core/metrics"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
)
const meterName = "github.com/synapsecns/sanguine/ethergo/listener"
// generate an interface for otelRecorder that exports the public method.
// this allows us to avoid using recordX externally anad makes the package less confusing.
//
// =============================================================================
// =============================================================================
// IMPORTANT: DO NOT REMOVE THIS COMMENT.
// NOTICE: PLEASE MAKE SURE YOU UPDATE BOTH THE DOCS AND THE GRAFANA DASHBOARD (IF NEEDED) AFTER UPDATING METRICS.
// =============================================================================
// =============================================================================
//
//go:generate go run github.com/vburenin/ifacemaker -f otel.go -s otelRecorder -i iOtelRecorder -p listener -o otel_generated.go -c "autogenerated file"
type otelRecorder struct {
metrics metrics.Handler
// meter is the metrics meter.
meter metric.Meter
// lastBlockGauge is the gauge for the last block.
lastBlockGauge metric.Int64ObservableGauge
// lastFetchedBlockAgeGauge is the gauge for the last block age.
lastFetchedBlockAgeGauge metric.Float64ObservableGauge
// lastBlock is the last block processed by the listener.
lastBlock *uint64
// lastBlockFetchTime is the time the last block was fetched (used to calculate last block age).
lastBlockFetchTime *time.Time
// chainID is the chain ID for the listener.
chainID int
// listenerName is the name of the listener.
listenerName string
}
func newOtelRecorder(meterHandler metrics.Handler, chainID int, name string) (_ iOtelRecorder, err error) {
or := otelRecorder{
metrics: meterHandler,
meter: meterHandler.Meter(meterName),
lastBlock: nil,
lastBlockFetchTime: nil,
chainID: chainID,
listenerName: name,
}
or.lastBlockGauge, err = or.meter.Int64ObservableGauge("last_block")
if err != nil {
return nil, fmt.Errorf("could not create last block gauge")
}
or.lastFetchedBlockAgeGauge, err = or.meter.Float64ObservableGauge("last_block_age")
if err != nil {
return nil, fmt.Errorf("could not create last block age gauge")
}
_, err = or.meter.RegisterCallback(or.recordLastBlock, or.lastBlockGauge)
if err != nil {
return nil, fmt.Errorf("could not register callback for last block gauge")
}
_, err = or.meter.RegisterCallback(or.recordLastFetchedBlockAge, or.lastFetchedBlockAgeGauge)
if err != nil {
return nil, fmt.Errorf("could not register callback for last block age gauge")
}
return &or, nil
}
func (o *otelRecorder) recordLastBlock(_ context.Context, observer metric.Observer) (err error) {
if o.metrics == nil || o.lastBlockGauge == nil || o.lastBlock == nil {
return nil
}
opts := metric.WithAttributes(
attribute.Int(metrics.ChainID, o.chainID),
attribute.String("listener_name", o.listenerName),
)
observer.ObserveInt64(o.lastBlockGauge, int64(*o.lastBlock), opts)
return nil
}
func (o *otelRecorder) recordLastFetchedBlockAge(_ context.Context, observer metric.Observer) (err error) {
if o.metrics == nil || o.lastFetchedBlockAgeGauge == nil || o.lastBlockFetchTime == nil {
return nil
}
age := time.Since(*o.lastBlockFetchTime).Seconds()
opts := metric.WithAttributes(
attribute.Int(metrics.ChainID, o.chainID),
attribute.String("listener_name", o.listenerName),
)
observer.ObserveFloat64(o.lastFetchedBlockAgeGauge, age, opts)
return nil
}
// RecordLastBlock records the last block processed by the listener.
func (o *otelRecorder) RecordLastBlock(lastBlock uint64) {
// verify if the last block has changed
var hasChanged bool
if o.lastBlock == nil {
hasChanged = true
} else {
hasChanged = *o.lastBlock != lastBlock
}
if !hasChanged {
return
}
// record the block
o.lastBlock = &lastBlock
fetchTime := time.Now()
o.lastBlockFetchTime = &fetchTime
}