master
go 488 lines 14.5 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package metrix
4
5 const MeasureSetFieldLabel = "measure_field"
6
7 // stagedMeasureSet holds one in-cycle MeasureSet sample for a single series identity.
8 type stagedMeasureSet struct {
9 key string
10 name string
11 hostScopeKey string
12 hostScope HostScope
13 labels []Label
14 labelsKey string
15 desc *instrumentDescriptor
16 values []SampleValue
17 }
18
19 // snapshotMeasureSetGaugeInstrument writes sampled MeasureSet gauge points.
20 type snapshotMeasureSetGaugeInstrument struct {
21 backend meterBackend
22 desc *instrumentDescriptor
23 scope HostScope
24 base []LabelSet
25 }
26
27 // snapshotMeasureSetCounterInstrument writes sampled MeasureSet counter totals.
28 type snapshotMeasureSetCounterInstrument struct {
29 backend meterBackend
30 desc *instrumentDescriptor
31 scope HostScope
32 base []LabelSet
33 }
34
35 // statefulMeasureSetGaugeInstrument writes maintained MeasureSet gauge points.
36 type statefulMeasureSetGaugeInstrument struct {
37 backend meterBackend
38 desc *instrumentDescriptor
39 scope HostScope
40 base []LabelSet
41 }
42
43 // statefulMeasureSetCounterInstrument writes maintained MeasureSet counter deltas.
44 type statefulMeasureSetCounterInstrument struct {
45 backend meterBackend
46 desc *instrumentDescriptor
47 scope HostScope
48 base []LabelSet
49 }
50
51 func appendMeasureSetSemantics(opts []InstrumentOption, semantics MeasureSetSemantics) []InstrumentOption {
52 out := make([]InstrumentOption, 0, len(opts)+1)
53 out = append(out, withMeasureSetSemantics(semantics))
54 out = append(out, opts...)
55 return out
56 }
57
58 // MeasureSetGauge declares or reuses a snapshot MeasureSet with gauge semantics.
59 func (m *snapshotMeter) MeasureSetGauge(name string, opts ...InstrumentOption) SnapshotMeasureSetGauge {
60 desc, err := m.backend.registerInstrument(metricName(m.prefix, name), kindMeasureSet, modeSnapshot, appendMeasureSetSemantics(opts, MeasureSetSemanticsGauge)...)
61 if err != nil {
62 panic(err)
63 }
64 return &snapshotMeasureSetGaugeInstrument{
65 backend: m.backend,
66 desc: desc,
67 scope: m.scope,
68 base: appendLabelSets(m.sets, nil),
69 }
70 }
71
72 // MeasureSetCounter declares or reuses a snapshot MeasureSet with counter semantics.
73 func (m *snapshotMeter) MeasureSetCounter(name string, opts ...InstrumentOption) SnapshotMeasureSetCounter {
74 desc, err := m.backend.registerInstrument(metricName(m.prefix, name), kindMeasureSet, modeSnapshot, appendMeasureSetSemantics(opts, MeasureSetSemanticsCounter)...)
75 if err != nil {
76 panic(err)
77 }
78 return &snapshotMeasureSetCounterInstrument{
79 backend: m.backend,
80 desc: desc,
81 scope: m.scope,
82 base: appendLabelSets(m.sets, nil),
83 }
84 }
85
86 // MeasureSetGauge declares or reuses a stateful MeasureSet with gauge semantics.
87 func (m *statefulMeter) MeasureSetGauge(name string, opts ...InstrumentOption) StatefulMeasureSetGauge {
88 desc, err := m.backend.registerInstrument(metricName(m.prefix, name), kindMeasureSet, modeStateful, appendMeasureSetSemantics(opts, MeasureSetSemanticsGauge)...)
89 if err != nil {
90 panic(err)
91 }
92 return &statefulMeasureSetGaugeInstrument{
93 backend: m.backend,
94 desc: desc,
95 scope: m.scope,
96 base: appendLabelSets(m.sets, nil),
97 }
98 }
99
100 // MeasureSetCounter declares or reuses a stateful MeasureSet with counter semantics.
101 func (m *statefulMeter) MeasureSetCounter(name string, opts ...InstrumentOption) StatefulMeasureSetCounter {
102 desc, err := m.backend.registerInstrument(metricName(m.prefix, name), kindMeasureSet, modeStateful, appendMeasureSetSemantics(opts, MeasureSetSemanticsCounter)...)
103 if err != nil {
104 panic(err)
105 }
106 return &statefulMeasureSetCounterInstrument{
107 backend: m.backend,
108 desc: desc,
109 scope: m.scope,
110 base: appendLabelSets(m.sets, nil),
111 }
112 }
113
114 func (m *snapshotMeasureSetGaugeInstrument) ObservePoint(p MeasureSetPoint, labels ...LabelSet) {
115 m.backend.recordMeasureSetGaugeObservePoint(m.desc, m.scope, p, appendLabelSets(m.base, labels))
116 }
117
118 func (m *snapshotMeasureSetGaugeInstrument) ObserveFields(fields map[string]SampleValue, labels ...LabelSet) {
119 m.ObservePoint(measureSetPointFromFields(fields, m.desc.measureSet), labels...)
120 }
121
122 func (m *snapshotMeasureSetCounterInstrument) ObserveTotalPoint(p MeasureSetPoint, labels ...LabelSet) {
123 m.backend.recordMeasureSetCounterObserveTotalPoint(m.desc, m.scope, p, appendLabelSets(m.base, labels))
124 }
125
126 func (m *snapshotMeasureSetCounterInstrument) ObserveTotalFields(fields map[string]SampleValue, labels ...LabelSet) {
127 m.ObserveTotalPoint(measureSetPointFromFields(fields, m.desc.measureSet), labels...)
128 }
129
130 func (m *statefulMeasureSetGaugeInstrument) SetPoint(p MeasureSetPoint, labels ...LabelSet) {
131 m.backend.recordMeasureSetGaugeSetPoint(m.desc, m.scope, p, appendLabelSets(m.base, labels))
132 }
133
134 func (m *statefulMeasureSetGaugeInstrument) SetFields(fields map[string]SampleValue, labels ...LabelSet) {
135 m.SetPoint(measureSetPointFromFields(fields, m.desc.measureSet), labels...)
136 }
137
138 func (m *statefulMeasureSetGaugeInstrument) SetField(field string, value SampleValue, labels ...LabelSet) {
139 m.backend.recordMeasureSetGaugeSetField(m.desc, m.scope, field, value, appendLabelSets(m.base, labels))
140 }
141
142 func (m *statefulMeasureSetGaugeInstrument) AddPoint(delta MeasureSetPoint, labels ...LabelSet) {
143 m.backend.recordMeasureSetGaugeAddPoint(m.desc, m.scope, delta, appendLabelSets(m.base, labels))
144 }
145
146 func (m *statefulMeasureSetGaugeInstrument) AddFields(delta map[string]SampleValue, labels ...LabelSet) {
147 m.AddPoint(measureSetPointFromFields(delta, m.desc.measureSet), labels...)
148 }
149
150 func (m *statefulMeasureSetGaugeInstrument) AddField(field string, delta SampleValue, labels ...LabelSet) {
151 m.AddPoint(singleMeasureSetPoint(field, delta, m.desc.measureSet), labels...)
152 }
153
154 func (m *statefulMeasureSetCounterInstrument) AddPoint(delta MeasureSetPoint, labels ...LabelSet) {
155 m.backend.recordMeasureSetCounterAddPoint(m.desc, m.scope, delta, appendLabelSets(m.base, labels))
156 }
157
158 func (m *statefulMeasureSetCounterInstrument) AddFields(delta map[string]SampleValue, labels ...LabelSet) {
159 m.AddPoint(measureSetPointFromFields(delta, m.desc.measureSet), labels...)
160 }
161
162 func (m *statefulMeasureSetCounterInstrument) AddField(field string, delta SampleValue, labels ...LabelSet) {
163 m.AddPoint(singleMeasureSetPoint(field, delta, m.desc.measureSet), labels...)
164 }
165
166 func normalizeMeasureSetPoint(point MeasureSetPoint, schema *measureSetSchema) []SampleValue {
167 if schema == nil {
168 panic(errMeasureSetSchema)
169 }
170 if len(point.Values) != len(schema.fields) {
171 panic(errMeasureSetPoint)
172 }
173
174 values := make([]SampleValue, len(point.Values))
175 for i, v := range point.Values {
176 mustFiniteSample(v)
177 values[i] = v
178 }
179 return values
180 }
181
182 func measureSetPointFromFields(fields map[string]SampleValue, schema *measureSetSchema) MeasureSetPoint {
183 return MeasureSetPoint{Values: normalizeMeasureSetFields(fields, schema)}
184 }
185
186 func normalizeMeasureSetFields(fields map[string]SampleValue, schema *measureSetSchema) []SampleValue {
187 if schema == nil {
188 panic(errMeasureSetSchema)
189 }
190 if len(fields) != len(schema.fields) {
191 panic(errMeasureSetFields)
192 }
193
194 values := make([]SampleValue, len(schema.fields))
195 for field, value := range fields {
196 idx, ok := schema.index[field]
197 if !ok {
198 panic(errMeasureSetField)
199 }
200 mustFiniteSample(value)
201 values[idx] = value
202 }
203 return values
204 }
205
206 func singleMeasureSetPoint(field string, value SampleValue, schema *measureSetSchema) MeasureSetPoint {
207 values := make([]SampleValue, len(schema.fields))
208 idx := mustMeasureSetFieldIndex(field, schema)
209 mustFiniteSample(value)
210 values[idx] = value
211 return MeasureSetPoint{Values: values}
212 }
213
214 func mustMeasureSetFieldIndex(field string, schema *measureSetSchema) int {
215 if schema == nil {
216 panic(errMeasureSetSchema)
217 }
218 idx, ok := schema.index[field]
219 if !ok {
220 panic(errMeasureSetField)
221 }
222 return idx
223 }
224
225 func normalizeMeasureSetCounterDelta(delta MeasureSetPoint, schema *measureSetSchema) []SampleValue {
226 values := normalizeMeasureSetPoint(delta, schema)
227 for _, v := range values {
228 if v < 0 {
229 panic(errCounterNegativeDelta)
230 }
231 }
232 return values
233 }
234
235 func (c *storeCore) recordMeasureSetGaugeObservePoint(desc *instrumentDescriptor, scope HostScope, point MeasureSetPoint, sets []LabelSet) {
236 c.recordMeasureSetGaugeSetPoint(desc, scope, point, sets)
237 }
238
239 func (c *storeCore) recordMeasureSetGaugeSetPoint(desc *instrumentDescriptor, scope HostScope, point MeasureSetPoint, sets []LabelSet) {
240 schema := desc.measureSet
241 if schema == nil || schema.semantics != MeasureSetSemanticsGauge {
242 panic(errMeasureSetSchema)
243 }
244
245 values := normalizeMeasureSetPoint(point, schema)
246
247 c.mu.Lock()
248 defer c.mu.Unlock()
249
250 if c.active == nil {
251 panic(errCycleInactive)
252 }
253
254 labels, labelsKey, err := labelsFromSet(sets, c)
255 if err != nil {
256 panic(err)
257 }
258 if labelsContainKey(labels, MeasureSetFieldLabel) {
259 panic(errMeasureSetLabelKey)
260 }
261 scope, ok := c.prepareHostScopeForWriteLocked(scope)
262 if !ok {
263 return
264 }
265
266 key := makeSeriesKey(scope.ScopeKey, desc.name, labelsKey)
267 entry, ok := c.active.measureSetGauges[key]
268 if !ok {
269 entry = &stagedMeasureSet{
270 key: key,
271 name: desc.name,
272 hostScopeKey: scope.ScopeKey,
273 hostScope: scope,
274 labels: labels,
275 labelsKey: labelsKey,
276 desc: desc,
277 }
278 c.active.measureSetGauges[key] = entry
279 }
280 entry.values = append(entry.values[:0], values...)
281 }
282
283 func (c *storeCore) recordMeasureSetGaugeAddPoint(desc *instrumentDescriptor, scope HostScope, delta MeasureSetPoint, sets []LabelSet) {
284 schema := desc.measureSet
285 if schema == nil || schema.semantics != MeasureSetSemanticsGauge {
286 panic(errMeasureSetSchema)
287 }
288
289 values := normalizeMeasureSetPoint(delta, schema)
290
291 c.mu.Lock()
292 defer c.mu.Unlock()
293
294 if c.active == nil {
295 panic(errCycleInactive)
296 }
297
298 labels, labelsKey, err := labelsFromSet(sets, c)
299 if err != nil {
300 panic(err)
301 }
302 if labelsContainKey(labels, MeasureSetFieldLabel) {
303 panic(errMeasureSetLabelKey)
304 }
305 scope, ok := c.prepareHostScopeForWriteLocked(scope)
306 if !ok {
307 return
308 }
309
310 key := makeSeriesKey(scope.ScopeKey, desc.name, labelsKey)
311 entry, ok := c.active.measureSetGauges[key]
312 if !ok {
313 baseline := make([]SampleValue, len(schema.fields))
314 if existing := c.snapshot.Load().series[key]; existing != nil {
315 baseline = append(baseline[:0], existing.measureSetValues...)
316 if len(baseline) != len(schema.fields) {
317 baseline = make([]SampleValue, len(schema.fields))
318 }
319 }
320 entry = &stagedMeasureSet{
321 key: key,
322 name: desc.name,
323 hostScopeKey: scope.ScopeKey,
324 hostScope: scope,
325 labels: labels,
326 labelsKey: labelsKey,
327 desc: desc,
328 values: baseline,
329 }
330 c.active.measureSetGauges[key] = entry
331 }
332 for i, deltaValue := range values {
333 entry.values[i] += deltaValue
334 }
335 }
336
337 func (c *storeCore) recordMeasureSetGaugeSetField(desc *instrumentDescriptor, scope HostScope, field string, value SampleValue, sets []LabelSet) {
338 schema := desc.measureSet
339 if schema == nil || schema.semantics != MeasureSetSemanticsGauge {
340 panic(errMeasureSetSchema)
341 }
342
343 fieldIndex := mustMeasureSetFieldIndex(field, schema)
344 mustFiniteSample(value)
345
346 c.mu.Lock()
347 defer c.mu.Unlock()
348
349 if c.active == nil {
350 panic(errCycleInactive)
351 }
352
353 labels, labelsKey, err := labelsFromSet(sets, c)
354 if err != nil {
355 panic(err)
356 }
357 if labelsContainKey(labels, MeasureSetFieldLabel) {
358 panic(errMeasureSetLabelKey)
359 }
360 scope, ok := c.prepareHostScopeForWriteLocked(scope)
361 if !ok {
362 return
363 }
364
365 key := makeSeriesKey(scope.ScopeKey, desc.name, labelsKey)
366 entry, ok := c.active.measureSetGauges[key]
367 if !ok {
368 baseline := make([]SampleValue, len(schema.fields))
369 if existing := c.snapshot.Load().series[key]; existing != nil {
370 baseline = append(baseline[:0], existing.measureSetValues...)
371 if len(baseline) != len(schema.fields) {
372 baseline = make([]SampleValue, len(schema.fields))
373 }
374 }
375 entry = &stagedMeasureSet{
376 key: key,
377 name: desc.name,
378 hostScopeKey: scope.ScopeKey,
379 hostScope: scope,
380 labels: labels,
381 labelsKey: labelsKey,
382 desc: desc,
383 values: baseline,
384 }
385 c.active.measureSetGauges[key] = entry
386 } else if len(entry.values) == 0 {
387 entry.values = make([]SampleValue, len(schema.fields))
388 }
389 entry.values[fieldIndex] = value
390 }
391
392 func (c *storeCore) recordMeasureSetCounterObserveTotalPoint(desc *instrumentDescriptor, scope HostScope, point MeasureSetPoint, sets []LabelSet) {
393 schema := desc.measureSet
394 if schema == nil || schema.semantics != MeasureSetSemanticsCounter {
395 panic(errMeasureSetSchema)
396 }
397
398 values := normalizeMeasureSetPoint(point, schema)
399
400 c.mu.Lock()
401 defer c.mu.Unlock()
402
403 if c.active == nil {
404 panic(errCycleInactive)
405 }
406
407 labels, labelsKey, err := labelsFromSet(sets, c)
408 if err != nil {
409 panic(err)
410 }
411 if labelsContainKey(labels, MeasureSetFieldLabel) {
412 panic(errMeasureSetLabelKey)
413 }
414 scope, ok := c.prepareHostScopeForWriteLocked(scope)
415 if !ok {
416 return
417 }
418
419 key := makeSeriesKey(scope.ScopeKey, desc.name, labelsKey)
420 entry, ok := c.active.measureSetCounters[key]
421 if !ok {
422 entry = &stagedMeasureSet{
423 key: key,
424 name: desc.name,
425 hostScopeKey: scope.ScopeKey,
426 hostScope: scope,
427 labels: labels,
428 labelsKey: labelsKey,
429 desc: desc,
430 }
431 c.active.measureSetCounters[key] = entry
432 }
433 entry.values = append(entry.values[:0], values...)
434 }
435
436 func (c *storeCore) recordMeasureSetCounterAddPoint(desc *instrumentDescriptor, scope HostScope, delta MeasureSetPoint, sets []LabelSet) {
437 schema := desc.measureSet
438 if schema == nil || schema.semantics != MeasureSetSemanticsCounter {
439 panic(errMeasureSetSchema)
440 }
441
442 values := normalizeMeasureSetCounterDelta(delta, schema)
443
444 c.mu.Lock()
445 defer c.mu.Unlock()
446
447 if c.active == nil {
448 panic(errCycleInactive)
449 }
450
451 labels, labelsKey, err := labelsFromSet(sets, c)
452 if err != nil {
453 panic(err)
454 }
455 if labelsContainKey(labels, MeasureSetFieldLabel) {
456 panic(errMeasureSetLabelKey)
457 }
458 scope, ok := c.prepareHostScopeForWriteLocked(scope)
459 if !ok {
460 return
461 }
462
463 key := makeSeriesKey(scope.ScopeKey, desc.name, labelsKey)
464 entry, ok := c.active.measureSetCounters[key]
465 if !ok {
466 baseline := make([]SampleValue, len(schema.fields))
467 if existing := c.snapshot.Load().series[key]; existing != nil {
468 baseline = append(baseline[:0], existing.measureSetValues...)
469 if len(baseline) != len(schema.fields) {
470 baseline = make([]SampleValue, len(schema.fields))
471 }
472 }
473 entry = &stagedMeasureSet{
474 key: key,
475 name: desc.name,
476 hostScopeKey: scope.ScopeKey,
477 hostScope: scope,
478 labels: labels,
479 labelsKey: labelsKey,
480 desc: desc,
481 values: baseline,
482 }
483 c.active.measureSetCounters[key] = entry
484 }
485 for i, deltaValue := range values {
486 entry.values[i] += deltaValue
487 }
488 }