-
Notifications
You must be signed in to change notification settings - Fork 605
/
collector.go
94 lines (76 loc) · 2.32 KB
/
collector.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
package prometheusmetrics
import (
"sync"
"github.com/prometheus/client_golang/prometheus"
)
// CachedGaugeVec is a wrapper for the prometheus.GaugeVec which allows
// for staging changes in the metrics vector. Calling "WithLabelValues(...)"
// will update the internal gauge value, but it will not be returned by
// "Collect(...)" until the "Commit()" method is called. The "Commit()" method
// resets the internal gauge and applies all staged changes to it.
//
// The Use of CachedGaugeVec is recommended for use cases when there is a risk
// that the Prometheus collector receives incomplete metrics, collected
// in the middle of metrics recalculation, between "Reset()" and the last
// "WithLabelValues()" call.
type CachedGaugeVec struct {
m sync.Mutex
gaugeVec *prometheus.GaugeVec
records []vectorRecord
}
var _ prometheus.Collector = new(CachedGaugeVec)
type VectorOperation int
const (
VectorOperationAdd VectorOperation = iota
VectorOperationSet
)
type vectorRecord struct {
operation VectorOperation
value float64
labelValues []string
}
func NewCachedGaugeVec(gaugeVec *prometheus.GaugeVec) *CachedGaugeVec {
return &CachedGaugeVec{
gaugeVec: gaugeVec,
}
}
func (v *CachedGaugeVec) Describe(desc chan<- *prometheus.Desc) {
v.gaugeVec.Describe(desc)
}
func (v *CachedGaugeVec) Collect(ch chan<- prometheus.Metric) {
v.m.Lock()
defer v.m.Unlock()
v.gaugeVec.Collect(ch)
}
func (v *CachedGaugeVec) WithLabelValues(operation VectorOperation, value float64, labelValues ...string) {
switch operation {
case VectorOperationAdd, VectorOperationSet:
default:
panic("unsupported vector operation")
}
v.m.Lock()
defer v.m.Unlock()
v.records = append(v.records, vectorRecord{
operation: operation,
value: value,
labelValues: labelValues,
})
}
// Commit will set the internal value as the cached value to return from "Collect()".
// The internal metric value is completely reset, so the caller should expect
// the gauge to be empty for the next 'WithLabelValues' values.
func (v *CachedGaugeVec) Commit() {
v.m.Lock()
defer v.m.Unlock()
v.gaugeVec.Reset()
for _, record := range v.records {
g := v.gaugeVec.WithLabelValues(record.labelValues...)
switch record.operation {
case VectorOperationAdd:
g.Add(record.value)
case VectorOperationSet:
g.Set(record.value)
}
}
v.records = nil
}