mirror of
https://github.com/prometheus/prometheus.git
synced 2024-12-25 21:54:10 -08:00
Add function for iterating through all buckets in reverse to find max bucket
Signed-off-by: Carrie Edwards <edwrdscarrie@gmail.com>
This commit is contained in:
parent
89e213bc02
commit
a462f7fa21
|
@ -622,6 +622,20 @@ func (h *FloatHistogram) AllBucketIterator() BucketIterator[float64] {
|
|||
}
|
||||
}
|
||||
|
||||
// AllReverseBucketIterator returns a BucketIterator to iterate over all negative,
|
||||
// zero, and positive buckets in descending order (starting at the lowest bucket
|
||||
// and going up). If the highest negative bucket or the lowest positive bucket
|
||||
// overlap with the zero bucket, their upper or lower boundary, respectively, is
|
||||
// set to the zero threshold.
|
||||
func (h *FloatHistogram) AllReverseBucketIterator() BucketIterator[float64] {
|
||||
return &allReverseFloatBucketIterator{
|
||||
h: h,
|
||||
negIter: h.NegativeBucketIterator(),
|
||||
posIter: h.PositiveReverseBucketIterator(),
|
||||
state: 1,
|
||||
}
|
||||
}
|
||||
|
||||
// zeroCountForLargerThreshold returns what the histogram's zero count would be
|
||||
// if the ZeroThreshold had the provided larger (or equal) value. If the
|
||||
// provided value is less than the histogram's ZeroThreshold, the method panics.
|
||||
|
@ -957,3 +971,59 @@ func (i *allFloatBucketIterator) Next() bool {
|
|||
func (i *allFloatBucketIterator) At() Bucket[float64] {
|
||||
return i.currBucket
|
||||
}
|
||||
|
||||
type allReverseFloatBucketIterator struct {
|
||||
h *FloatHistogram
|
||||
negIter, posIter BucketIterator[float64]
|
||||
// 1 means we are iterating positive buckets.
|
||||
// 0 means it is time for the zero bucket.
|
||||
// -1 means we are iterating negative buckets.
|
||||
// Anything else means iteration is over.
|
||||
state int8
|
||||
currBucket Bucket[float64]
|
||||
}
|
||||
|
||||
func (i *allReverseFloatBucketIterator) Next() bool {
|
||||
switch i.state {
|
||||
case 1:
|
||||
if i.posIter.Next() {
|
||||
i.currBucket = i.posIter.At()
|
||||
if i.currBucket.Lower < i.h.ZeroThreshold {
|
||||
i.currBucket.Lower = i.h.ZeroThreshold
|
||||
}
|
||||
return true
|
||||
}
|
||||
i.state = 0
|
||||
return i.Next()
|
||||
case 0:
|
||||
i.state = -1
|
||||
if i.h.ZeroCount > 0 {
|
||||
i.currBucket = Bucket[float64]{
|
||||
Lower: -i.h.ZeroThreshold,
|
||||
Upper: i.h.ZeroThreshold,
|
||||
LowerInclusive: true,
|
||||
UpperInclusive: true,
|
||||
Count: i.h.ZeroCount,
|
||||
// Index is irrelevant for the zero bucket.
|
||||
}
|
||||
return true
|
||||
}
|
||||
return i.Next()
|
||||
case -1:
|
||||
if i.negIter.Next() {
|
||||
i.currBucket = i.negIter.At()
|
||||
if i.currBucket.Upper > -i.h.ZeroThreshold {
|
||||
i.currBucket.Upper = -i.h.ZeroThreshold
|
||||
}
|
||||
return true
|
||||
}
|
||||
i.state = 42
|
||||
return false
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (i *allReverseFloatBucketIterator) At() Bucket[float64] {
|
||||
return i.currBucket
|
||||
}
|
||||
|
|
|
@ -1979,3 +1979,229 @@ func TestAllFloatBucketIterator(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllReverseFloatBucketIterator(t *testing.T) {
|
||||
cases := []struct {
|
||||
h FloatHistogram
|
||||
// To determine the expected buckets.
|
||||
includeNeg, includeZero, includePos bool
|
||||
}{
|
||||
{
|
||||
h: FloatHistogram{
|
||||
Count: 405,
|
||||
ZeroCount: 102,
|
||||
ZeroThreshold: 0.001,
|
||||
Sum: 1008.4,
|
||||
Schema: 1,
|
||||
PositiveSpans: []Span{
|
||||
{Offset: 0, Length: 4},
|
||||
{Offset: 1, Length: 0},
|
||||
{Offset: 3, Length: 3},
|
||||
{Offset: 3, Length: 0},
|
||||
{Offset: 2, Length: 0},
|
||||
{Offset: 5, Length: 3},
|
||||
},
|
||||
PositiveBuckets: []float64{100, 344, 123, 55, 3, 63, 2, 54, 235, 33},
|
||||
NegativeSpans: []Span{
|
||||
{Offset: 0, Length: 3},
|
||||
{Offset: 1, Length: 0},
|
||||
{Offset: 3, Length: 0},
|
||||
{Offset: 3, Length: 4},
|
||||
{Offset: 2, Length: 0},
|
||||
{Offset: 5, Length: 3},
|
||||
},
|
||||
NegativeBuckets: []float64{10, 34, 1230, 54, 67, 63, 2, 554, 235, 33},
|
||||
},
|
||||
includeNeg: true,
|
||||
includeZero: true,
|
||||
includePos: true,
|
||||
},
|
||||
{
|
||||
h: FloatHistogram{
|
||||
Count: 405,
|
||||
ZeroCount: 102,
|
||||
ZeroThreshold: 0.001,
|
||||
Sum: 1008.4,
|
||||
Schema: 1,
|
||||
NegativeSpans: []Span{
|
||||
{Offset: 0, Length: 3},
|
||||
{Offset: 1, Length: 0},
|
||||
{Offset: 3, Length: 0},
|
||||
{Offset: 3, Length: 4},
|
||||
{Offset: 2, Length: 0},
|
||||
{Offset: 5, Length: 3},
|
||||
},
|
||||
NegativeBuckets: []float64{10, 34, 1230, 54, 67, 63, 2, 554, 235, 33},
|
||||
},
|
||||
includeNeg: true,
|
||||
includeZero: true,
|
||||
includePos: false,
|
||||
},
|
||||
{
|
||||
h: FloatHistogram{
|
||||
Count: 405,
|
||||
ZeroCount: 102,
|
||||
ZeroThreshold: 0.001,
|
||||
Sum: 1008.4,
|
||||
Schema: 1,
|
||||
PositiveSpans: []Span{
|
||||
{Offset: 0, Length: 4},
|
||||
{Offset: 1, Length: 0},
|
||||
{Offset: 3, Length: 3},
|
||||
{Offset: 3, Length: 0},
|
||||
{Offset: 2, Length: 0},
|
||||
{Offset: 5, Length: 3},
|
||||
},
|
||||
PositiveBuckets: []float64{100, 344, 123, 55, 3, 63, 2, 54, 235, 33},
|
||||
},
|
||||
includeNeg: false,
|
||||
includeZero: true,
|
||||
includePos: true,
|
||||
},
|
||||
{
|
||||
h: FloatHistogram{
|
||||
Count: 405,
|
||||
ZeroCount: 102,
|
||||
ZeroThreshold: 0.001,
|
||||
Sum: 1008.4,
|
||||
Schema: 1,
|
||||
},
|
||||
includeNeg: false,
|
||||
includeZero: true,
|
||||
includePos: false,
|
||||
},
|
||||
{
|
||||
h: FloatHistogram{
|
||||
Count: 405,
|
||||
ZeroCount: 0,
|
||||
ZeroThreshold: 0.001,
|
||||
Sum: 1008.4,
|
||||
Schema: 1,
|
||||
PositiveSpans: []Span{
|
||||
{Offset: 0, Length: 4},
|
||||
{Offset: 1, Length: 0},
|
||||
{Offset: 3, Length: 3},
|
||||
{Offset: 3, Length: 0},
|
||||
{Offset: 2, Length: 0},
|
||||
{Offset: 5, Length: 3},
|
||||
},
|
||||
PositiveBuckets: []float64{100, 344, 123, 55, 3, 63, 2, 54, 235, 33},
|
||||
NegativeSpans: []Span{
|
||||
{Offset: 0, Length: 3},
|
||||
{Offset: 1, Length: 0},
|
||||
{Offset: 3, Length: 0},
|
||||
{Offset: 3, Length: 4},
|
||||
{Offset: 2, Length: 0},
|
||||
{Offset: 5, Length: 3},
|
||||
},
|
||||
NegativeBuckets: []float64{10, 34, 1230, 54, 67, 63, 2, 554, 235, 33},
|
||||
},
|
||||
includeNeg: true,
|
||||
includeZero: false,
|
||||
includePos: true,
|
||||
},
|
||||
{
|
||||
h: FloatHistogram{
|
||||
Count: 447,
|
||||
ZeroCount: 42,
|
||||
ZeroThreshold: 0.5, // Coinciding with bucket boundary.
|
||||
Sum: 1008.4,
|
||||
Schema: 0,
|
||||
PositiveSpans: []Span{
|
||||
{Offset: 0, Length: 4},
|
||||
{Offset: 1, Length: 0},
|
||||
{Offset: 3, Length: 3},
|
||||
{Offset: 3, Length: 0},
|
||||
{Offset: 2, Length: 0},
|
||||
{Offset: 5, Length: 3},
|
||||
},
|
||||
PositiveBuckets: []float64{100, 344, 123, 55, 3, 63, 2, 54, 235, 33},
|
||||
NegativeSpans: []Span{
|
||||
{Offset: 0, Length: 3},
|
||||
{Offset: 1, Length: 0},
|
||||
{Offset: 3, Length: 0},
|
||||
{Offset: 3, Length: 4},
|
||||
{Offset: 2, Length: 0},
|
||||
{Offset: 5, Length: 3},
|
||||
},
|
||||
NegativeBuckets: []float64{10, 34, 1230, 54, 67, 63, 2, 554, 235, 33},
|
||||
},
|
||||
includeNeg: true,
|
||||
includeZero: true,
|
||||
includePos: true,
|
||||
},
|
||||
{
|
||||
h: FloatHistogram{
|
||||
Count: 447,
|
||||
ZeroCount: 42,
|
||||
ZeroThreshold: 0.6, // Within the bucket closest to zero.
|
||||
Sum: 1008.4,
|
||||
Schema: 0,
|
||||
PositiveSpans: []Span{
|
||||
{Offset: 0, Length: 4},
|
||||
{Offset: 1, Length: 0},
|
||||
{Offset: 3, Length: 3},
|
||||
{Offset: 3, Length: 0},
|
||||
{Offset: 2, Length: 0},
|
||||
{Offset: 5, Length: 3},
|
||||
},
|
||||
PositiveBuckets: []float64{100, 344, 123, 55, 3, 63, 2, 54, 235, 33},
|
||||
NegativeSpans: []Span{
|
||||
{Offset: 0, Length: 3},
|
||||
{Offset: 1, Length: 0},
|
||||
{Offset: 3, Length: 0},
|
||||
{Offset: 3, Length: 4},
|
||||
{Offset: 2, Length: 0},
|
||||
{Offset: 5, Length: 3},
|
||||
},
|
||||
NegativeBuckets: []float64{10, 34, 1230, 54, 67, 63, 2, 554, 235, 33},
|
||||
},
|
||||
includeNeg: true,
|
||||
includeZero: true,
|
||||
includePos: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||
var expBuckets, actBuckets []Bucket[float64]
|
||||
|
||||
if c.includePos {
|
||||
it := c.h.PositiveReverseBucketIterator()
|
||||
for it.Next() {
|
||||
b := it.At()
|
||||
if c.includeZero && b.Lower < c.h.ZeroThreshold {
|
||||
b.Lower = c.h.ZeroThreshold
|
||||
}
|
||||
expBuckets = append(expBuckets, b)
|
||||
}
|
||||
}
|
||||
if c.includeZero {
|
||||
expBuckets = append(expBuckets, Bucket[float64]{
|
||||
Lower: -c.h.ZeroThreshold,
|
||||
Upper: c.h.ZeroThreshold,
|
||||
LowerInclusive: true,
|
||||
UpperInclusive: true,
|
||||
Count: c.h.ZeroCount,
|
||||
})
|
||||
}
|
||||
if c.includeNeg {
|
||||
it := c.h.NegativeBucketIterator()
|
||||
for it.Next() {
|
||||
b := it.At()
|
||||
if c.includeZero && b.Upper > -c.h.ZeroThreshold {
|
||||
b.Upper = -c.h.ZeroThreshold
|
||||
}
|
||||
expBuckets = append(expBuckets, b)
|
||||
}
|
||||
}
|
||||
|
||||
it := c.h.AllReverseBucketIterator()
|
||||
for it.Next() {
|
||||
actBuckets = append(actBuckets, it.At())
|
||||
}
|
||||
|
||||
require.Equal(t, expBuckets, actBuckets)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue