mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
commit
3f3172cde1
|
@ -1,5 +1,9 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2.47.2 / 2023-10-11
|
||||||
|
|
||||||
|
* [BUGFIX] TSDB: Fix counter reset edgecases causing native histogram panics. #12838
|
||||||
|
|
||||||
## 2.47.1 / 2023-10-04
|
## 2.47.1 / 2023-10-04
|
||||||
|
|
||||||
* [BUGFIX] Fix duplicate sample detection at chunk size limit #12874
|
* [BUGFIX] Fix duplicate sample detection at chunk size limit #12874
|
||||||
|
|
|
@ -334,11 +334,16 @@ func counterResetInAnyFloatBucket(oldBuckets []xorValue, newBuckets []float64, o
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
oldSpanSliceIdx, newSpanSliceIdx := 0, 0 // Index for the span slices.
|
var (
|
||||||
oldInsideSpanIdx, newInsideSpanIdx := uint32(0), uint32(0) // Index inside a span.
|
oldSpanSliceIdx, newSpanSliceIdx int = -1, -1 // Index for the span slices. Starts at -1 to indicate that the first non empty span is not yet found.
|
||||||
oldIdx, newIdx := oldSpans[0].Offset, newSpans[0].Offset
|
oldInsideSpanIdx, newInsideSpanIdx uint32 // Index inside a span.
|
||||||
|
oldIdx, newIdx int32 // Index inside a bucket slice.
|
||||||
|
oldBucketSliceIdx, newBucketSliceIdx int // Index inside bucket slice.
|
||||||
|
)
|
||||||
|
|
||||||
oldBucketSliceIdx, newBucketSliceIdx := 0, 0 // Index inside bucket slice.
|
// Find first non empty spans.
|
||||||
|
oldSpanSliceIdx, oldIdx = nextNonEmptySpanSliceIdx(oldSpanSliceIdx, oldIdx, oldSpans)
|
||||||
|
newSpanSliceIdx, newIdx = nextNonEmptySpanSliceIdx(newSpanSliceIdx, newIdx, newSpans)
|
||||||
oldVal, newVal := oldBuckets[0].value, newBuckets[0]
|
oldVal, newVal := oldBuckets[0].value, newBuckets[0]
|
||||||
|
|
||||||
// Since we assume that new spans won't have missing buckets, there will never be a case
|
// Since we assume that new spans won't have missing buckets, there will never be a case
|
||||||
|
@ -354,13 +359,12 @@ func counterResetInAnyFloatBucket(oldBuckets []xorValue, newBuckets []float64, o
|
||||||
// Moving ahead old bucket and span by 1 index.
|
// Moving ahead old bucket and span by 1 index.
|
||||||
if oldInsideSpanIdx+1 >= oldSpans[oldSpanSliceIdx].Length {
|
if oldInsideSpanIdx+1 >= oldSpans[oldSpanSliceIdx].Length {
|
||||||
// Current span is over.
|
// Current span is over.
|
||||||
oldSpanSliceIdx = nextNonEmptySpanSliceIdx(oldSpanSliceIdx, oldSpans)
|
oldSpanSliceIdx, oldIdx = nextNonEmptySpanSliceIdx(oldSpanSliceIdx, oldIdx, oldSpans)
|
||||||
oldInsideSpanIdx = 0
|
oldInsideSpanIdx = 0
|
||||||
if oldSpanSliceIdx >= len(oldSpans) {
|
if oldSpanSliceIdx >= len(oldSpans) {
|
||||||
// All old spans are over.
|
// All old spans are over.
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
oldIdx += 1 + oldSpans[oldSpanSliceIdx].Offset
|
|
||||||
} else {
|
} else {
|
||||||
oldInsideSpanIdx++
|
oldInsideSpanIdx++
|
||||||
oldIdx++
|
oldIdx++
|
||||||
|
@ -373,14 +377,13 @@ func counterResetInAnyFloatBucket(oldBuckets []xorValue, newBuckets []float64, o
|
||||||
// Moving ahead new bucket and span by 1 index.
|
// Moving ahead new bucket and span by 1 index.
|
||||||
if newInsideSpanIdx+1 >= newSpans[newSpanSliceIdx].Length {
|
if newInsideSpanIdx+1 >= newSpans[newSpanSliceIdx].Length {
|
||||||
// Current span is over.
|
// Current span is over.
|
||||||
newSpanSliceIdx = nextNonEmptySpanSliceIdx(newSpanSliceIdx, newSpans)
|
newSpanSliceIdx, newIdx = nextNonEmptySpanSliceIdx(newSpanSliceIdx, newIdx, newSpans)
|
||||||
newInsideSpanIdx = 0
|
newInsideSpanIdx = 0
|
||||||
if newSpanSliceIdx >= len(newSpans) {
|
if newSpanSliceIdx >= len(newSpans) {
|
||||||
// All new spans are over.
|
// All new spans are over.
|
||||||
// This should not happen, old spans above should catch this first.
|
// This should not happen, old spans above should catch this first.
|
||||||
panic("new spans over before old spans in counterReset")
|
panic("new spans over before old spans in counterReset")
|
||||||
}
|
}
|
||||||
newIdx += 1 + newSpans[newSpanSliceIdx].Offset
|
|
||||||
} else {
|
} else {
|
||||||
newInsideSpanIdx++
|
newInsideSpanIdx++
|
||||||
newIdx++
|
newIdx++
|
||||||
|
|
|
@ -443,7 +443,12 @@ func assertRecodedFloatHistogramChunkOnAppend(t *testing.T, prevChunk Chunk, hAp
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFloatHistogramChunkAppendableWithEmptySpan(t *testing.T) {
|
func TestFloatHistogramChunkAppendableWithEmptySpan(t *testing.T) {
|
||||||
h1 := &histogram.FloatHistogram{
|
tests := map[string]struct {
|
||||||
|
h1 *histogram.FloatHistogram
|
||||||
|
h2 *histogram.FloatHistogram
|
||||||
|
}{
|
||||||
|
"empty span in old and new histogram": {
|
||||||
|
h1: &histogram.FloatHistogram{
|
||||||
Schema: 0,
|
Schema: 0,
|
||||||
Count: 21,
|
Count: 21,
|
||||||
Sum: 1234.5,
|
Sum: 1234.5,
|
||||||
|
@ -461,8 +466,8 @@ func TestFloatHistogramChunkAppendableWithEmptySpan(t *testing.T) {
|
||||||
{Offset: 2, Length: 3},
|
{Offset: 2, Length: 3},
|
||||||
},
|
},
|
||||||
NegativeBuckets: []float64{1, 2, 1, 2, 2, 2, 2},
|
NegativeBuckets: []float64{1, 2, 1, 2, 2, 2, 2},
|
||||||
}
|
},
|
||||||
h2 := &histogram.FloatHistogram{
|
h2: &histogram.FloatHistogram{
|
||||||
Schema: 0,
|
Schema: 0,
|
||||||
Count: 37,
|
Count: 37,
|
||||||
Sum: 2345.6,
|
Sum: 2345.6,
|
||||||
|
@ -480,8 +485,132 @@ func TestFloatHistogramChunkAppendableWithEmptySpan(t *testing.T) {
|
||||||
{Offset: 2, Length: 3},
|
{Offset: 2, Length: 3},
|
||||||
},
|
},
|
||||||
NegativeBuckets: []float64{1, 4, 2, 7, 5, 5, 2},
|
NegativeBuckets: []float64{1, 4, 2, 7, 5, 5, 2},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"empty span in old histogram": {
|
||||||
|
h1: &histogram.FloatHistogram{
|
||||||
|
Schema: 0,
|
||||||
|
Count: 21,
|
||||||
|
Sum: 1234.5,
|
||||||
|
ZeroThreshold: 0.001,
|
||||||
|
ZeroCount: 4,
|
||||||
|
PositiveSpans: []histogram.Span{
|
||||||
|
{Offset: 1, Length: 0}, // This span will disappear.
|
||||||
|
{Offset: 2, Length: 4},
|
||||||
|
{Offset: 0, Length: 3},
|
||||||
|
},
|
||||||
|
PositiveBuckets: []float64{1, 2, 1, 1, 1, 1, 1},
|
||||||
|
NegativeSpans: []histogram.Span{
|
||||||
|
{Offset: 1, Length: 4},
|
||||||
|
{Offset: 2, Length: 0},
|
||||||
|
{Offset: 2, Length: 3},
|
||||||
|
},
|
||||||
|
NegativeBuckets: []float64{1, 2, 1, 2, 2, 2, 2},
|
||||||
|
},
|
||||||
|
h2: &histogram.FloatHistogram{
|
||||||
|
Schema: 0,
|
||||||
|
Count: 37,
|
||||||
|
Sum: 2345.6,
|
||||||
|
ZeroThreshold: 0.001,
|
||||||
|
ZeroCount: 5,
|
||||||
|
PositiveSpans: []histogram.Span{
|
||||||
|
{Offset: 3, Length: 4},
|
||||||
|
{Offset: 0, Length: 3},
|
||||||
|
},
|
||||||
|
PositiveBuckets: []float64{1, 3, 1, 2, 1, 1, 1},
|
||||||
|
NegativeSpans: []histogram.Span{
|
||||||
|
{Offset: 1, Length: 4},
|
||||||
|
{Offset: 2, Length: 0},
|
||||||
|
{Offset: 2, Length: 3},
|
||||||
|
},
|
||||||
|
NegativeBuckets: []float64{1, 4, 2, 7, 5, 5, 2},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"empty span in new histogram": {
|
||||||
|
h1: &histogram.FloatHistogram{
|
||||||
|
Schema: 0,
|
||||||
|
Count: 21,
|
||||||
|
Sum: 1234.5,
|
||||||
|
ZeroThreshold: 0.001,
|
||||||
|
ZeroCount: 4,
|
||||||
|
PositiveSpans: []histogram.Span{
|
||||||
|
{Offset: 0, Length: 4},
|
||||||
|
{Offset: 3, Length: 3},
|
||||||
|
},
|
||||||
|
PositiveBuckets: []float64{1, 2, 1, 1, 1, 1, 1},
|
||||||
|
NegativeSpans: []histogram.Span{
|
||||||
|
{Offset: 1, Length: 4},
|
||||||
|
{Offset: 2, Length: 0},
|
||||||
|
{Offset: 2, Length: 3},
|
||||||
|
},
|
||||||
|
NegativeBuckets: []float64{1, 2, 1, 2, 2, 2, 2},
|
||||||
|
},
|
||||||
|
h2: &histogram.FloatHistogram{
|
||||||
|
Schema: 0,
|
||||||
|
Count: 37,
|
||||||
|
Sum: 2345.6,
|
||||||
|
ZeroThreshold: 0.001,
|
||||||
|
ZeroCount: 5,
|
||||||
|
PositiveSpans: []histogram.Span{
|
||||||
|
{Offset: 0, Length: 4},
|
||||||
|
{Offset: 1, Length: 0}, // This span is new.
|
||||||
|
{Offset: 2, Length: 3},
|
||||||
|
},
|
||||||
|
PositiveBuckets: []float64{1, 3, 1, 2, 1, 1, 1},
|
||||||
|
NegativeSpans: []histogram.Span{
|
||||||
|
{Offset: 1, Length: 4},
|
||||||
|
{Offset: 2, Length: 0},
|
||||||
|
{Offset: 2, Length: 3},
|
||||||
|
},
|
||||||
|
NegativeBuckets: []float64{1, 4, 2, 7, 5, 5, 2},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"two empty spans mixing offsets": {
|
||||||
|
h1: &histogram.FloatHistogram{
|
||||||
|
Schema: 0,
|
||||||
|
Count: 21,
|
||||||
|
Sum: 1234.5,
|
||||||
|
ZeroThreshold: 0.001,
|
||||||
|
ZeroCount: 4,
|
||||||
|
PositiveSpans: []histogram.Span{
|
||||||
|
{Offset: 0, Length: 4},
|
||||||
|
{Offset: 1, Length: 0},
|
||||||
|
{Offset: 3, Length: 0},
|
||||||
|
{Offset: 4, Length: 3},
|
||||||
|
},
|
||||||
|
PositiveBuckets: []float64{1, 2, 1, 1, 1, 1, 1},
|
||||||
|
NegativeSpans: []histogram.Span{
|
||||||
|
{Offset: 1, Length: 4},
|
||||||
|
{Offset: 2, Length: 0},
|
||||||
|
{Offset: 2, Length: 3},
|
||||||
|
},
|
||||||
|
NegativeBuckets: []float64{1, 2, 1, 2, 2, 2, 2},
|
||||||
|
},
|
||||||
|
h2: &histogram.FloatHistogram{
|
||||||
|
Schema: 0,
|
||||||
|
Count: 37,
|
||||||
|
Sum: 2345.6,
|
||||||
|
ZeroThreshold: 0.001,
|
||||||
|
ZeroCount: 5,
|
||||||
|
PositiveSpans: []histogram.Span{
|
||||||
|
{Offset: 0, Length: 4},
|
||||||
|
{Offset: 3, Length: 0},
|
||||||
|
{Offset: 1, Length: 0},
|
||||||
|
{Offset: 4, Length: 3},
|
||||||
|
},
|
||||||
|
PositiveBuckets: []float64{1, 3, 1, 2, 1, 1, 1},
|
||||||
|
NegativeSpans: []histogram.Span{
|
||||||
|
{Offset: 1, Length: 4},
|
||||||
|
{Offset: 2, Length: 0},
|
||||||
|
{Offset: 2, Length: 3},
|
||||||
|
},
|
||||||
|
NegativeBuckets: []float64{1, 4, 2, 7, 5, 5, 2},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for name, tc := range tests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
c := Chunk(NewFloatHistogramChunk())
|
c := Chunk(NewFloatHistogramChunk())
|
||||||
|
|
||||||
// Create fresh appender and add the first histogram.
|
// Create fresh appender and add the first histogram.
|
||||||
|
@ -489,16 +618,18 @@ func TestFloatHistogramChunkAppendableWithEmptySpan(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 0, c.NumSamples())
|
require.Equal(t, 0, c.NumSamples())
|
||||||
|
|
||||||
_, _, _, err = app.AppendFloatHistogram(nil, 1, h1, true)
|
_, _, _, err = app.AppendFloatHistogram(nil, 1, tc.h1, true)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 1, c.NumSamples())
|
require.Equal(t, 1, c.NumSamples())
|
||||||
hApp, _ := app.(*FloatHistogramAppender)
|
hApp, _ := app.(*FloatHistogramAppender)
|
||||||
|
|
||||||
pI, nI, okToAppend, counterReset := hApp.appendable(h2)
|
pI, nI, okToAppend, counterReset := hApp.appendable(tc.h2)
|
||||||
require.Empty(t, pI)
|
require.Empty(t, pI)
|
||||||
require.Empty(t, nI)
|
require.Empty(t, nI)
|
||||||
require.True(t, okToAppend)
|
require.True(t, okToAppend)
|
||||||
require.False(t, counterReset)
|
require.False(t, counterReset)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFloatHistogramChunkAppendableGauge(t *testing.T) {
|
func TestFloatHistogramChunkAppendableGauge(t *testing.T) {
|
||||||
|
|
|
@ -354,11 +354,16 @@ func counterResetInAnyBucket(oldBuckets, newBuckets []int64, oldSpans, newSpans
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
oldSpanSliceIdx, newSpanSliceIdx := 0, 0 // Index for the span slices.
|
var (
|
||||||
oldInsideSpanIdx, newInsideSpanIdx := uint32(0), uint32(0) // Index inside a span.
|
oldSpanSliceIdx, newSpanSliceIdx int = -1, -1 // Index for the span slices. Starts at -1 to indicate that the first non empty span is not yet found.
|
||||||
oldIdx, newIdx := oldSpans[0].Offset, newSpans[0].Offset
|
oldInsideSpanIdx, newInsideSpanIdx uint32 // Index inside a span.
|
||||||
|
oldIdx, newIdx int32 // Index inside a bucket slice.
|
||||||
|
oldBucketSliceIdx, newBucketSliceIdx int // Index inside bucket slice.
|
||||||
|
)
|
||||||
|
|
||||||
oldBucketSliceIdx, newBucketSliceIdx := 0, 0 // Index inside bucket slice.
|
// Find first non empty spans.
|
||||||
|
oldSpanSliceIdx, oldIdx = nextNonEmptySpanSliceIdx(oldSpanSliceIdx, oldIdx, oldSpans)
|
||||||
|
newSpanSliceIdx, newIdx = nextNonEmptySpanSliceIdx(newSpanSliceIdx, newIdx, newSpans)
|
||||||
oldVal, newVal := oldBuckets[0], newBuckets[0]
|
oldVal, newVal := oldBuckets[0], newBuckets[0]
|
||||||
|
|
||||||
// Since we assume that new spans won't have missing buckets, there will never be a case
|
// Since we assume that new spans won't have missing buckets, there will never be a case
|
||||||
|
@ -374,13 +379,12 @@ func counterResetInAnyBucket(oldBuckets, newBuckets []int64, oldSpans, newSpans
|
||||||
// Moving ahead old bucket and span by 1 index.
|
// Moving ahead old bucket and span by 1 index.
|
||||||
if oldInsideSpanIdx+1 >= oldSpans[oldSpanSliceIdx].Length {
|
if oldInsideSpanIdx+1 >= oldSpans[oldSpanSliceIdx].Length {
|
||||||
// Current span is over.
|
// Current span is over.
|
||||||
oldSpanSliceIdx = nextNonEmptySpanSliceIdx(oldSpanSliceIdx, oldSpans)
|
oldSpanSliceIdx, oldIdx = nextNonEmptySpanSliceIdx(oldSpanSliceIdx, oldIdx, oldSpans)
|
||||||
oldInsideSpanIdx = 0
|
oldInsideSpanIdx = 0
|
||||||
if oldSpanSliceIdx >= len(oldSpans) {
|
if oldSpanSliceIdx >= len(oldSpans) {
|
||||||
// All old spans are over.
|
// All old spans are over.
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
oldIdx += 1 + oldSpans[oldSpanSliceIdx].Offset
|
|
||||||
} else {
|
} else {
|
||||||
oldInsideSpanIdx++
|
oldInsideSpanIdx++
|
||||||
oldIdx++
|
oldIdx++
|
||||||
|
@ -393,14 +397,13 @@ func counterResetInAnyBucket(oldBuckets, newBuckets []int64, oldSpans, newSpans
|
||||||
// Moving ahead new bucket and span by 1 index.
|
// Moving ahead new bucket and span by 1 index.
|
||||||
if newInsideSpanIdx+1 >= newSpans[newSpanSliceIdx].Length {
|
if newInsideSpanIdx+1 >= newSpans[newSpanSliceIdx].Length {
|
||||||
// Current span is over.
|
// Current span is over.
|
||||||
newSpanSliceIdx = nextNonEmptySpanSliceIdx(newSpanSliceIdx, newSpans)
|
newSpanSliceIdx, newIdx = nextNonEmptySpanSliceIdx(newSpanSliceIdx, newIdx, newSpans)
|
||||||
newInsideSpanIdx = 0
|
newInsideSpanIdx = 0
|
||||||
if newSpanSliceIdx >= len(newSpans) {
|
if newSpanSliceIdx >= len(newSpans) {
|
||||||
// All new spans are over.
|
// All new spans are over.
|
||||||
// This should not happen, old spans above should catch this first.
|
// This should not happen, old spans above should catch this first.
|
||||||
panic("new spans over before old spans in counterReset")
|
panic("new spans over before old spans in counterReset")
|
||||||
}
|
}
|
||||||
newIdx += 1 + newSpans[newSpanSliceIdx].Offset
|
|
||||||
} else {
|
} else {
|
||||||
newInsideSpanIdx++
|
newInsideSpanIdx++
|
||||||
newIdx++
|
newIdx++
|
||||||
|
|
|
@ -489,8 +489,13 @@ func counterResetHint(crh CounterResetHeader, numRead uint16) histogram.CounterR
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle pathological case of empty span when advancing span idx.
|
// Handle pathological case of empty span when advancing span idx.
|
||||||
func nextNonEmptySpanSliceIdx(idx int, spans []histogram.Span) (newIdx int) {
|
// Call it with idx==-1 to find the first non empty span.
|
||||||
for idx++; idx < len(spans) && spans[idx].Length == 0; idx++ {
|
func nextNonEmptySpanSliceIdx(idx int, bucketIdx int32, spans []histogram.Span) (newIdx int, newBucketIdx int32) {
|
||||||
|
for idx++; idx < len(spans); idx++ {
|
||||||
|
if spans[idx].Length > 0 {
|
||||||
|
return idx, bucketIdx + spans[idx].Offset + 1
|
||||||
}
|
}
|
||||||
return idx
|
bucketIdx += spans[idx].Offset
|
||||||
|
}
|
||||||
|
return idx, 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -463,7 +463,12 @@ func assertSampleCount(t *testing.T, c Chunk, exp int64, vtype ValueType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHistogramChunkAppendableWithEmptySpan(t *testing.T) {
|
func TestHistogramChunkAppendableWithEmptySpan(t *testing.T) {
|
||||||
h1 := &histogram.Histogram{
|
tests := map[string]struct {
|
||||||
|
h1 *histogram.Histogram
|
||||||
|
h2 *histogram.Histogram
|
||||||
|
}{
|
||||||
|
"empty span in old and new histogram": {
|
||||||
|
h1: &histogram.Histogram{
|
||||||
Schema: 0,
|
Schema: 0,
|
||||||
Count: 21,
|
Count: 21,
|
||||||
Sum: 1234.5,
|
Sum: 1234.5,
|
||||||
|
@ -481,8 +486,8 @@ func TestHistogramChunkAppendableWithEmptySpan(t *testing.T) {
|
||||||
{Offset: 2, Length: 3},
|
{Offset: 2, Length: 3},
|
||||||
},
|
},
|
||||||
NegativeBuckets: []int64{1, 1, -1, 1, 0, 0, 0},
|
NegativeBuckets: []int64{1, 1, -1, 1, 0, 0, 0},
|
||||||
}
|
},
|
||||||
h2 := &histogram.Histogram{
|
h2: &histogram.Histogram{
|
||||||
Schema: 0,
|
Schema: 0,
|
||||||
Count: 37,
|
Count: 37,
|
||||||
Sum: 2345.6,
|
Sum: 2345.6,
|
||||||
|
@ -500,8 +505,132 @@ func TestHistogramChunkAppendableWithEmptySpan(t *testing.T) {
|
||||||
{Offset: 2, Length: 3},
|
{Offset: 2, Length: 3},
|
||||||
},
|
},
|
||||||
NegativeBuckets: []int64{1, 3, -2, 5, -2, 0, -3},
|
NegativeBuckets: []int64{1, 3, -2, 5, -2, 0, -3},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"empty span in old histogram": {
|
||||||
|
h1: &histogram.Histogram{
|
||||||
|
Schema: 0,
|
||||||
|
Count: 21,
|
||||||
|
Sum: 1234.5,
|
||||||
|
ZeroThreshold: 0.001,
|
||||||
|
ZeroCount: 4,
|
||||||
|
PositiveSpans: []histogram.Span{
|
||||||
|
{Offset: 1, Length: 0}, // This span will disappear.
|
||||||
|
{Offset: 2, Length: 4},
|
||||||
|
{Offset: 0, Length: 3},
|
||||||
|
},
|
||||||
|
PositiveBuckets: []int64{1, 1, -1, 0, 0, 0, 0},
|
||||||
|
NegativeSpans: []histogram.Span{
|
||||||
|
{Offset: 1, Length: 4},
|
||||||
|
{Offset: 2, Length: 0},
|
||||||
|
{Offset: 2, Length: 3},
|
||||||
|
},
|
||||||
|
NegativeBuckets: []int64{1, 1, -1, 1, 0, 0, 0},
|
||||||
|
},
|
||||||
|
h2: &histogram.Histogram{
|
||||||
|
Schema: 0,
|
||||||
|
Count: 37,
|
||||||
|
Sum: 2345.6,
|
||||||
|
ZeroThreshold: 0.001,
|
||||||
|
ZeroCount: 5,
|
||||||
|
PositiveSpans: []histogram.Span{
|
||||||
|
{Offset: 3, Length: 4},
|
||||||
|
{Offset: 0, Length: 3},
|
||||||
|
},
|
||||||
|
PositiveBuckets: []int64{1, 2, -2, 1, -1, 0, 0},
|
||||||
|
NegativeSpans: []histogram.Span{
|
||||||
|
{Offset: 1, Length: 4},
|
||||||
|
{Offset: 2, Length: 0},
|
||||||
|
{Offset: 2, Length: 3},
|
||||||
|
},
|
||||||
|
NegativeBuckets: []int64{1, 3, -2, 5, -2, 0, -3},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"empty span in new histogram": {
|
||||||
|
h1: &histogram.Histogram{
|
||||||
|
Schema: 0,
|
||||||
|
Count: 21,
|
||||||
|
Sum: 1234.5,
|
||||||
|
ZeroThreshold: 0.001,
|
||||||
|
ZeroCount: 4,
|
||||||
|
PositiveSpans: []histogram.Span{
|
||||||
|
{Offset: 0, Length: 4},
|
||||||
|
{Offset: 3, Length: 3},
|
||||||
|
},
|
||||||
|
PositiveBuckets: []int64{1, 1, -1, 0, 0, 0, 0},
|
||||||
|
NegativeSpans: []histogram.Span{
|
||||||
|
{Offset: 1, Length: 4},
|
||||||
|
{Offset: 2, Length: 0},
|
||||||
|
{Offset: 2, Length: 3},
|
||||||
|
},
|
||||||
|
NegativeBuckets: []int64{1, 1, -1, 1, 0, 0, 0},
|
||||||
|
},
|
||||||
|
h2: &histogram.Histogram{
|
||||||
|
Schema: 0,
|
||||||
|
Count: 37,
|
||||||
|
Sum: 2345.6,
|
||||||
|
ZeroThreshold: 0.001,
|
||||||
|
ZeroCount: 5,
|
||||||
|
PositiveSpans: []histogram.Span{
|
||||||
|
{Offset: 0, Length: 4},
|
||||||
|
{Offset: 1, Length: 0}, // This span is new.
|
||||||
|
{Offset: 2, Length: 3},
|
||||||
|
},
|
||||||
|
PositiveBuckets: []int64{1, 2, -2, 1, -1, 0, 0},
|
||||||
|
NegativeSpans: []histogram.Span{
|
||||||
|
{Offset: 1, Length: 4},
|
||||||
|
{Offset: 2, Length: 0},
|
||||||
|
{Offset: 2, Length: 3},
|
||||||
|
},
|
||||||
|
NegativeBuckets: []int64{1, 3, -2, 5, -2, 0, -3},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"two empty spans mixing offsets": {
|
||||||
|
h1: &histogram.Histogram{
|
||||||
|
Schema: 0,
|
||||||
|
Count: 21,
|
||||||
|
Sum: 1234.5,
|
||||||
|
ZeroThreshold: 0.001,
|
||||||
|
ZeroCount: 4,
|
||||||
|
PositiveSpans: []histogram.Span{
|
||||||
|
{Offset: 0, Length: 4},
|
||||||
|
{Offset: 1, Length: 0},
|
||||||
|
{Offset: 3, Length: 0},
|
||||||
|
{Offset: 4, Length: 3},
|
||||||
|
},
|
||||||
|
PositiveBuckets: []int64{1, 1, -1, 0, 0, 0, 0},
|
||||||
|
NegativeSpans: []histogram.Span{
|
||||||
|
{Offset: 1, Length: 4},
|
||||||
|
{Offset: 2, Length: 0},
|
||||||
|
{Offset: 2, Length: 3},
|
||||||
|
},
|
||||||
|
NegativeBuckets: []int64{1, 1, -1, 1, 0, 0, 0},
|
||||||
|
},
|
||||||
|
h2: &histogram.Histogram{
|
||||||
|
Schema: 0,
|
||||||
|
Count: 37,
|
||||||
|
Sum: 2345.6,
|
||||||
|
ZeroThreshold: 0.001,
|
||||||
|
ZeroCount: 5,
|
||||||
|
PositiveSpans: []histogram.Span{
|
||||||
|
{Offset: 0, Length: 4},
|
||||||
|
{Offset: 3, Length: 0},
|
||||||
|
{Offset: 1, Length: 0},
|
||||||
|
{Offset: 4, Length: 3},
|
||||||
|
},
|
||||||
|
PositiveBuckets: []int64{1, 2, -2, 1, -1, 0, 0},
|
||||||
|
NegativeSpans: []histogram.Span{
|
||||||
|
{Offset: 1, Length: 4},
|
||||||
|
{Offset: 2, Length: 0},
|
||||||
|
{Offset: 2, Length: 3},
|
||||||
|
},
|
||||||
|
NegativeBuckets: []int64{1, 3, -2, 5, -2, 0, -3},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for name, tc := range tests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
c := Chunk(NewHistogramChunk())
|
c := Chunk(NewHistogramChunk())
|
||||||
|
|
||||||
// Create fresh appender and add the first histogram.
|
// Create fresh appender and add the first histogram.
|
||||||
|
@ -509,16 +638,18 @@ func TestHistogramChunkAppendableWithEmptySpan(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 0, c.NumSamples())
|
require.Equal(t, 0, c.NumSamples())
|
||||||
|
|
||||||
_, _, _, err = app.AppendHistogram(nil, 1, h1, true)
|
_, _, _, err = app.AppendHistogram(nil, 1, tc.h1, true)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 1, c.NumSamples())
|
require.Equal(t, 1, c.NumSamples())
|
||||||
hApp, _ := app.(*HistogramAppender)
|
hApp, _ := app.(*HistogramAppender)
|
||||||
|
|
||||||
pI, nI, okToAppend, counterReset := hApp.appendable(h2)
|
pI, nI, okToAppend, counterReset := hApp.appendable(tc.h2)
|
||||||
require.Empty(t, pI)
|
require.Empty(t, pI)
|
||||||
require.Empty(t, nI)
|
require.Empty(t, nI)
|
||||||
require.True(t, okToAppend)
|
require.True(t, okToAppend)
|
||||||
require.False(t, counterReset)
|
require.False(t, counterReset)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAtFloatHistogram(t *testing.T) {
|
func TestAtFloatHistogram(t *testing.T) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@prometheus-io/codemirror-promql",
|
"name": "@prometheus-io/codemirror-promql",
|
||||||
"version": "0.47.0",
|
"version": "0.47.2",
|
||||||
"description": "a CodeMirror mode for the PromQL language",
|
"description": "a CodeMirror mode for the PromQL language",
|
||||||
"types": "dist/esm/index.d.ts",
|
"types": "dist/esm/index.d.ts",
|
||||||
"module": "dist/esm/index.js",
|
"module": "dist/esm/index.js",
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/prometheus/prometheus/blob/main/web/ui/module/codemirror-promql/README.md",
|
"homepage": "https://github.com/prometheus/prometheus/blob/main/web/ui/module/codemirror-promql/README.md",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prometheus-io/lezer-promql": "0.47.0",
|
"@prometheus-io/lezer-promql": "0.47.2",
|
||||||
"lru-cache": "^6.0.0"
|
"lru-cache": "^6.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@prometheus-io/lezer-promql",
|
"name": "@prometheus-io/lezer-promql",
|
||||||
"version": "0.47.0",
|
"version": "0.47.2",
|
||||||
"description": "lezer-based PromQL grammar",
|
"description": "lezer-based PromQL grammar",
|
||||||
"main": "dist/index.cjs",
|
"main": "dist/index.cjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
14
web/ui/package-lock.json
generated
14
web/ui/package-lock.json
generated
|
@ -28,10 +28,10 @@
|
||||||
},
|
},
|
||||||
"module/codemirror-promql": {
|
"module/codemirror-promql": {
|
||||||
"name": "@prometheus-io/codemirror-promql",
|
"name": "@prometheus-io/codemirror-promql",
|
||||||
"version": "0.47.0",
|
"version": "0.47.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prometheus-io/lezer-promql": "0.47.0",
|
"@prometheus-io/lezer-promql": "0.47.2",
|
||||||
"lru-cache": "^6.0.0"
|
"lru-cache": "^6.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -61,7 +61,7 @@
|
||||||
},
|
},
|
||||||
"module/lezer-promql": {
|
"module/lezer-promql": {
|
||||||
"name": "@prometheus-io/lezer-promql",
|
"name": "@prometheus-io/lezer-promql",
|
||||||
"version": "0.47.0",
|
"version": "0.47.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lezer/generator": "^1.2.3",
|
"@lezer/generator": "^1.2.3",
|
||||||
|
@ -20765,7 +20765,7 @@
|
||||||
},
|
},
|
||||||
"react-app": {
|
"react-app": {
|
||||||
"name": "@prometheus-io/app",
|
"name": "@prometheus-io/app",
|
||||||
"version": "0.47.0",
|
"version": "0.47.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.7.1",
|
"@codemirror/autocomplete": "^6.7.1",
|
||||||
"@codemirror/commands": "^6.2.4",
|
"@codemirror/commands": "^6.2.4",
|
||||||
|
@ -20783,7 +20783,7 @@
|
||||||
"@lezer/lr": "^1.3.6",
|
"@lezer/lr": "^1.3.6",
|
||||||
"@nexucis/fuzzy": "^0.4.1",
|
"@nexucis/fuzzy": "^0.4.1",
|
||||||
"@nexucis/kvsearch": "^0.8.1",
|
"@nexucis/kvsearch": "^0.8.1",
|
||||||
"@prometheus-io/codemirror-promql": "0.47.0",
|
"@prometheus-io/codemirror-promql": "0.47.2",
|
||||||
"bootstrap": "^4.6.2",
|
"bootstrap": "^4.6.2",
|
||||||
"css.escape": "^1.5.1",
|
"css.escape": "^1.5.1",
|
||||||
"downshift": "^7.6.0",
|
"downshift": "^7.6.0",
|
||||||
|
@ -23423,7 +23423,7 @@
|
||||||
"@lezer/lr": "^1.3.6",
|
"@lezer/lr": "^1.3.6",
|
||||||
"@nexucis/fuzzy": "^0.4.1",
|
"@nexucis/fuzzy": "^0.4.1",
|
||||||
"@nexucis/kvsearch": "^0.8.1",
|
"@nexucis/kvsearch": "^0.8.1",
|
||||||
"@prometheus-io/codemirror-promql": "0.47.0",
|
"@prometheus-io/codemirror-promql": "0.47.2",
|
||||||
"@testing-library/react-hooks": "^7.0.2",
|
"@testing-library/react-hooks": "^7.0.2",
|
||||||
"@types/enzyme": "^3.10.13",
|
"@types/enzyme": "^3.10.13",
|
||||||
"@types/flot": "0.0.32",
|
"@types/flot": "0.0.32",
|
||||||
|
@ -23487,7 +23487,7 @@
|
||||||
"@lezer/common": "^1.0.3",
|
"@lezer/common": "^1.0.3",
|
||||||
"@lezer/highlight": "^1.1.6",
|
"@lezer/highlight": "^1.1.6",
|
||||||
"@lezer/lr": "^1.3.6",
|
"@lezer/lr": "^1.3.6",
|
||||||
"@prometheus-io/lezer-promql": "0.47.0",
|
"@prometheus-io/lezer-promql": "0.47.2",
|
||||||
"@types/lru-cache": "^5.1.1",
|
"@types/lru-cache": "^5.1.1",
|
||||||
"isomorphic-fetch": "^3.0.0",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
"lru-cache": "^6.0.0",
|
"lru-cache": "^6.0.0",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@prometheus-io/app",
|
"name": "@prometheus-io/app",
|
||||||
"version": "0.47.0",
|
"version": "0.47.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.7.1",
|
"@codemirror/autocomplete": "^6.7.1",
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
"@lezer/common": "^1.0.3",
|
"@lezer/common": "^1.0.3",
|
||||||
"@nexucis/fuzzy": "^0.4.1",
|
"@nexucis/fuzzy": "^0.4.1",
|
||||||
"@nexucis/kvsearch": "^0.8.1",
|
"@nexucis/kvsearch": "^0.8.1",
|
||||||
"@prometheus-io/codemirror-promql": "0.47.0",
|
"@prometheus-io/codemirror-promql": "0.47.2",
|
||||||
"bootstrap": "^4.6.2",
|
"bootstrap": "^4.6.2",
|
||||||
"css.escape": "^1.5.1",
|
"css.escape": "^1.5.1",
|
||||||
"downshift": "^7.6.0",
|
"downshift": "^7.6.0",
|
||||||
|
|
Loading…
Reference in a new issue