master
go 153 lines 4.07 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package metrix
4
5 // snapshotGaugeInstrument writes sampled absolute gauge values.
6 type snapshotGaugeInstrument struct {
7 backend meterBackend
8 desc *instrumentDescriptor
9 scope HostScope
10 base []LabelSet
11 }
12
13 // statefulGaugeInstrument writes maintained gauge values.
14 type statefulGaugeInstrument struct {
15 backend meterBackend
16 desc *instrumentDescriptor
17 scope HostScope
18 base []LabelSet
19 }
20
21 // stagedGauge holds one in-cycle gauge sample for a single series identity.
22 type stagedGauge struct {
23 key string
24 name string
25 hostScopeKey string
26 hostScope HostScope
27 labels []Label
28 labelsKey string
29 desc *instrumentDescriptor
30 value SampleValue
31 }
32
33 // Gauge declares or reuses a snapshot gauge under this meter.
34 func (m *snapshotMeter) Gauge(name string, opts ...InstrumentOption) SnapshotGauge {
35 desc, err := m.backend.registerInstrument(metricName(m.prefix, name), kindGauge, modeSnapshot, opts...)
36 if err != nil {
37 panic(err)
38 }
39 return &snapshotGaugeInstrument{
40 backend: m.backend,
41 desc: desc,
42 scope: m.scope,
43 base: appendLabelSets(m.sets, nil),
44 }
45 }
46
47 // Gauge declares or reuses a stateful gauge under this meter.
48 func (m *statefulMeter) Gauge(name string, opts ...InstrumentOption) StatefulGauge {
49 desc, err := m.backend.registerInstrument(metricName(m.prefix, name), kindGauge, modeStateful, opts...)
50 if err != nil {
51 panic(err)
52 }
53 return &statefulGaugeInstrument{
54 backend: m.backend,
55 desc: desc,
56 scope: m.scope,
57 base: appendLabelSets(m.sets, nil),
58 }
59 }
60
61 // Observe writes one absolute gauge value for this collect cycle.
62 func (g *snapshotGaugeInstrument) Observe(v SampleValue, labels ...LabelSet) {
63 g.backend.recordGaugeSet(g.desc, g.scope, v, appendLabelSets(g.base, labels))
64 }
65
66 // Set overwrites the staged gauge value for this collect cycle.
67 func (g *statefulGaugeInstrument) Set(v SampleValue, labels ...LabelSet) {
68 g.backend.recordGaugeSet(g.desc, g.scope, v, appendLabelSets(g.base, labels))
69 }
70
71 // Add accumulates on top of the committed baseline for this collect cycle.
72 func (g *statefulGaugeInstrument) Add(delta SampleValue, labels ...LabelSet) {
73 g.backend.recordGaugeAdd(g.desc, g.scope, delta, appendLabelSets(g.base, labels))
74 }
75
76 // recordGaugeSet writes one gauge sample into the active frame (last-write-wins in-cycle).
77 func (c *storeCore) recordGaugeSet(desc *instrumentDescriptor, scope HostScope, value SampleValue, sets []LabelSet) {
78 mustFiniteSample(value)
79
80 c.mu.Lock()
81 defer c.mu.Unlock()
82
83 if c.active == nil {
84 panic(errCycleInactive)
85 }
86
87 labels, labelsKey, err := labelsFromSet(sets, c)
88 if err != nil {
89 panic(err)
90 }
91 scope, ok := c.prepareHostScopeForWriteLocked(scope)
92 if !ok {
93 return
94 }
95
96 key := makeSeriesKey(scope.ScopeKey, desc.name, labelsKey)
97 entry, ok := c.active.gauges[key]
98 if !ok {
99 entry = &stagedGauge{
100 key: key,
101 name: desc.name,
102 hostScopeKey: scope.ScopeKey,
103 hostScope: scope,
104 labels: labels,
105 labelsKey: labelsKey,
106 desc: desc,
107 }
108 c.active.gauges[key] = entry
109 }
110 entry.value = value
111 }
112
113 // recordGaugeAdd accumulates delta into the active frame using committed baseline on first write.
114 func (c *storeCore) recordGaugeAdd(desc *instrumentDescriptor, scope HostScope, delta SampleValue, sets []LabelSet) {
115 mustFiniteSample(delta)
116
117 c.mu.Lock()
118 defer c.mu.Unlock()
119
120 if c.active == nil {
121 panic(errCycleInactive)
122 }
123
124 labels, labelsKey, err := labelsFromSet(sets, c)
125 if err != nil {
126 panic(err)
127 }
128 scope, ok := c.prepareHostScopeForWriteLocked(scope)
129 if !ok {
130 return
131 }
132
133 key := makeSeriesKey(scope.ScopeKey, desc.name, labelsKey)
134 entry, ok := c.active.gauges[key]
135 if !ok {
136 baseline := SampleValue(0)
137 if existing := c.snapshot.Load().series[key]; existing != nil {
138 baseline = existing.value
139 }
140 entry = &stagedGauge{
141 key: key,
142 name: desc.name,
143 hostScopeKey: scope.ScopeKey,
144 hostScope: scope,
145 labels: labels,
146 labelsKey: labelsKey,
147 desc: desc,
148 value: baseline,
149 }
150 c.active.gauges[key] = entry
151 }
152 entry.value += delta
153 }