Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/component/otelcol/receiver/prometheus/internal/metrics_adjuster_test.go
5443 views
1
// Copyright The OpenTelemetry Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
package internal
16
17
import (
18
"testing"
19
"time"
20
21
"github.com/stretchr/testify/assert"
22
"go.opentelemetry.io/collector/pdata/pmetric"
23
semconv "go.opentelemetry.io/collector/semconv/v1.8.0"
24
"go.uber.org/zap"
25
)
26
27
var (
28
tUnknown = timestampFromMs(0)
29
t1 = timestampFromMs(1)
30
t2 = timestampFromMs(2)
31
t3 = timestampFromMs(3)
32
t4 = timestampFromMs(4)
33
t5 = timestampFromMs(5)
34
35
bounds0 = []float64{1, 2, 4}
36
percent0 = []float64{10, 50, 90}
37
38
sum1 = "sum1"
39
gauge1 = "gauge1"
40
histogram1 = "histogram1"
41
summary1 = "summary1"
42
43
k1v1k2v2 = []*kv{
44
{"k1", "v1"},
45
{"k2", "v2"},
46
}
47
48
k1v10k2v20 = []*kv{
49
{"k1", "v10"},
50
{"k2", "v20"},
51
}
52
53
k1v100k2v200 = []*kv{
54
{"k1", "v100"},
55
{"k2", "v200"},
56
}
57
58
emptyLabels []*kv
59
k1vEmpty = []*kv{{"k1", ""}}
60
k1vEmptyk2vEmptyk3vEmpty = []*kv{{"k1", ""}, {"k2", ""}, {"k3", ""}}
61
)
62
63
func TestGauge(t *testing.T) {
64
script := []*metricsAdjusterTest{
65
{
66
description: "Gauge: round 1 - gauge not adjusted",
67
metrics: metrics(gaugeMetric(gauge1, doublePoint(k1v1k2v2, t1, t1, 44))),
68
adjusted: metrics(gaugeMetric(gauge1, doublePoint(k1v1k2v2, t1, t1, 44))),
69
},
70
{
71
description: "Gauge: round 2 - gauge not adjusted",
72
metrics: metrics(gaugeMetric(gauge1, doublePoint(k1v1k2v2, t2, t2, 66))),
73
adjusted: metrics(gaugeMetric(gauge1, doublePoint(k1v1k2v2, t2, t2, 66))),
74
},
75
{
76
description: "Gauge: round 3 - value less than previous value - gauge is not adjusted",
77
metrics: metrics(gaugeMetric(gauge1, doublePoint(k1v1k2v2, t3, t3, 55))),
78
adjusted: metrics(gaugeMetric(gauge1, doublePoint(k1v1k2v2, t3, t3, 55))),
79
},
80
}
81
runScript(t, NewInitialPointAdjuster(zap.NewNop(), time.Minute), "job", "0", script)
82
}
83
84
func TestSum(t *testing.T) {
85
script := []*metricsAdjusterTest{
86
{
87
description: "Sum: round 1 - initial instance, start time is established",
88
metrics: metrics(sumMetric(sum1, doublePoint(k1v1k2v2, t1, t1, 44))),
89
adjusted: metrics(sumMetric(sum1, doublePoint(k1v1k2v2, t1, t1, 44))),
90
},
91
{
92
description: "Sum: round 2 - instance adjusted based on round 1",
93
metrics: metrics(sumMetric(sum1, doublePoint(k1v1k2v2, t2, t2, 66))),
94
adjusted: metrics(sumMetric(sum1, doublePoint(k1v1k2v2, t1, t2, 66))),
95
},
96
{
97
description: "Sum: round 3 - instance reset (value less than previous value), start time is reset",
98
metrics: metrics(sumMetric(sum1, doublePoint(k1v1k2v2, t3, t3, 55))),
99
adjusted: metrics(sumMetric(sum1, doublePoint(k1v1k2v2, t3, t3, 55))),
100
},
101
{
102
description: "Sum: round 4 - instance adjusted based on round 3",
103
metrics: metrics(sumMetric(sum1, doublePoint(k1v1k2v2, t4, t4, 72))),
104
adjusted: metrics(sumMetric(sum1, doublePoint(k1v1k2v2, t3, t4, 72))),
105
},
106
{
107
description: "Sum: round 5 - instance adjusted based on round 4",
108
metrics: metrics(sumMetric(sum1, doublePoint(k1v1k2v2, t5, t5, 72))),
109
adjusted: metrics(sumMetric(sum1, doublePoint(k1v1k2v2, t3, t5, 72))),
110
},
111
}
112
runScript(t, NewInitialPointAdjuster(zap.NewNop(), time.Minute), "job", "0", script)
113
}
114
115
func TestSummaryNoCount(t *testing.T) {
116
script := []*metricsAdjusterTest{
117
{
118
description: "Summary No Count: round 1 - initial instance, start time is established",
119
metrics: metrics(summaryMetric(summary1, summaryPoint(k1v1k2v2, t1, t1, 0, 40, percent0, []float64{1, 5, 8}))),
120
adjusted: metrics(summaryMetric(summary1, summaryPoint(k1v1k2v2, t1, t1, 0, 40, percent0, []float64{1, 5, 8}))),
121
},
122
{
123
description: "Summary No Count: round 2 - instance adjusted based on round 1",
124
metrics: metrics(summaryMetric(summary1, summaryPoint(k1v1k2v2, t2, t2, 0, 70, percent0, []float64{7, 44, 9}))),
125
adjusted: metrics(summaryMetric(summary1, summaryPoint(k1v1k2v2, t1, t2, 0, 70, percent0, []float64{7, 44, 9}))),
126
},
127
{
128
description: "Summary No Count: round 3 - instance reset (count less than previous), start time is reset",
129
metrics: metrics(summaryMetric(summary1, summaryPoint(k1v1k2v2, t3, t3, 0, 66, percent0, []float64{3, 22, 5}))),
130
adjusted: metrics(summaryMetric(summary1, summaryPoint(k1v1k2v2, t3, t3, 0, 66, percent0, []float64{3, 22, 5}))),
131
},
132
{
133
description: "Summary No Count: round 4 - instance adjusted based on round 3",
134
metrics: metrics(summaryMetric(summary1, summaryPoint(k1v1k2v2, t4, t4, 0, 96, percent0, []float64{9, 47, 8}))),
135
adjusted: metrics(summaryMetric(summary1, summaryPoint(k1v1k2v2, t3, t4, 0, 96, percent0, []float64{9, 47, 8}))),
136
},
137
}
138
139
runScript(t, NewInitialPointAdjuster(zap.NewNop(), time.Minute), "job", "0", script)
140
}
141
142
func TestSummaryFlagNoRecordedValue(t *testing.T) {
143
script := []*metricsAdjusterTest{
144
{
145
description: "Summary No Count: round 1 - initial instance, start time is established",
146
metrics: metrics(summaryMetric(summary1, summaryPoint(k1v1k2v2, t1, t1, 0, 40, percent0, []float64{1, 5, 8}))),
147
adjusted: metrics(summaryMetric(summary1, summaryPoint(k1v1k2v2, t1, t1, 0, 40, percent0, []float64{1, 5, 8}))),
148
},
149
{
150
description: "Summary Flag NoRecordedValue: round 2 - instance adjusted based on round 1",
151
metrics: metrics(summaryMetric(summary1, summaryPointNoValue(k1v1k2v2, t2, t2))),
152
adjusted: metrics(summaryMetric(summary1, summaryPointNoValue(k1v1k2v2, t1, t2))),
153
},
154
}
155
156
runScript(t, NewInitialPointAdjuster(zap.NewNop(), time.Minute), "job", "0", script)
157
}
158
159
func TestSummary(t *testing.T) {
160
script := []*metricsAdjusterTest{
161
{
162
description: "Summary: round 1 - initial instance, start time is established",
163
metrics: metrics(
164
summaryMetric(summary1, summaryPoint(k1v1k2v2, t1, t1, 10, 40, percent0, []float64{1, 5, 8})),
165
),
166
adjusted: metrics(
167
summaryMetric(summary1, summaryPoint(k1v1k2v2, t1, t1, 10, 40, percent0, []float64{1, 5, 8})),
168
),
169
},
170
{
171
description: "Summary: round 2 - instance adjusted based on round 1",
172
metrics: metrics(
173
summaryMetric(summary1, summaryPoint(k1v1k2v2, t2, t2, 15, 70, percent0, []float64{7, 44, 9})),
174
),
175
adjusted: metrics(
176
summaryMetric(summary1, summaryPoint(k1v1k2v2, t1, t2, 15, 70, percent0, []float64{7, 44, 9})),
177
),
178
},
179
{
180
description: "Summary: round 3 - instance reset (count less than previous), start time is reset",
181
metrics: metrics(
182
summaryMetric(summary1, summaryPoint(k1v1k2v2, t3, t3, 12, 66, percent0, []float64{3, 22, 5})),
183
),
184
adjusted: metrics(
185
summaryMetric(summary1, summaryPoint(k1v1k2v2, t3, t3, 12, 66, percent0, []float64{3, 22, 5})),
186
),
187
},
188
{
189
description: "Summary: round 4 - instance adjusted based on round 3",
190
metrics: metrics(
191
summaryMetric(summary1, summaryPoint(k1v1k2v2, t4, t4, 14, 96, percent0, []float64{9, 47, 8})),
192
),
193
adjusted: metrics(
194
summaryMetric(summary1, summaryPoint(k1v1k2v2, t3, t4, 14, 96, percent0, []float64{9, 47, 8})),
195
),
196
},
197
}
198
199
runScript(t, NewInitialPointAdjuster(zap.NewNop(), time.Minute), "job", "0", script)
200
}
201
202
func TestHistogram(t *testing.T) {
203
script := []*metricsAdjusterTest{
204
{
205
description: "Histogram: round 1 - initial instance, start time is established",
206
metrics: metrics(histogramMetric(histogram1, histogramPoint(k1v1k2v2, t1, t1, bounds0, []uint64{4, 2, 3, 7}))),
207
adjusted: metrics(histogramMetric(histogram1, histogramPoint(k1v1k2v2, t1, t1, bounds0, []uint64{4, 2, 3, 7}))),
208
}, {
209
description: "Histogram: round 2 - instance adjusted based on round 1",
210
metrics: metrics(histogramMetric(histogram1, histogramPoint(k1v1k2v2, t2, t2, bounds0, []uint64{6, 3, 4, 8}))),
211
adjusted: metrics(histogramMetric(histogram1, histogramPoint(k1v1k2v2, t1, t2, bounds0, []uint64{6, 3, 4, 8}))),
212
}, {
213
description: "Histogram: round 3 - instance reset (value less than previous value), start time is reset",
214
metrics: metrics(histogramMetric(histogram1, histogramPoint(k1v1k2v2, t3, t3, bounds0, []uint64{5, 3, 2, 7}))),
215
adjusted: metrics(histogramMetric(histogram1, histogramPoint(k1v1k2v2, t3, t3, bounds0, []uint64{5, 3, 2, 7}))),
216
}, {
217
description: "Histogram: round 4 - instance adjusted based on round 3",
218
metrics: metrics(histogramMetric(histogram1, histogramPoint(k1v1k2v2, t4, t4, bounds0, []uint64{7, 4, 2, 12}))),
219
adjusted: metrics(histogramMetric(histogram1, histogramPoint(k1v1k2v2, t3, t4, bounds0, []uint64{7, 4, 2, 12}))),
220
},
221
}
222
runScript(t, NewInitialPointAdjuster(zap.NewNop(), time.Minute), "job", "0", script)
223
}
224
225
func TestHistogramFlagNoRecordedValue(t *testing.T) {
226
script := []*metricsAdjusterTest{
227
{
228
description: "Histogram: round 1 - initial instance, start time is established",
229
metrics: metrics(histogramMetric(histogram1, histogramPoint(k1v1k2v2, t1, t1, bounds0, []uint64{7, 4, 2, 12}))),
230
adjusted: metrics(histogramMetric(histogram1, histogramPoint(k1v1k2v2, t1, t1, bounds0, []uint64{7, 4, 2, 12}))),
231
},
232
{
233
description: "Histogram: round 2 - instance adjusted based on round 1",
234
metrics: metrics(histogramMetric(histogram1, histogramPointNoValue(k1v1k2v2, tUnknown, t2))),
235
adjusted: metrics(histogramMetric(histogram1, histogramPointNoValue(k1v1k2v2, t1, t2))),
236
},
237
}
238
239
runScript(t, NewInitialPointAdjuster(zap.NewNop(), time.Minute), "job", "0", script)
240
}
241
242
func TestHistogramFlagNoRecordedValueFirstObservation(t *testing.T) {
243
script := []*metricsAdjusterTest{
244
{
245
description: "Histogram: round 1 - initial instance, start time is unknown",
246
metrics: metrics(histogramMetric(histogram1, histogramPointNoValue(k1v1k2v2, tUnknown, t1))),
247
adjusted: metrics(histogramMetric(histogram1, histogramPointNoValue(k1v1k2v2, tUnknown, t1))),
248
},
249
{
250
description: "Histogram: round 2 - instance unchanged",
251
metrics: metrics(histogramMetric(histogram1, histogramPointNoValue(k1v1k2v2, tUnknown, t2))),
252
adjusted: metrics(histogramMetric(histogram1, histogramPointNoValue(k1v1k2v2, tUnknown, t2))),
253
},
254
}
255
256
runScript(t, NewInitialPointAdjuster(zap.NewNop(), time.Minute), "job", "0", script)
257
}
258
259
func TestSummaryFlagNoRecordedValueFirstObservation(t *testing.T) {
260
script := []*metricsAdjusterTest{
261
{
262
description: "Summary: round 1 - initial instance, start time is unknown",
263
metrics: metrics(summaryMetric(summary1, summaryPointNoValue(k1v1k2v2, tUnknown, t1))),
264
adjusted: metrics(summaryMetric(summary1, summaryPointNoValue(k1v1k2v2, tUnknown, t1))),
265
},
266
{
267
description: "Summary: round 2 - instance unchanged",
268
metrics: metrics(summaryMetric(summary1, summaryPointNoValue(k1v1k2v2, tUnknown, t2))),
269
adjusted: metrics(summaryMetric(summary1, summaryPointNoValue(k1v1k2v2, tUnknown, t2))),
270
},
271
}
272
273
runScript(t, NewInitialPointAdjuster(zap.NewNop(), time.Minute), "job", "0", script)
274
}
275
276
func TestGaugeFlagNoRecordedValueFirstObservation(t *testing.T) {
277
script := []*metricsAdjusterTest{
278
{
279
description: "Gauge: round 1 - initial instance, start time is unknown",
280
metrics: metrics(gaugeMetric(gauge1, doublePointNoValue(k1v1k2v2, tUnknown, t1))),
281
adjusted: metrics(gaugeMetric(gauge1, doublePointNoValue(k1v1k2v2, tUnknown, t1))),
282
},
283
{
284
description: "Gauge: round 2 - instance unchanged",
285
metrics: metrics(gaugeMetric(gauge1, doublePointNoValue(k1v1k2v2, tUnknown, t2))),
286
adjusted: metrics(gaugeMetric(gauge1, doublePointNoValue(k1v1k2v2, tUnknown, t2))),
287
},
288
}
289
290
runScript(t, NewInitialPointAdjuster(zap.NewNop(), time.Minute), "job", "0", script)
291
}
292
293
func TestSumFlagNoRecordedValueFirstObservation(t *testing.T) {
294
script := []*metricsAdjusterTest{
295
{
296
description: "Sum: round 1 - initial instance, start time is unknown",
297
metrics: metrics(sumMetric("sum1", doublePointNoValue(k1v1k2v2, tUnknown, t1))),
298
adjusted: metrics(sumMetric("sum1", doublePointNoValue(k1v1k2v2, tUnknown, t1))),
299
},
300
{
301
description: "Sum: round 2 - instance unchanged",
302
metrics: metrics(sumMetric("sum1", doublePointNoValue(k1v1k2v2, tUnknown, t2))),
303
adjusted: metrics(sumMetric("sum1", doublePointNoValue(k1v1k2v2, tUnknown, t2))),
304
},
305
}
306
307
runScript(t, NewInitialPointAdjuster(zap.NewNop(), time.Minute), "job", "0", script)
308
}
309
310
func TestMultiMetrics(t *testing.T) {
311
script := []*metricsAdjusterTest{
312
{
313
description: "MultiMetrics: round 1 - combined round 1 of individual metrics",
314
metrics: metrics(
315
gaugeMetric(gauge1, doublePoint(k1v1k2v2, t1, t1, 44)),
316
sumMetric(sum1, doublePoint(k1v1k2v2, t1, t1, 44)),
317
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t1, t1, bounds0, []uint64{4, 2, 3, 7})),
318
summaryMetric(summary1, summaryPoint(k1v1k2v2, t1, t1, 10, 40, percent0, []float64{1, 5, 8})),
319
),
320
adjusted: metrics(
321
gaugeMetric(gauge1, doublePoint(k1v1k2v2, t1, t1, 44)),
322
sumMetric(sum1, doublePoint(k1v1k2v2, t1, t1, 44)),
323
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t1, t1, bounds0, []uint64{4, 2, 3, 7})),
324
summaryMetric(summary1, summaryPoint(k1v1k2v2, t1, t1, 10, 40, percent0, []float64{1, 5, 8})),
325
),
326
},
327
{
328
description: "MultiMetrics: round 2 - combined round 2 of individual metrics",
329
metrics: metrics(
330
gaugeMetric(gauge1, doublePoint(k1v1k2v2, t2, t2, 66)),
331
sumMetric(sum1, doublePoint(k1v1k2v2, t2, t2, 66)),
332
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t2, t2, bounds0, []uint64{6, 3, 4, 8})),
333
summaryMetric(summary1, summaryPoint(k1v1k2v2, t2, t2, 15, 70, percent0, []float64{7, 44, 9})),
334
),
335
adjusted: metrics(
336
gaugeMetric(gauge1, doublePoint(k1v1k2v2, t2, t2, 66)),
337
sumMetric(sum1, doublePoint(k1v1k2v2, t1, t2, 66)),
338
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t1, t2, bounds0, []uint64{6, 3, 4, 8})),
339
summaryMetric(summary1, summaryPoint(k1v1k2v2, t1, t2, 15, 70, percent0, []float64{7, 44, 9})),
340
),
341
},
342
{
343
description: "MultiMetrics: round 3 - combined round 3 of individual metrics",
344
metrics: metrics(
345
gaugeMetric(gauge1, doublePoint(k1v1k2v2, t3, t3, 55)),
346
sumMetric(sum1, doublePoint(k1v1k2v2, t3, t3, 55)),
347
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t3, t3, bounds0, []uint64{5, 3, 2, 7})),
348
summaryMetric(summary1, summaryPoint(k1v1k2v2, t3, t3, 12, 66, percent0, []float64{3, 22, 5})),
349
),
350
adjusted: metrics(
351
gaugeMetric(gauge1, doublePoint(k1v1k2v2, t3, t3, 55)),
352
sumMetric(sum1, doublePoint(k1v1k2v2, t3, t3, 55)),
353
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t3, t3, bounds0, []uint64{5, 3, 2, 7})),
354
summaryMetric(summary1, summaryPoint(k1v1k2v2, t3, t3, 12, 66, percent0, []float64{3, 22, 5})),
355
),
356
},
357
{
358
description: "MultiMetrics: round 4 - combined round 4 of individual metrics",
359
metrics: metrics(
360
sumMetric(sum1, doublePoint(k1v1k2v2, t4, t4, 72)),
361
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t4, t4, bounds0, []uint64{7, 4, 2, 12})),
362
summaryMetric(summary1, summaryPoint(k1v1k2v2, t4, t4, 14, 96, percent0, []float64{9, 47, 8})),
363
),
364
adjusted: metrics(
365
sumMetric(sum1, doublePoint(k1v1k2v2, t3, t4, 72)),
366
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t3, t4, bounds0, []uint64{7, 4, 2, 12})),
367
summaryMetric(summary1, summaryPoint(k1v1k2v2, t3, t4, 14, 96, percent0, []float64{9, 47, 8})),
368
),
369
},
370
}
371
runScript(t, NewInitialPointAdjuster(zap.NewNop(), time.Minute), "job", "0", script)
372
}
373
374
func TestNewDataPointsAdded(t *testing.T) {
375
script := []*metricsAdjusterTest{
376
{
377
description: "New Datapoints: round 1 - two datapoints each",
378
metrics: metrics(
379
sumMetric(sum1,
380
doublePoint(k1v1k2v2, t1, t1, 44),
381
doublePoint(k1v100k2v200, t1, t1, 44)),
382
histogramMetric(histogram1,
383
histogramPoint(k1v1k2v2, t1, t1, bounds0, []uint64{4, 2, 3, 7}),
384
histogramPoint(k1v100k2v200, t1, t1, bounds0, []uint64{4, 2, 3, 7})),
385
summaryMetric(summary1,
386
summaryPoint(k1v1k2v2, t1, t1, 10, 40, percent0, []float64{1, 5, 8}),
387
summaryPoint(k1v100k2v200, t1, t1, 10, 40, percent0, []float64{1, 5, 8})),
388
),
389
adjusted: metrics(
390
sumMetric(sum1,
391
doublePoint(k1v1k2v2, t1, t1, 44),
392
doublePoint(k1v100k2v200, t1, t1, 44)),
393
histogramMetric(histogram1,
394
histogramPoint(k1v1k2v2, t1, t1, bounds0, []uint64{4, 2, 3, 7}),
395
histogramPoint(k1v100k2v200, t1, t1, bounds0, []uint64{4, 2, 3, 7})),
396
summaryMetric(summary1,
397
summaryPoint(k1v1k2v2, t1, t1, 10, 40, percent0, []float64{1, 5, 8}),
398
summaryPoint(k1v100k2v200, t1, t1, 10, 40, percent0, []float64{1, 5, 8})),
399
),
400
},
401
{
402
description: "New Datapoints: round 2 - new datapoints unchanged, old datapoints adjusted",
403
metrics: metrics(
404
sumMetric(sum1,
405
doublePoint(k1v1k2v2, t2, t2, 44),
406
doublePoint(k1v10k2v20, t2, t2, 44),
407
doublePoint(k1v100k2v200, t2, t2, 44)),
408
histogramMetric(histogram1,
409
histogramPoint(k1v1k2v2, t2, t2, bounds0, []uint64{4, 2, 3, 7}),
410
histogramPoint(k1v10k2v20, t2, t2, bounds0, []uint64{4, 2, 3, 7}),
411
histogramPoint(k1v100k2v200, t2, t2, bounds0, []uint64{4, 2, 3, 7})),
412
summaryMetric(summary1,
413
summaryPoint(k1v1k2v2, t2, t2, 10, 40, percent0, []float64{1, 5, 8}),
414
summaryPoint(k1v10k2v20, t2, t2, 10, 40, percent0, []float64{1, 5, 8}),
415
summaryPoint(k1v100k2v200, t2, t2, 10, 40, percent0, []float64{1, 5, 8})),
416
),
417
adjusted: metrics(
418
sumMetric(sum1,
419
doublePoint(k1v1k2v2, t1, t2, 44),
420
doublePoint(k1v10k2v20, t2, t2, 44),
421
doublePoint(k1v100k2v200, t1, t2, 44)),
422
histogramMetric(histogram1,
423
histogramPoint(k1v1k2v2, t1, t2, bounds0, []uint64{4, 2, 3, 7}),
424
histogramPoint(k1v10k2v20, t2, t2, bounds0, []uint64{4, 2, 3, 7}),
425
histogramPoint(k1v100k2v200, t1, t2, bounds0, []uint64{4, 2, 3, 7})),
426
summaryMetric(summary1,
427
summaryPoint(k1v1k2v2, t1, t2, 10, 40, percent0, []float64{1, 5, 8}),
428
summaryPoint(k1v10k2v20, t2, t2, 10, 40, percent0, []float64{1, 5, 8}),
429
summaryPoint(k1v100k2v200, t1, t2, 10, 40, percent0, []float64{1, 5, 8})),
430
),
431
},
432
}
433
runScript(t, NewInitialPointAdjuster(zap.NewNop(), time.Minute), "job", "0", script)
434
}
435
436
func TestMultiTimeseries(t *testing.T) {
437
script := []*metricsAdjusterTest{
438
{
439
description: "MultiTimeseries: round 1 - initial first instance, start time is established",
440
metrics: metrics(sumMetric(sum1, doublePoint(k1v1k2v2, t1, t1, 44))),
441
adjusted: metrics(sumMetric(sum1, doublePoint(k1v1k2v2, t1, t1, 44))),
442
},
443
{
444
description: "MultiTimeseries: round 2 - first instance adjusted based on round 1, initial second instance",
445
metrics: metrics(
446
sumMetric(sum1, doublePoint(k1v1k2v2, t2, t2, 66)),
447
sumMetric(sum1, doublePoint(k1v10k2v20, t2, t2, 20.0)),
448
),
449
adjusted: metrics(
450
sumMetric(sum1, doublePoint(k1v1k2v2, t1, t2, 66)),
451
sumMetric(sum1, doublePoint(k1v10k2v20, t2, t2, 20.0)),
452
),
453
},
454
{
455
description: "MultiTimeseries: round 3 - first instance adjusted based on round 1, second based on round 2",
456
metrics: metrics(
457
sumMetric(sum1, doublePoint(k1v1k2v2, t3, t3, 88.0)),
458
sumMetric(sum1, doublePoint(k1v10k2v20, t3, t3, 49.0)),
459
),
460
adjusted: metrics(
461
sumMetric(sum1, doublePoint(k1v1k2v2, t1, t3, 88.0)),
462
sumMetric(sum1, doublePoint(k1v10k2v20, t2, t3, 49.0)),
463
),
464
},
465
{
466
description: "MultiTimeseries: round 4 - first instance reset, second instance adjusted based on round 2, initial third instance",
467
metrics: metrics(
468
sumMetric(sum1, doublePoint(k1v1k2v2, t4, t4, 87.0)),
469
sumMetric(sum1, doublePoint(k1v10k2v20, t4, t4, 57.0)),
470
sumMetric(sum1, doublePoint(k1v100k2v200, t4, t4, 10.0)),
471
),
472
adjusted: metrics(
473
sumMetric(sum1, doublePoint(k1v1k2v2, t4, t4, 87.0)),
474
sumMetric(sum1, doublePoint(k1v10k2v20, t2, t4, 57.0)),
475
sumMetric(sum1, doublePoint(k1v100k2v200, t4, t4, 10.0)),
476
),
477
},
478
{
479
description: "MultiTimeseries: round 5 - first instance adjusted based on round 4, second on round 2, third on round 4",
480
metrics: metrics(
481
sumMetric(sum1, doublePoint(k1v1k2v2, t5, t5, 90.0)),
482
sumMetric(sum1, doublePoint(k1v10k2v20, t5, t5, 65.0)),
483
sumMetric(sum1, doublePoint(k1v100k2v200, t5, t5, 22.0)),
484
),
485
adjusted: metrics(
486
sumMetric(sum1, doublePoint(k1v1k2v2, t4, t5, 90.0)),
487
sumMetric(sum1, doublePoint(k1v10k2v20, t2, t5, 65.0)),
488
sumMetric(sum1, doublePoint(k1v100k2v200, t4, t5, 22.0)),
489
),
490
},
491
}
492
runScript(t, NewInitialPointAdjuster(zap.NewNop(), time.Minute), "job", "0", script)
493
}
494
495
func TestEmptyLabels(t *testing.T) {
496
script := []*metricsAdjusterTest{
497
{
498
description: "EmptyLabels: round 1 - initial instance, implicitly empty labels, start time is established",
499
metrics: metrics(sumMetric(sum1, doublePoint(emptyLabels, t1, t1, 44))),
500
adjusted: metrics(sumMetric(sum1, doublePoint(emptyLabels, t1, t1, 44))),
501
},
502
{
503
description: "EmptyLabels: round 2 - instance adjusted based on round 1",
504
metrics: metrics(sumMetric(sum1, doublePoint(emptyLabels, t2, t2, 66))),
505
adjusted: metrics(sumMetric(sum1, doublePoint(emptyLabels, t1, t2, 66))),
506
},
507
{
508
description: "EmptyLabels: round 3 - one explicitly empty label, instance adjusted based on round 1",
509
metrics: metrics(sumMetric(sum1, doublePoint(k1vEmpty, t3, t3, 77))),
510
adjusted: metrics(sumMetric(sum1, doublePoint(k1vEmpty, t1, t3, 77))),
511
},
512
{
513
description: "EmptyLabels: round 4 - three explicitly empty labels, instance adjusted based on round 1",
514
metrics: metrics(sumMetric(sum1, doublePoint(k1vEmptyk2vEmptyk3vEmpty, t3, t3, 88))),
515
adjusted: metrics(sumMetric(sum1, doublePoint(k1vEmptyk2vEmptyk3vEmpty, t1, t3, 88))),
516
},
517
}
518
runScript(t, NewInitialPointAdjuster(zap.NewNop(), time.Minute), "job", "0", script)
519
}
520
521
func TestTsGC(t *testing.T) {
522
script1 := []*metricsAdjusterTest{
523
{
524
description: "TsGC: round 1 - initial instances, start time is established",
525
metrics: metrics(
526
sumMetric(sum1, doublePoint(k1v1k2v2, t1, t1, 44)),
527
sumMetric(sum1, doublePoint(k1v10k2v20, t1, t1, 20)),
528
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t1, t1, bounds0, []uint64{4, 2, 3, 7})),
529
histogramMetric(histogram1, histogramPoint(k1v10k2v20, t1, t1, bounds0, []uint64{40, 20, 30, 70})),
530
),
531
adjusted: metrics(
532
sumMetric(sum1, doublePoint(k1v1k2v2, t1, t1, 44)),
533
sumMetric(sum1, doublePoint(k1v10k2v20, t1, t1, 20)),
534
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t1, t1, bounds0, []uint64{4, 2, 3, 7})),
535
histogramMetric(histogram1, histogramPoint(k1v10k2v20, t1, t1, bounds0, []uint64{40, 20, 30, 70})),
536
),
537
},
538
}
539
540
script2 := []*metricsAdjusterTest{
541
{
542
description: "TsGC: round 2 - metrics first timeseries adjusted based on round 2, second timeseries not updated",
543
metrics: metrics(
544
sumMetric(sum1, doublePoint(k1v1k2v2, t2, t2, 88)),
545
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t2, t2, bounds0, []uint64{8, 7, 9, 14})),
546
),
547
adjusted: metrics(
548
sumMetric(sum1, doublePoint(k1v1k2v2, t1, t2, 88)),
549
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t1, t2, bounds0, []uint64{8, 7, 9, 14})),
550
),
551
},
552
}
553
554
script3 := []*metricsAdjusterTest{
555
{
556
description: "TsGC: round 3 - metrics first timeseries adjusted based on round 2, second timeseries empty due to timeseries gc()",
557
metrics: metrics(
558
sumMetric(sum1, doublePoint(k1v1k2v2, t3, t3, 99)),
559
sumMetric(sum1, doublePoint(k1v10k2v20, t3, t3, 80)),
560
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t3, t3, bounds0, []uint64{9, 8, 10, 15})),
561
histogramMetric(histogram1, histogramPoint(k1v10k2v20, t3, t3, bounds0, []uint64{55, 66, 33, 77})),
562
),
563
adjusted: metrics(
564
sumMetric(sum1, doublePoint(k1v1k2v2, t1, t3, 99)),
565
sumMetric(sum1, doublePoint(k1v10k2v20, t3, t3, 80)),
566
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t1, t3, bounds0, []uint64{9, 8, 10, 15})),
567
histogramMetric(histogram1, histogramPoint(k1v10k2v20, t3, t3, bounds0, []uint64{55, 66, 33, 77})),
568
),
569
},
570
}
571
572
ma := NewInitialPointAdjuster(zap.NewNop(), time.Minute)
573
574
// run round 1
575
runScript(t, ma, "job", "0", script1)
576
// gc the tsmap, unmarking all entries
577
ma.(*initialPointAdjuster).jobsMap.get("job", "0").gc()
578
// run round 2 - update metrics first timeseries only
579
runScript(t, ma, "job", "0", script2)
580
// gc the tsmap, collecting umarked entries
581
ma.(*initialPointAdjuster).jobsMap.get("job", "0").gc()
582
// run round 3 - verify that metrics second timeseries have been gc'd
583
runScript(t, ma, "job", "0", script3)
584
}
585
586
func TestJobGC(t *testing.T) {
587
job1Script1 := []*metricsAdjusterTest{
588
{
589
description: "JobGC: job 1, round 1 - initial instances, adjusted should be empty",
590
metrics: metrics(
591
sumMetric(sum1, doublePoint(k1v1k2v2, t1, t1, 44)),
592
sumMetric(sum1, doublePoint(k1v10k2v20, t1, t1, 20)),
593
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t1, t1, bounds0, []uint64{4, 2, 3, 7})),
594
histogramMetric(histogram1, histogramPoint(k1v10k2v20, t1, t1, bounds0, []uint64{40, 20, 30, 70})),
595
),
596
adjusted: metrics(
597
sumMetric(sum1, doublePoint(k1v1k2v2, t1, t1, 44)),
598
sumMetric(sum1, doublePoint(k1v10k2v20, t1, t1, 20)),
599
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t1, t1, bounds0, []uint64{4, 2, 3, 7})),
600
histogramMetric(histogram1, histogramPoint(k1v10k2v20, t1, t1, bounds0, []uint64{40, 20, 30, 70})),
601
),
602
},
603
}
604
605
job2Script1 := []*metricsAdjusterTest{
606
{
607
description: "JobGC: job2, round 1 - no metrics adjusted, just trigger gc",
608
metrics: metrics(),
609
adjusted: metrics(),
610
},
611
}
612
613
job1Script2 := []*metricsAdjusterTest{
614
{
615
description: "JobGC: job 1, round 2 - metrics timeseries empty due to job-level gc",
616
metrics: metrics(
617
sumMetric(sum1, doublePoint(k1v1k2v2, t4, t4, 99)),
618
sumMetric(sum1, doublePoint(k1v10k2v20, t4, t4, 80)),
619
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t4, t4, bounds0, []uint64{9, 8, 10, 15})),
620
histogramMetric(histogram1, histogramPoint(k1v10k2v20, t4, t4, bounds0, []uint64{55, 66, 33, 77})),
621
),
622
adjusted: metrics(
623
sumMetric(sum1, doublePoint(k1v1k2v2, t4, t4, 99)),
624
sumMetric(sum1, doublePoint(k1v10k2v20, t4, t4, 80)),
625
histogramMetric(histogram1, histogramPoint(k1v1k2v2, t4, t4, bounds0, []uint64{9, 8, 10, 15})),
626
histogramMetric(histogram1, histogramPoint(k1v10k2v20, t4, t4, bounds0, []uint64{55, 66, 33, 77})),
627
),
628
},
629
}
630
631
gcInterval := 10 * time.Millisecond
632
ma := NewInitialPointAdjuster(zap.NewNop(), gcInterval)
633
634
// run job 1, round 1 - all entries marked
635
runScript(t, ma, "job1", "0", job1Script1)
636
// sleep longer than gcInterval to enable job gc in the next run
637
time.Sleep(2 * gcInterval)
638
// run job 2, round1 - trigger job gc, unmarking all entries
639
runScript(t, ma, "job1", "1", job2Script1)
640
// sleep longer than gcInterval to enable job gc in the next run
641
time.Sleep(2 * gcInterval)
642
// re-run job 2, round1 - trigger job gc, removing unmarked entries
643
runScript(t, ma, "job1", "1", job2Script1)
644
// ensure that at least one jobsMap.gc() completed
645
ma.(*initialPointAdjuster).jobsMap.gc()
646
// run job 1, round 2 - verify that all job 1 timeseries have been gc'd
647
runScript(t, ma, "job1", "0", job1Script2)
648
}
649
650
type metricsAdjusterTest struct {
651
description string
652
metrics pmetric.Metrics
653
adjusted pmetric.Metrics
654
}
655
656
func runScript(t *testing.T, ma MetricsAdjuster, job, instance string, tests []*metricsAdjusterTest) {
657
for _, test := range tests {
658
t.Run(test.description, func(t *testing.T) {
659
adjusted := pmetric.NewMetrics()
660
test.metrics.CopyTo(adjusted)
661
// Add the instance/job to the input metrics.
662
adjusted.ResourceMetrics().At(0).Resource().Attributes().PutStr(semconv.AttributeServiceInstanceID, instance)
663
adjusted.ResourceMetrics().At(0).Resource().Attributes().PutStr(semconv.AttributeServiceName, job)
664
assert.NoError(t, ma.AdjustMetrics(adjusted))
665
666
// Add the instance/job to the expected metrics as well.
667
test.adjusted.ResourceMetrics().At(0).Resource().Attributes().PutStr(semconv.AttributeServiceInstanceID, instance)
668
test.adjusted.ResourceMetrics().At(0).Resource().Attributes().PutStr(semconv.AttributeServiceName, job)
669
assert.EqualValues(t, test.adjusted, adjusted)
670
})
671
}
672
}
673
674