diff --git a/prompb/types.pb.go b/prompb/types.pb.go index 4f23d4a275..a4c6b332bb 100644 --- a/prompb/types.pb.go +++ b/prompb/types.pb.go @@ -363,6 +363,7 @@ func (m *Exemplar) GetTimestamp() int64 { // integer histogram as well as a float histogram. type Histogram struct { // Types that are valid to be assigned to Count: + // // *Histogram_CountInt // *Histogram_CountFloat Count isHistogram_Count `protobuf_oneof:"count"` @@ -377,6 +378,7 @@ type Histogram struct { Schema int32 `protobuf:"zigzag32,4,opt,name=schema,proto3" json:"schema,omitempty"` ZeroThreshold float64 `protobuf:"fixed64,5,opt,name=zero_threshold,json=zeroThreshold,proto3" json:"zero_threshold,omitempty"` // Types that are valid to be assigned to ZeroCount: + // // *Histogram_ZeroCountInt // *Histogram_ZeroCountFloat ZeroCount isHistogram_ZeroCount `protobuf_oneof:"zero_count"` diff --git a/tsdb/chunkenc/histogram.go b/tsdb/chunkenc/histogram.go index 28a39e57d0..aeabd256f7 100644 --- a/tsdb/chunkenc/histogram.go +++ b/tsdb/chunkenc/histogram.go @@ -738,6 +738,7 @@ func (it *histogramIterator) Next() ValueType { } it.sum = math.Float64frombits(sum) + var current int64 for i := range it.pBuckets { v, err := readVarbitInt(&it.br) if err != nil { @@ -745,8 +746,10 @@ func (it *histogramIterator) Next() ValueType { return ValNone } it.pBuckets[i] = v - it.pFloatBuckets[i] = float64(v) + current += it.pBuckets[i] + it.pFloatBuckets[i] = float64(current) } + current = 0 for i := range it.nBuckets { v, err := readVarbitInt(&it.br) if err != nil { @@ -754,7 +757,8 @@ func (it *histogramIterator) Next() ValueType { return ValNone } it.nBuckets[i] = v - it.nFloatBuckets[i] = float64(v) + current += it.nBuckets[i] + it.nFloatBuckets[i] = float64(current) } it.numRead++ diff --git a/tsdb/chunkenc/histogram_test.go b/tsdb/chunkenc/histogram_test.go index a7b8fbb209..1a187667c3 100644 --- a/tsdb/chunkenc/histogram_test.go +++ b/tsdb/chunkenc/histogram_test.go @@ -330,3 +330,140 @@ func TestHistoChunkAppendable(t *testing.T) { require.True(t, cr) } } + +func TestAtFloatHistogram(t *testing.T) { + input := []histogram.Histogram{ + { + Schema: 0, + Count: 21, + Sum: 1234.5, + ZeroThreshold: 0.001, + ZeroCount: 4, + PositiveSpans: []histogram.Span{ + {Offset: 0, Length: 4}, + {Offset: 0, Length: 0}, + {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}, + }, + { + Schema: 0, + Count: 36, + Sum: 2345.6, + ZeroThreshold: 0.001, + ZeroCount: 5, + PositiveSpans: []histogram.Span{ + {Offset: 0, Length: 4}, + {Offset: 0, Length: 0}, + {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}, + }, + { + Schema: 0, + Count: 36, + Sum: 1111.1, + ZeroThreshold: 0.001, + ZeroCount: 5, + PositiveSpans: []histogram.Span{ + {Offset: 0, Length: 4}, + {Offset: 0, Length: 0}, + {Offset: 0, Length: 3}, + }, + PositiveBuckets: []int64{1, 2, -2, 2, -1, 0, 0}, + NegativeSpans: []histogram.Span{ + {Offset: 1, Length: 4}, + {Offset: 2, Length: 0}, + {Offset: 2, Length: 3}, + }, + NegativeBuckets: []int64{1, 3, -2, 5, -1, 0, -3}, + }, + } + + expOutput := []*histogram.FloatHistogram{ + { + Schema: 0, + Count: 21, + Sum: 1234.5, + ZeroThreshold: 0.001, + ZeroCount: 4, + PositiveSpans: []histogram.Span{ + {Offset: 0, Length: 4}, + {Offset: 0, Length: 0}, + {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}, + }, + { + Schema: 0, + Count: 36, + Sum: 2345.6, + ZeroThreshold: 0.001, + ZeroCount: 5, + PositiveSpans: []histogram.Span{ + {Offset: 0, Length: 4}, + {Offset: 0, Length: 0}, + {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}, + }, + { + Schema: 0, + Count: 36, + Sum: 1111.1, + ZeroThreshold: 0.001, + ZeroCount: 5, + PositiveSpans: []histogram.Span{ + {Offset: 0, Length: 4}, + {Offset: 0, Length: 0}, + {Offset: 0, Length: 3}, + }, + PositiveBuckets: []float64{1, 3, 1, 3, 2, 2, 2}, + NegativeSpans: []histogram.Span{ + {Offset: 1, Length: 4}, + {Offset: 2, Length: 0}, + {Offset: 2, Length: 3}, + }, + NegativeBuckets: []float64{1, 4, 2, 7, 6, 6, 3}, + }, + } + + chk := NewHistogramChunk() + app, err := chk.Appender() + require.NoError(t, err) + for i := range input { + app.AppendHistogram(int64(i), &input[i]) + } + it := chk.Iterator(nil) + i := int64(0) + for it.Next() != ValNone { + ts, h := it.AtFloatHistogram() + require.Equal(t, i, ts) + require.Equal(t, expOutput[i], h, "histogram %d unequal", i) + i++ + } +}