Skip to content

Commit 951bff7

Browse files
committed
nativehistogram exemplar test
1 parent 819d3c1 commit 951bff7

File tree

1 file changed

+189
-0
lines changed

1 file changed

+189
-0
lines changed

prometheus/metric_test.go

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
package prometheus
1515

1616
import (
17+
"errors"
18+
"fmt"
1719
"math"
1820
"testing"
1921
"time"
@@ -167,4 +169,191 @@ func TestWithExemplarsNativeHistogramMetric(t *testing.T) {
167169
}
168170
}
169171
})
172+
t.Run("nativehistogram metric exemplars should be available in both buckets and exemplars", func(t *testing.T) {
173+
now := time.Now()
174+
tcs := []struct {
175+
Name string
176+
Count uint64
177+
Sum float64
178+
PositiveBuckets map[int]int64
179+
NegativeBuckets map[int]int64
180+
ZeroBucket uint64
181+
NativeHistogramSchema int32
182+
NativeHistogramZeroThreshold float64
183+
CreatedTimestamp time.Time
184+
Bucket []*dto.Bucket
185+
Exemplars []Exemplar
186+
Want *dto.Metric
187+
}{
188+
{
189+
Name: "nativehistogram metric exemplars should be available in both buckets and exemplars",
190+
Count: 6,
191+
Sum: 7.4,
192+
PositiveBuckets: map[int]int64{
193+
0: 1, 2: 2, 4: 2,
194+
},
195+
NegativeBuckets: map[int]int64{},
196+
ZeroBucket: 1,
197+
198+
NativeHistogramSchema: 2,
199+
NativeHistogramZeroThreshold: 2.938735877055719e-39,
200+
CreatedTimestamp: now,
201+
Bucket: []*dto.Bucket{
202+
{
203+
CumulativeCount: PointOf(uint64(6)),
204+
UpperBound: PointOf(float64(1)),
205+
},
206+
{
207+
CumulativeCount: PointOf(uint64(8)),
208+
UpperBound: PointOf(float64(2)),
209+
},
210+
{
211+
CumulativeCount: PointOf(uint64(11)),
212+
UpperBound: PointOf(float64(5)),
213+
},
214+
{
215+
CumulativeCount: PointOf(uint64(13)),
216+
UpperBound: PointOf(float64(10)),
217+
},
218+
},
219+
Exemplars: []Exemplar{
220+
{
221+
Timestamp: now,
222+
Value: 10,
223+
},
224+
},
225+
Want: &dto.Metric{
226+
Histogram: &dto.Histogram{
227+
SampleCount: proto.Uint64(6),
228+
SampleSum: proto.Float64(7.4),
229+
Schema: proto.Int32(2),
230+
ZeroThreshold: proto.Float64(2.938735877055719e-39),
231+
ZeroCount: proto.Uint64(1),
232+
PositiveSpan: []*dto.BucketSpan{
233+
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
234+
},
235+
PositiveDelta: []int64{1, -1, 2, -2, 2},
236+
Exemplars: []*dto.Exemplar{
237+
{
238+
Value: PointOf(float64(10)),
239+
Timestamp: timestamppb.New(now),
240+
},
241+
},
242+
Bucket: []*dto.Bucket{
243+
{
244+
CumulativeCount: PointOf(uint64(6)),
245+
UpperBound: PointOf(float64(1)),
246+
},
247+
{
248+
CumulativeCount: PointOf(uint64(8)),
249+
UpperBound: PointOf(float64(2)),
250+
},
251+
{
252+
CumulativeCount: PointOf(uint64(11)),
253+
UpperBound: PointOf(float64(5)),
254+
},
255+
{
256+
CumulativeCount: PointOf(uint64(13)),
257+
UpperBound: PointOf(float64(10)),
258+
Exemplar: &dto.Exemplar{
259+
Timestamp: timestamppb.New(now),
260+
Value: PointOf(float64(10)),
261+
},
262+
},
263+
},
264+
CreatedTimestamp: timestamppb.New(now),
265+
},
266+
},
267+
},
268+
}
269+
270+
for _, tc := range tcs {
271+
m, err := NewDummyConstNativeHistogram(NewDesc(tc.Name, "None", []string{}, map[string]string{}), tc.Count, tc.Sum, tc.PositiveBuckets, tc.NegativeBuckets, tc.ZeroBucket, tc.NativeHistogramSchema, tc.NativeHistogramZeroThreshold, tc.CreatedTimestamp, tc.Bucket)
272+
if err != nil {
273+
fmt.Println(err)
274+
t.Fail()
275+
}
276+
metricWithExemplar, err := NewMetricWithExemplars(m, tc.Exemplars[0])
277+
if err != nil {
278+
fmt.Println(err)
279+
t.Fail()
280+
}
281+
got := &dto.Metric{}
282+
err = metricWithExemplar.Write(got)
283+
if err != nil {
284+
fmt.Println(err)
285+
t.Fail()
286+
}
287+
288+
if !proto.Equal(tc.Want, got) {
289+
t.Errorf("want histogram %q, got %q", tc.Want, got)
290+
}
291+
292+
}
293+
})
294+
}
295+
296+
func PointOf[T any](value T) *T {
297+
return &value
298+
}
299+
300+
// This is a dummy Histogram which has both buckets and nativehistogram
301+
// to test metrics with exemplars
302+
func NewDummyConstNativeHistogram(
303+
desc *Desc,
304+
count uint64,
305+
sum float64,
306+
positiveBuckets, negativeBuckets map[int]int64,
307+
zeroBucket uint64,
308+
schema int32,
309+
zeroThreshold float64,
310+
createdTimestamp time.Time,
311+
// DummyNativeHistogram also defines buckets in the metric for testing
312+
buckets []*dto.Bucket,
313+
labelValues ...string,
314+
) (Metric, error) {
315+
if desc.err != nil {
316+
return nil, desc.err
317+
}
318+
if err := validateLabelValues(labelValues, len(desc.variableLabels.names)); err != nil {
319+
return nil, err
320+
}
321+
if schema > nativeHistogramSchemaMaximum || schema < nativeHistogramSchemaMinimum {
322+
return nil, errors.New("invalid native histogram schema")
323+
}
324+
if err := validateCount(sum, count, negativeBuckets, positiveBuckets, zeroBucket); err != nil {
325+
return nil, err
326+
}
327+
328+
NegativeSpan, NegativeDelta := makeBucketsFromMap(negativeBuckets)
329+
PositiveSpan, PositiveDelta := makeBucketsFromMap(positiveBuckets)
330+
ret := &constNativeHistogram{
331+
desc: desc,
332+
Histogram: dto.Histogram{
333+
CreatedTimestamp: timestamppb.New(createdTimestamp),
334+
Schema: &schema,
335+
ZeroThreshold: &zeroThreshold,
336+
SampleCount: &count,
337+
SampleSum: &sum,
338+
339+
NegativeSpan: NegativeSpan,
340+
NegativeDelta: NegativeDelta,
341+
342+
PositiveSpan: PositiveSpan,
343+
PositiveDelta: PositiveDelta,
344+
345+
ZeroCount: proto.Uint64(zeroBucket),
346+
347+
// DummyNativeHistogram also defines buckets in the metric
348+
Bucket: buckets,
349+
},
350+
labelPairs: MakeLabelPairs(desc, labelValues),
351+
}
352+
if *ret.ZeroThreshold == 0 && *ret.ZeroCount == 0 && len(ret.PositiveSpan) == 0 && len(ret.NegativeSpan) == 0 {
353+
ret.PositiveSpan = []*dto.BucketSpan{{
354+
Offset: proto.Int32(0),
355+
Length: proto.Uint32(0),
356+
}}
357+
}
358+
return ret, nil
170359
}

0 commit comments

Comments
 (0)