client_golang/prometheus/histogram_test.go

2088 lines
59 KiB
Go
Raw Normal View History

// Copyright 2015 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package prometheus
import (
"math"
"math/rand"
"reflect"
"runtime"
"sort"
"sync"
"sync/atomic"
"testing"
"testing/quick"
"time"
2015-02-27 18:12:59 +03:00
dto "github.com/prometheus/client_model/go"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/timestamppb"
Add native histograms Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Apply suggestions from code review Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Fix references and existing tests Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Review comments Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> fmt Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> validation Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Count validation Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Validation Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Review comments Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Space formatting Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Review comments Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Rename SyncMaptoMap -> SyncMapToMap Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Remove exemplars from parameters for constNativeHistogram function Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Update prometheus/histogram.go Co-authored-by: George Krajcsovits <krajorama@users.noreply.github.com> Signed-off-by: Shivanth MP <shivanth.metchem@deliveryhero.com> Update prometheus/histogram.go Co-authored-by: George Krajcsovits <krajorama@users.noreply.github.com> Signed-off-by: Shivanth MP <shivanth.metchem@deliveryhero.com> Update prometheus/histogram.go Co-authored-by: George Krajcsovits <krajorama@users.noreply.github.com> Signed-off-by: Shivanth MP <shivanth.metchem@deliveryhero.com> Update prometheus/histogram.go Co-authored-by: Björn Rabenstein <github@rabenste.in> Signed-off-by: Shivanth MP <shivanth.metchem@deliveryhero.com> Review comments Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Lint fix Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com>
2024-10-16 15:30:59 +03:00
"github.com/prometheus/client_golang/prometheus/internal"
)
func benchmarkHistogramObserve(w int, b *testing.B) {
b.StopTimer()
wg := new(sync.WaitGroup)
wg.Add(w)
g := new(sync.WaitGroup)
g.Add(1)
s := NewHistogram(HistogramOpts{})
for i := 0; i < w; i++ {
go func() {
g.Wait()
for i := 0; i < b.N; i++ {
s.Observe(float64(i))
}
wg.Done()
}()
}
b.StartTimer()
g.Done()
wg.Wait()
}
func BenchmarkHistogramObserve1(b *testing.B) {
benchmarkHistogramObserve(1, b)
}
func BenchmarkHistogramObserve2(b *testing.B) {
benchmarkHistogramObserve(2, b)
}
func BenchmarkHistogramObserve4(b *testing.B) {
benchmarkHistogramObserve(4, b)
}
func BenchmarkHistogramObserve8(b *testing.B) {
benchmarkHistogramObserve(8, b)
}
func benchmarkHistogramWrite(w int, b *testing.B) {
b.StopTimer()
wg := new(sync.WaitGroup)
wg.Add(w)
g := new(sync.WaitGroup)
g.Add(1)
s := NewHistogram(HistogramOpts{})
for i := 0; i < 1000000; i++ {
s.Observe(float64(i))
}
for j := 0; j < w; j++ {
outs := make([]dto.Metric, b.N)
go func(o []dto.Metric) {
g.Wait()
for i := 0; i < b.N; i++ {
s.Write(&o[i])
}
wg.Done()
}(outs)
}
b.StartTimer()
g.Done()
wg.Wait()
}
func BenchmarkHistogramWrite1(b *testing.B) {
benchmarkHistogramWrite(1, b)
}
func BenchmarkHistogramWrite2(b *testing.B) {
benchmarkHistogramWrite(2, b)
}
func BenchmarkHistogramWrite4(b *testing.B) {
benchmarkHistogramWrite(4, b)
}
func BenchmarkHistogramWrite8(b *testing.B) {
benchmarkHistogramWrite(8, b)
}
func TestHistogramNonMonotonicBuckets(t *testing.T) {
testCases := map[string][]float64{
"not strictly monotonic": {1, 2, 2, 3},
"not monotonic at all": {1, 2, 4, 3, 5},
"have +Inf in the middle": {1, 2, math.Inf(+1), 3},
}
for name, buckets := range testCases {
func() {
defer func() {
if r := recover(); r == nil {
t.Errorf("Buckets %v are %s but NewHistogram did not panic.", buckets, name)
}
}()
_ = NewHistogram(HistogramOpts{
Name: "test_histogram",
Help: "helpless",
Buckets: buckets,
})
}()
}
}
// Intentionally adding +Inf here to test if that case is handled correctly.
// Also, getCumulativeCounts depends on it.
var testBuckets = []float64{-2, -1, -0.5, 0, 0.5, 1, 2, math.Inf(+1)}
func TestHistogramConcurrency(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test in short mode.")
}
2015-11-09 16:52:51 +03:00
rand.New(rand.NewSource(42))
it := func(n uint32) bool {
mutations := int(n%1e4 + 1e4)
concLevel := int(n%5 + 1)
total := mutations * concLevel
var start, end sync.WaitGroup
start.Add(1)
end.Add(concLevel)
his := NewHistogram(HistogramOpts{
Name: "test_histogram",
Help: "helpless",
Buckets: testBuckets,
})
allVars := make([]float64, total)
var sampleSum float64
for i := 0; i < concLevel; i++ {
vals := make([]float64, mutations)
for j := 0; j < mutations; j++ {
v := rand.NormFloat64()
vals[j] = v
allVars[i*mutations+j] = v
sampleSum += v
}
go func(vals []float64) {
start.Wait()
for _, v := range vals {
if n%2 == 0 {
his.Observe(v)
} else {
his.(ExemplarObserver).ObserveWithExemplar(v, Labels{"foo": "bar"})
}
}
end.Done()
}(vals)
}
sort.Float64s(allVars)
start.Done()
end.Wait()
m := &dto.Metric{}
his.Write(m)
if got, want := int(*m.Histogram.SampleCount), total; got != want {
t.Errorf("got sample count %d, want %d", got, want)
}
if got, want := *m.Histogram.SampleSum, sampleSum; math.Abs((got-want)/want) > 0.001 {
t.Errorf("got sample sum %f, want %f", got, want)
}
wantCounts := getCumulativeCounts(allVars)
wantBuckets := len(testBuckets)
if !math.IsInf(m.Histogram.Bucket[len(m.Histogram.Bucket)-1].GetUpperBound(), +1) {
wantBuckets--
}
if got := len(m.Histogram.Bucket); got != wantBuckets {
t.Errorf("got %d buckets in protobuf, want %d", got, wantBuckets)
}
for i, wantBound := range testBuckets {
if i == len(testBuckets)-1 {
break // No +Inf bucket in protobuf.
}
if gotBound := *m.Histogram.Bucket[i].UpperBound; gotBound != wantBound {
t.Errorf("got bound %f, want %f", gotBound, wantBound)
}
if gotCount, wantCount := *m.Histogram.Bucket[i].CumulativeCount, wantCounts[i]; gotCount != wantCount {
t.Errorf("got count %d, want %d", gotCount, wantCount)
}
}
return true
}
if err := quick.Check(it, nil); err != nil {
t.Error(err)
}
}
func TestHistogramVecConcurrency(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test in short mode.")
}
rand.New(rand.NewSource(42))
it := func(n uint32) bool {
mutations := int(n%1e4 + 1e4)
concLevel := int(n%7 + 1)
vecLength := int(n%3 + 1)
var start, end sync.WaitGroup
start.Add(1)
end.Add(concLevel)
his := NewHistogramVec(
HistogramOpts{
Name: "test_histogram",
Help: "helpless",
Buckets: []float64{-2, -1, -0.5, 0, 0.5, 1, 2, math.Inf(+1)},
},
[]string{"label"},
)
allVars := make([][]float64, vecLength)
sampleSums := make([]float64, vecLength)
for i := 0; i < concLevel; i++ {
vals := make([]float64, mutations)
picks := make([]int, mutations)
for j := 0; j < mutations; j++ {
v := rand.NormFloat64()
vals[j] = v
pick := rand.Intn(vecLength)
picks[j] = pick
allVars[pick] = append(allVars[pick], v)
sampleSums[pick] += v
}
go func(vals []float64) {
start.Wait()
for i, v := range vals {
his.WithLabelValues(string('A' + rune(picks[i]))).Observe(v)
}
end.Done()
}(vals)
}
for _, vars := range allVars {
sort.Float64s(vars)
}
start.Done()
end.Wait()
for i := 0; i < vecLength; i++ {
m := &dto.Metric{}
s := his.WithLabelValues(string('A' + rune(i)))
s.(Histogram).Write(m)
if got, want := len(m.Histogram.Bucket), len(testBuckets)-1; got != want {
t.Errorf("got %d buckets in protobuf, want %d", got, want)
}
if got, want := int(*m.Histogram.SampleCount), len(allVars[i]); got != want {
t.Errorf("got sample count %d, want %d", got, want)
}
if got, want := *m.Histogram.SampleSum, sampleSums[i]; math.Abs((got-want)/want) > 0.001 {
t.Errorf("got sample sum %f, want %f", got, want)
}
wantCounts := getCumulativeCounts(allVars[i])
for j, wantBound := range testBuckets {
if j == len(testBuckets)-1 {
break // No +Inf bucket in protobuf.
}
if gotBound := *m.Histogram.Bucket[j].UpperBound; gotBound != wantBound {
t.Errorf("got bound %f, want %f", gotBound, wantBound)
}
if gotCount, wantCount := *m.Histogram.Bucket[j].CumulativeCount, wantCounts[j]; gotCount != wantCount {
t.Errorf("got count %d, want %d", gotCount, wantCount)
}
}
}
return true
}
if err := quick.Check(it, nil); err != nil {
t.Error(err)
}
}
func getCumulativeCounts(vars []float64) []uint64 {
counts := make([]uint64, len(testBuckets))
for _, v := range vars {
for i := len(testBuckets) - 1; i >= 0; i-- {
if v > testBuckets[i] {
break
}
counts[i]++
}
}
return counts
}
func TestBuckets(t *testing.T) {
got := LinearBuckets(-15, 5, 6)
want := []float64{-15, -10, -5, 0, 5, 10}
if !reflect.DeepEqual(got, want) {
t.Errorf("linear buckets: got %v, want %v", got, want)
}
got = ExponentialBuckets(100, 1.2, 3)
want = []float64{100, 120, 144}
if !reflect.DeepEqual(got, want) {
t.Errorf("exponential buckets: got %v, want %v", got, want)
}
got = ExponentialBucketsRange(1, 100, 10)
want = []float64{
Fix float64 comparison test failure on archs using FMA (#1133) * Fix float64 comparison test failure on archs using FMA Architectures using FMA optimization yield slightly different results so we cannot assume floating point values will be precisely the same across different architectures. The solution in this change is to check "abs(a-b) < tolerance" instead of comparing the exact values. This will give us confidence that the histogram buckets are near identical. Signed-off-by: Seth Bunce <seth.bunce@getcruise.com> * Apply suggestions from code review Co-authored-by: Daniel Swarbrick <daniel.swarbrick@gmail.com> Signed-off-by: Seth Bunce <seth.bunce@getcruise.com> * copy float compare dependency Per discussion in the pull request, we'd like to avoid having an extra dependency on a float comparison package. Instead, we copy the float compare functions from the float comparison package. The float comparison package we're choosing is this. The author of this package has commented in the pull request and it looks like we have consensus that this is the best option. github.com/beorn7/floats Signed-off-by: Seth Bunce <seth.bunce@gmail.com> * remove float32 variant, relocate into separate file This change removes the float32 variant of the AlmostEqual funcs, that we will likely never use. This change also relocates the function into a separate file to avoid modifying a file that's a fork of another vendored package. Signed-off-by: Seth Bunce <seth.bunce@gmail.com> Signed-off-by: Seth Bunce <seth.bunce@getcruise.com> Signed-off-by: Seth Bunce <seth.bunce@gmail.com> Co-authored-by: Daniel Swarbrick <daniel.swarbrick@gmail.com>
2022-11-07 21:20:43 +03:00
1.0, 1.6681, 2.7825, 4.6415, 7.7426, 12.9154, 21.5443,
35.9381, 59.9484, 100.0000,
}
Fix float64 comparison test failure on archs using FMA (#1133) * Fix float64 comparison test failure on archs using FMA Architectures using FMA optimization yield slightly different results so we cannot assume floating point values will be precisely the same across different architectures. The solution in this change is to check "abs(a-b) < tolerance" instead of comparing the exact values. This will give us confidence that the histogram buckets are near identical. Signed-off-by: Seth Bunce <seth.bunce@getcruise.com> * Apply suggestions from code review Co-authored-by: Daniel Swarbrick <daniel.swarbrick@gmail.com> Signed-off-by: Seth Bunce <seth.bunce@getcruise.com> * copy float compare dependency Per discussion in the pull request, we'd like to avoid having an extra dependency on a float comparison package. Instead, we copy the float compare functions from the float comparison package. The float comparison package we're choosing is this. The author of this package has commented in the pull request and it looks like we have consensus that this is the best option. github.com/beorn7/floats Signed-off-by: Seth Bunce <seth.bunce@gmail.com> * remove float32 variant, relocate into separate file This change removes the float32 variant of the AlmostEqual funcs, that we will likely never use. This change also relocates the function into a separate file to avoid modifying a file that's a fork of another vendored package. Signed-off-by: Seth Bunce <seth.bunce@gmail.com> Signed-off-by: Seth Bunce <seth.bunce@getcruise.com> Signed-off-by: Seth Bunce <seth.bunce@gmail.com> Co-authored-by: Daniel Swarbrick <daniel.swarbrick@gmail.com>
2022-11-07 21:20:43 +03:00
const epsilon = 0.0001
if !internal.AlmostEqualFloat64s(got, want, epsilon) {
t.Errorf("exponential buckets range: got %v, want %v (epsilon %f)", got, want, epsilon)
}
}
func TestHistogramAtomicObserve(t *testing.T) {
var (
quit = make(chan struct{})
his = NewHistogram(HistogramOpts{
Buckets: []float64{0.5, 10, 20},
})
)
defer func() { close(quit) }()
Make Histogram observations atomic while keeping them lock-free Fixes #275 This is rather tricky and required some studying of the Go memory model. I have added copious code comments to explain what's going on. Benchmarks haven't changed significantly, despite the additional atomic operations now required during Observe. Write performance is noticable, but it is also much more involved now and has a mutex. (But note that Write is supposed to be a relatively rare operation and thus not in the hot path compared to Observe.) Allocs haven't changed at all. OLD: BenchmarkHistogramWithLabelValues-4 10000000 151 ns/op 0 B/op 0 allocs/op BenchmarkHistogramNoLabels-4 50000000 36.0 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve1-4 50000000 28.1 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve2-4 10000000 160 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve4-4 5000000 378 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve8-4 2000000 768 ns/op 0 B/op 0 allocs/op BenchmarkHistogramWrite1-4 1000000 1589 ns/op 896 B/op 37 allocs/op BenchmarkHistogramWrite2-4 500000 2973 ns/op 1792 B/op 74 allocs/op BenchmarkHistogramWrite4-4 300000 6979 ns/op 3584 B/op 148 allocs/op BenchmarkHistogramWrite8-4 100000 10701 ns/op 7168 B/op 296 allocs/op NEW: BenchmarkHistogramWithLabelValues-4 10000000 191 ns/op 0 B/op 0 allocs/op BenchmarkHistogramNoLabels-4 30000000 50.1 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve1-4 30000000 40.0 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve2-4 20000000 91.5 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve4-4 5000000 317 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve8-4 2000000 636 ns/op 0 B/op 0 allocs/op BenchmarkHistogramWrite1-4 1000000 2072 ns/op 896 B/op 37 allocs/op BenchmarkHistogramWrite2-4 300000 3729 ns/op 1792 B/op 74 allocs/op BenchmarkHistogramWrite4-4 200000 7847 ns/op 3584 B/op 148 allocs/op BenchmarkHistogramWrite8-4 100000 16975 ns/op 7168 B/op 296 allocs/op Signed-off-by: beorn7 <beorn@soundcloud.com>
2018-09-07 17:20:30 +03:00
observe := func() {
for {
select {
case <-quit:
return
default:
his.Observe(1)
time.Sleep(time.Nanosecond)
}
}
Make Histogram observations atomic while keeping them lock-free Fixes #275 This is rather tricky and required some studying of the Go memory model. I have added copious code comments to explain what's going on. Benchmarks haven't changed significantly, despite the additional atomic operations now required during Observe. Write performance is noticable, but it is also much more involved now and has a mutex. (But note that Write is supposed to be a relatively rare operation and thus not in the hot path compared to Observe.) Allocs haven't changed at all. OLD: BenchmarkHistogramWithLabelValues-4 10000000 151 ns/op 0 B/op 0 allocs/op BenchmarkHistogramNoLabels-4 50000000 36.0 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve1-4 50000000 28.1 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve2-4 10000000 160 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve4-4 5000000 378 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve8-4 2000000 768 ns/op 0 B/op 0 allocs/op BenchmarkHistogramWrite1-4 1000000 1589 ns/op 896 B/op 37 allocs/op BenchmarkHistogramWrite2-4 500000 2973 ns/op 1792 B/op 74 allocs/op BenchmarkHistogramWrite4-4 300000 6979 ns/op 3584 B/op 148 allocs/op BenchmarkHistogramWrite8-4 100000 10701 ns/op 7168 B/op 296 allocs/op NEW: BenchmarkHistogramWithLabelValues-4 10000000 191 ns/op 0 B/op 0 allocs/op BenchmarkHistogramNoLabels-4 30000000 50.1 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve1-4 30000000 40.0 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve2-4 20000000 91.5 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve4-4 5000000 317 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve8-4 2000000 636 ns/op 0 B/op 0 allocs/op BenchmarkHistogramWrite1-4 1000000 2072 ns/op 896 B/op 37 allocs/op BenchmarkHistogramWrite2-4 300000 3729 ns/op 1792 B/op 74 allocs/op BenchmarkHistogramWrite4-4 200000 7847 ns/op 3584 B/op 148 allocs/op BenchmarkHistogramWrite8-4 100000 16975 ns/op 7168 B/op 296 allocs/op Signed-off-by: beorn7 <beorn@soundcloud.com>
2018-09-07 17:20:30 +03:00
}
go observe()
go observe()
go observe()
for i := 0; i < 100; i++ {
m := &dto.Metric{}
if err := his.Write(m); err != nil {
t.Fatal("unexpected error writing histogram:", err)
}
h := m.GetHistogram()
if h.GetSampleCount() != uint64(h.GetSampleSum()) ||
Make Histogram observations atomic while keeping them lock-free Fixes #275 This is rather tricky and required some studying of the Go memory model. I have added copious code comments to explain what's going on. Benchmarks haven't changed significantly, despite the additional atomic operations now required during Observe. Write performance is noticable, but it is also much more involved now and has a mutex. (But note that Write is supposed to be a relatively rare operation and thus not in the hot path compared to Observe.) Allocs haven't changed at all. OLD: BenchmarkHistogramWithLabelValues-4 10000000 151 ns/op 0 B/op 0 allocs/op BenchmarkHistogramNoLabels-4 50000000 36.0 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve1-4 50000000 28.1 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve2-4 10000000 160 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve4-4 5000000 378 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve8-4 2000000 768 ns/op 0 B/op 0 allocs/op BenchmarkHistogramWrite1-4 1000000 1589 ns/op 896 B/op 37 allocs/op BenchmarkHistogramWrite2-4 500000 2973 ns/op 1792 B/op 74 allocs/op BenchmarkHistogramWrite4-4 300000 6979 ns/op 3584 B/op 148 allocs/op BenchmarkHistogramWrite8-4 100000 10701 ns/op 7168 B/op 296 allocs/op NEW: BenchmarkHistogramWithLabelValues-4 10000000 191 ns/op 0 B/op 0 allocs/op BenchmarkHistogramNoLabels-4 30000000 50.1 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve1-4 30000000 40.0 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve2-4 20000000 91.5 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve4-4 5000000 317 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve8-4 2000000 636 ns/op 0 B/op 0 allocs/op BenchmarkHistogramWrite1-4 1000000 2072 ns/op 896 B/op 37 allocs/op BenchmarkHistogramWrite2-4 300000 3729 ns/op 1792 B/op 74 allocs/op BenchmarkHistogramWrite4-4 200000 7847 ns/op 3584 B/op 148 allocs/op BenchmarkHistogramWrite8-4 100000 16975 ns/op 7168 B/op 296 allocs/op Signed-off-by: beorn7 <beorn@soundcloud.com>
2018-09-07 17:20:30 +03:00
h.GetSampleCount() != h.GetBucket()[1].GetCumulativeCount() ||
h.GetSampleCount() != h.GetBucket()[2].GetCumulativeCount() {
t.Fatalf(
Make Histogram observations atomic while keeping them lock-free Fixes #275 This is rather tricky and required some studying of the Go memory model. I have added copious code comments to explain what's going on. Benchmarks haven't changed significantly, despite the additional atomic operations now required during Observe. Write performance is noticable, but it is also much more involved now and has a mutex. (But note that Write is supposed to be a relatively rare operation and thus not in the hot path compared to Observe.) Allocs haven't changed at all. OLD: BenchmarkHistogramWithLabelValues-4 10000000 151 ns/op 0 B/op 0 allocs/op BenchmarkHistogramNoLabels-4 50000000 36.0 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve1-4 50000000 28.1 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve2-4 10000000 160 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve4-4 5000000 378 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve8-4 2000000 768 ns/op 0 B/op 0 allocs/op BenchmarkHistogramWrite1-4 1000000 1589 ns/op 896 B/op 37 allocs/op BenchmarkHistogramWrite2-4 500000 2973 ns/op 1792 B/op 74 allocs/op BenchmarkHistogramWrite4-4 300000 6979 ns/op 3584 B/op 148 allocs/op BenchmarkHistogramWrite8-4 100000 10701 ns/op 7168 B/op 296 allocs/op NEW: BenchmarkHistogramWithLabelValues-4 10000000 191 ns/op 0 B/op 0 allocs/op BenchmarkHistogramNoLabels-4 30000000 50.1 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve1-4 30000000 40.0 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve2-4 20000000 91.5 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve4-4 5000000 317 ns/op 0 B/op 0 allocs/op BenchmarkHistogramObserve8-4 2000000 636 ns/op 0 B/op 0 allocs/op BenchmarkHistogramWrite1-4 1000000 2072 ns/op 896 B/op 37 allocs/op BenchmarkHistogramWrite2-4 300000 3729 ns/op 1792 B/op 74 allocs/op BenchmarkHistogramWrite4-4 200000 7847 ns/op 3584 B/op 148 allocs/op BenchmarkHistogramWrite8-4 100000 16975 ns/op 7168 B/op 296 allocs/op Signed-off-by: beorn7 <beorn@soundcloud.com>
2018-09-07 17:20:30 +03:00
"inconsistent counts in histogram: count=%d sum=%f buckets=[%d, %d]",
h.GetSampleCount(), h.GetSampleSum(),
h.GetBucket()[1].GetCumulativeCount(), h.GetBucket()[2].GetCumulativeCount(),
)
}
runtime.Gosched()
}
}
func TestHistogramExemplar(t *testing.T) {
now := time.Now()
histogram := NewHistogram(HistogramOpts{
Name: "test",
Help: "test help",
Buckets: []float64{1, 2, 3, 4},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
now: func() time.Time { return now },
}).(*histogram)
ts := timestamppb.New(now)
if err := ts.CheckValid(); err != nil {
t.Fatal(err)
}
expectedExemplars := []*dto.Exemplar{
nil,
{
Label: []*dto.LabelPair{
{Name: proto.String("id"), Value: proto.String("2")},
},
Value: proto.Float64(1.6),
Timestamp: ts,
},
nil,
{
Label: []*dto.LabelPair{
{Name: proto.String("id"), Value: proto.String("3")},
},
Value: proto.Float64(4),
Timestamp: ts,
},
{
Label: []*dto.LabelPair{
{Name: proto.String("id"), Value: proto.String("4")},
},
Value: proto.Float64(4.5),
Timestamp: ts,
},
}
histogram.ObserveWithExemplar(1.5, Labels{"id": "1"})
histogram.ObserveWithExemplar(1.6, Labels{"id": "2"}) // To replace exemplar in bucket 0.
histogram.ObserveWithExemplar(4, Labels{"id": "3"})
histogram.ObserveWithExemplar(4.5, Labels{"id": "4"}) // Should go to +Inf bucket.
for i, ex := range histogram.exemplars {
var got, expected string
if val := ex.Load(); val != nil {
got = val.(*dto.Exemplar).String()
}
if expectedExemplars[i] != nil {
expected = expectedExemplars[i].String()
}
if got != expected {
t.Errorf("expected exemplar %s, got %s.", expected, got)
}
}
}
func TestNativeHistogram(t *testing.T) {
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
now := time.Now()
scenarios := []struct {
name string
observations []float64 // With simulated interval of 1m.
factor float64
zeroThreshold float64
maxBuckets uint32
minResetDuration time.Duration
maxZeroThreshold float64
want *dto.Histogram
}{
{
name: "no sparse buckets",
observations: []float64{1, 2, 3},
factor: 1,
want: &dto.Histogram{
SampleCount: proto.Uint64(3),
SampleSum: proto.Float64(6),
Bucket: []*dto.Bucket{
{CumulativeCount: proto.Uint64(0), UpperBound: proto.Float64(0.005)},
{CumulativeCount: proto.Uint64(0), UpperBound: proto.Float64(0.01)},
{CumulativeCount: proto.Uint64(0), UpperBound: proto.Float64(0.025)},
{CumulativeCount: proto.Uint64(0), UpperBound: proto.Float64(0.05)},
{CumulativeCount: proto.Uint64(0), UpperBound: proto.Float64(0.1)},
{CumulativeCount: proto.Uint64(0), UpperBound: proto.Float64(0.25)},
{CumulativeCount: proto.Uint64(0), UpperBound: proto.Float64(0.5)},
{CumulativeCount: proto.Uint64(1), UpperBound: proto.Float64(1)},
{CumulativeCount: proto.Uint64(2), UpperBound: proto.Float64(2.5)},
{CumulativeCount: proto.Uint64(3), UpperBound: proto.Float64(5)},
{CumulativeCount: proto.Uint64(3), UpperBound: proto.Float64(10)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "no observations",
factor: 1.1,
want: &dto.Histogram{
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
SampleCount: proto.Uint64(0),
SampleSum: proto.Float64(0),
Schema: proto.Int32(3),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(0),
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "no observations and zero threshold of zero resulting in no-op span",
factor: 1.1,
zeroThreshold: NativeHistogramZeroThresholdZero,
want: &dto.Histogram{
SampleCount: proto.Uint64(0),
SampleSum: proto.Float64(0),
Schema: proto.Int32(3),
ZeroThreshold: proto.Float64(0),
ZeroCount: proto.Uint64(0),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(0)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "factor 1.1 results in schema 3",
observations: []float64{0, 1, 2, 3},
factor: 1.1,
want: &dto.Histogram{
SampleCount: proto.Uint64(4),
SampleSum: proto.Float64(6),
Schema: proto.Int32(3),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(1)},
{Offset: proto.Int32(7), Length: proto.Uint32(1)},
{Offset: proto.Int32(4), Length: proto.Uint32(1)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
PositiveDelta: []int64{1, 0, 0},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "factor 1.2 results in schema 2",
observations: []float64{0, 1, 1.2, 1.4, 1.8, 2},
factor: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(6),
SampleSum: proto.Float64(7.4),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
PositiveDelta: []int64{1, -1, 2, -2, 2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "factor 4 results in schema -1",
observations: []float64{
0.0156251, 0.0625, // Bucket -2: (0.015625, 0.0625)
0.1, 0.25, // Bucket -1: (0.0625, 0.25]
0.5, 1, // Bucket 0: (0.25, 1]
1.5, 2, 3, 3.5, // Bucket 1: (1, 4]
5, 6, 7, // Bucket 2: (4, 16]
33.33, // Bucket 3: (16, 64]
},
factor: 4,
want: &dto.Histogram{
SampleCount: proto.Uint64(14),
SampleSum: proto.Float64(63.2581251),
Schema: proto.Int32(-1),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(0),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(-2), Length: proto.Uint32(6)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
PositiveDelta: []int64{2, 0, 0, 2, -1, -2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "factor 17 results in schema -2",
observations: []float64{
0.0156251, 0.0625, // Bucket -1: (0.015625, 0.0625]
0.1, 0.25, 0.5, 1, // Bucket 0: (0.0625, 1]
1.5, 2, 3, 3.5, 5, 6, 7, // Bucket 1: (1, 16]
33.33, // Bucket 2: (16, 256]
},
factor: 17,
want: &dto.Histogram{
SampleCount: proto.Uint64(14),
SampleSum: proto.Float64(63.2581251),
Schema: proto.Int32(-2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(0),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(-1), Length: proto.Uint32(4)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
PositiveDelta: []int64{2, 2, 3, -6},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "negative buckets",
observations: []float64{0, -1, -1.2, -1.4, -1.8, -2},
factor: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(6),
SampleSum: proto.Float64(-7.4),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
NegativeDelta: []int64{1, -1, 2, -2, 2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "negative and positive buckets",
observations: []float64{0, -1, -1.2, -1.4, -1.8, -2, 1, 1.2, 1.4, 1.8, 2},
factor: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(11),
SampleSum: proto.Float64(0),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
NegativeDelta: []int64{1, -1, 2, -2, 2},
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
PositiveDelta: []int64{1, -1, 2, -2, 2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "wide zero bucket",
observations: []float64{0, -1, -1.2, -1.4, -1.8, -2, 1, 1.2, 1.4, 1.8, 2},
factor: 1.2,
zeroThreshold: 1.4,
want: &dto.Histogram{
SampleCount: proto.Uint64(11),
SampleSum: proto.Float64(0),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(1.4),
ZeroCount: proto.Uint64(7),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(4), Length: proto.Uint32(1)},
},
NegativeDelta: []int64{2},
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(4), Length: proto.Uint32(1)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
PositiveDelta: []int64{2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "NaN observation",
observations: []float64{0, 1, 1.2, 1.4, 1.8, 2, math.NaN()},
factor: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(7),
SampleSum: proto.Float64(math.NaN()),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
PositiveDelta: []int64{1, -1, 2, -2, 2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "+Inf observation",
observations: []float64{0, 1, 1.2, 1.4, 1.8, 2, math.Inf(+1)},
factor: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(7),
SampleSum: proto.Float64(math.Inf(+1)),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
{Offset: proto.Int32(4092), Length: proto.Uint32(1)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
PositiveDelta: []int64{1, -1, 2, -2, 2, -1},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "-Inf observation",
observations: []float64{0, 1, 1.2, 1.4, 1.8, 2, math.Inf(-1)},
factor: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(7),
SampleSum: proto.Float64(math.Inf(-1)),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(4097), Length: proto.Uint32(1)},
},
NegativeDelta: []int64{1},
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
PositiveDelta: []int64{1, -1, 2, -2, 2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "limited buckets but nothing triggered",
observations: []float64{0, 1, 1.2, 1.4, 1.8, 2},
factor: 1.2,
maxBuckets: 4,
want: &dto.Histogram{
SampleCount: proto.Uint64(6),
SampleSum: proto.Float64(7.4),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
PositiveDelta: []int64{1, -1, 2, -2, 2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by halving resolution",
observations: []float64{0, 1, 1.1, 1.2, 1.4, 1.8, 2, 3},
factor: 1.2,
maxBuckets: 4,
want: &dto.Histogram{
SampleCount: proto.Uint64(8),
SampleSum: proto.Float64(11.5),
Schema: proto.Int32(1),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
PositiveDelta: []int64{1, 2, -1, -2, 1},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by widening the zero bucket",
observations: []float64{0, 1, 1.1, 1.2, 1.4, 1.8, 2, 3},
factor: 1.2,
maxBuckets: 4,
maxZeroThreshold: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(8),
SampleSum: proto.Float64(11.5),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(1),
ZeroCount: proto.Uint64(2),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(1), Length: proto.Uint32(7)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
PositiveDelta: []int64{1, 1, -2, 2, -2, 0, 1},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by widening the zero bucket twice",
observations: []float64{0, 1, 1.1, 1.2, 1.4, 1.8, 2, 3, 4},
factor: 1.2,
maxBuckets: 4,
maxZeroThreshold: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(9),
SampleSum: proto.Float64(15.5),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(1.189207115002721),
ZeroCount: proto.Uint64(3),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(2), Length: proto.Uint32(7)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
PositiveDelta: []int64{2, -2, 2, -2, 0, 1, 0},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by reset",
observations: []float64{0, 1, 1.1, 1.2, 1.4, 1.8, 2, 3, 4},
factor: 1.2,
maxBuckets: 4,
maxZeroThreshold: 1.2,
minResetDuration: 5 * time.Minute,
want: &dto.Histogram{
SampleCount: proto.Uint64(2),
SampleSum: proto.Float64(7),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(0),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(7), Length: proto.Uint32(2)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
PositiveDelta: []int64{1, 0},
CreatedTimestamp: timestamppb.New(now.Add(8 * time.Minute)), // We expect reset to happen after 8 observations.
},
},
{
name: "limited buckets but nothing triggered, negative observations",
observations: []float64{0, -1, -1.2, -1.4, -1.8, -2},
factor: 1.2,
maxBuckets: 4,
want: &dto.Histogram{
SampleCount: proto.Uint64(6),
SampleSum: proto.Float64(-7.4),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
NegativeDelta: []int64{1, -1, 2, -2, 2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by halving resolution, negative observations",
observations: []float64{0, -1, -1.1, -1.2, -1.4, -1.8, -2, -3},
factor: 1.2,
maxBuckets: 4,
want: &dto.Histogram{
SampleCount: proto.Uint64(8),
SampleSum: proto.Float64(-11.5),
Schema: proto.Int32(1),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
NegativeDelta: []int64{1, 2, -1, -2, 1},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by widening the zero bucket, negative observations",
observations: []float64{0, -1, -1.1, -1.2, -1.4, -1.8, -2, -3},
factor: 1.2,
maxBuckets: 4,
maxZeroThreshold: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(8),
SampleSum: proto.Float64(-11.5),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(1),
ZeroCount: proto.Uint64(2),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(1), Length: proto.Uint32(7)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
NegativeDelta: []int64{1, 1, -2, 2, -2, 0, 1},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by widening the zero bucket twice, negative observations",
observations: []float64{0, -1, -1.1, -1.2, -1.4, -1.8, -2, -3, -4},
factor: 1.2,
maxBuckets: 4,
maxZeroThreshold: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(9),
SampleSum: proto.Float64(-15.5),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(1.189207115002721),
ZeroCount: proto.Uint64(3),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(2), Length: proto.Uint32(7)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
NegativeDelta: []int64{2, -2, 2, -2, 0, 1, 0},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by reset, negative observations",
observations: []float64{0, -1, -1.1, -1.2, -1.4, -1.8, -2, -3, -4},
factor: 1.2,
maxBuckets: 4,
maxZeroThreshold: 1.2,
minResetDuration: 5 * time.Minute,
want: &dto.Histogram{
SampleCount: proto.Uint64(2),
SampleSum: proto.Float64(-7),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(0),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(7), Length: proto.Uint32(2)},
},
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
NegativeDelta: []int64{1, 0},
CreatedTimestamp: timestamppb.New(now.Add(8 * time.Minute)), // We expect reset to happen after 8 observations.
},
},
{
name: "buckets limited by halving resolution, then reset",
observations: []float64{0, 1, 1.1, 1.2, 1.4, 1.8, 2, 5, 5.1, 3, 4},
factor: 1.2,
maxBuckets: 4,
minResetDuration: 9 * time.Minute,
want: &dto.Histogram{
SampleCount: proto.Uint64(3),
SampleSum: proto.Float64(12.1),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(0),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(7), Length: proto.Uint32(4)},
},
PositiveDelta: []int64{1, 0, -1, 1},
CreatedTimestamp: timestamppb.New(now.Add(9 * time.Minute)), // We expect reset to happen after 8 minutes.
},
},
{
name: "buckets limited by widening the zero bucket, then reset",
observations: []float64{0, 1, 1.1, 1.2, 1.4, 1.8, 2, 5, 5.1, 3, 4},
factor: 1.2,
maxBuckets: 4,
maxZeroThreshold: 1.2,
minResetDuration: 9 * time.Minute,
want: &dto.Histogram{
SampleCount: proto.Uint64(3),
SampleSum: proto.Float64(12.1),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(0),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(7), Length: proto.Uint32(4)},
},
PositiveDelta: []int64{1, 0, -1, 1},
CreatedTimestamp: timestamppb.New(now.Add(9 * time.Minute)), // We expect reset to happen after 8 minutes.
},
},
}
for _, s := range scenarios {
t.Run(s.name, func(t *testing.T) {
var (
ts = now
funcToCall func()
whenToCall time.Duration
)
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
his := NewHistogram(HistogramOpts{
Name: "name",
Help: "help",
NativeHistogramBucketFactor: s.factor,
NativeHistogramZeroThreshold: s.zeroThreshold,
NativeHistogramMaxBucketNumber: s.maxBuckets,
NativeHistogramMinResetDuration: s.minResetDuration,
NativeHistogramMaxZeroThreshold: s.maxZeroThreshold,
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
now: func() time.Time { return ts },
afterFunc: func(d time.Duration, f func()) *time.Timer {
funcToCall = f
whenToCall = d
return nil
},
})
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
ts = ts.Add(time.Minute)
for _, o := range s.observations {
his.Observe(o)
ts = ts.Add(time.Minute)
whenToCall -= time.Minute
if funcToCall != nil && whenToCall <= 0 {
funcToCall()
funcToCall = nil
}
}
m := &dto.Metric{}
if err := his.Write(m); err != nil {
t.Fatal("unexpected error writing metric", err)
}
got := m.Histogram
if !proto.Equal(s.want, got) {
t.Errorf("want histogram %q, got %q", s.want, got)
}
})
}
}
func TestNativeHistogramConcurrency(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test in short mode.")
}
rand.New(rand.NewSource(42))
it := func(n uint32) bool {
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
ts := time.Now().Add(30 * time.Second).Unix()
mutations := int(n%1e4 + 1e4)
concLevel := int(n%5 + 1)
total := mutations * concLevel
var start, end sync.WaitGroup
start.Add(1)
end.Add(concLevel)
his := NewHistogram(HistogramOpts{
Name: "test_native_histogram",
Help: "This help is sparse.",
NativeHistogramBucketFactor: 1.05,
NativeHistogramZeroThreshold: 0.0000001,
NativeHistogramMaxBucketNumber: 50,
NativeHistogramMinResetDuration: time.Hour, // Comment out to test for totals below.
NativeHistogramMaxZeroThreshold: 0.001,
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
now: func() time.Time {
return time.Unix(atomic.LoadInt64(&ts), 0)
},
})
allVars := make([]float64, total)
var sampleSum float64
for i := 0; i < concLevel; i++ {
vals := make([]float64, mutations)
for j := 0; j < mutations; j++ {
v := rand.NormFloat64()
vals[j] = v
allVars[i*mutations+j] = v
sampleSum += v
}
go func(vals []float64) {
start.Wait()
for i, v := range vals {
// An observation every 1 to 10 seconds.
atomic.AddInt64(&ts, rand.Int63n(10)+1)
if i%2 == 0 {
his.Observe(v)
} else {
his.(ExemplarObserver).ObserveWithExemplar(v, Labels{"foo": "bar"})
}
}
end.Done()
}(vals)
}
sort.Float64s(allVars)
start.Done()
end.Wait()
m := &dto.Metric{}
his.Write(m)
// Uncomment these tests for totals only if you have disabled histogram resets above.
//
// if got, want := int(*m.Histogram.SampleCount), total; got != want {
// t.Errorf("got sample count %d, want %d", got, want)
// }
// if got, want := *m.Histogram.SampleSum, sampleSum; math.Abs((got-want)/want) > 0.001 {
// t.Errorf("got sample sum %f, want %f", got, want)
// }
sumBuckets := int(m.Histogram.GetZeroCount())
current := 0
for _, delta := range m.Histogram.GetNegativeDelta() {
current += int(delta)
if current < 0 {
t.Fatalf("negative bucket population negative: %d", current)
}
sumBuckets += current
}
current = 0
for _, delta := range m.Histogram.GetPositiveDelta() {
current += int(delta)
if current < 0 {
t.Fatalf("positive bucket population negative: %d", current)
}
sumBuckets += current
}
if got, want := sumBuckets, int(*m.Histogram.SampleCount); got != want {
t.Errorf("got bucket population sum %d, want %d", got, want)
}
return true
}
if err := quick.Check(it, nil); err != nil {
t.Error(err)
}
}
func TestGetLe(t *testing.T) {
scenarios := []struct {
key int
schema int32
want float64
}{
{
key: -1,
schema: -1,
want: 0.25,
},
{
key: 0,
schema: -1,
want: 1,
},
{
key: 1,
schema: -1,
want: 4,
},
{
key: 512,
schema: -1,
want: math.MaxFloat64,
},
{
key: 513,
schema: -1,
want: math.Inf(+1),
},
{
key: -1,
schema: 0,
want: 0.5,
},
{
key: 0,
schema: 0,
want: 1,
},
{
key: 1,
schema: 0,
want: 2,
},
{
key: 1024,
schema: 0,
want: math.MaxFloat64,
},
{
key: 1025,
schema: 0,
want: math.Inf(+1),
},
{
key: -1,
schema: 2,
want: 0.8408964152537144,
},
{
key: 0,
schema: 2,
want: 1,
},
{
key: 1,
schema: 2,
want: 1.189207115002721,
},
{
key: 4096,
schema: 2,
want: math.MaxFloat64,
},
{
key: 4097,
schema: 2,
want: math.Inf(+1),
},
}
for i, s := range scenarios {
got := getLe(s.key, s.schema)
if s.want != got {
t.Errorf("%d. key %d, schema %d, want upper bound of %g, got %g", i, s.key, s.schema, s.want, got)
}
}
}
Extend Counters, Summaries and Histograms with creation timestamp (#1313) * Extend Counters, Summaries and Histograms with creation timestamp Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Backport created timestamp to existing tests Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> * Last touches (readability and consistency) Changes: * Comments for "now" are more explicit and not inlined. * populateMetrics is simpler and bit more efficient without timestamp to time to timestamp conversionts for more common code. * Test consistency and simplicity - the fewer variables the better. * Fixed inconsistency for v2 and MetricVec - let's pass opt.now consistently. * We don't need TestCounterXXXTimestamp - we test CT in many other places already. * Added more involved test for counter vectors with created timestamp. * Refactored normalization for simplicity. * Make histogram, summaries now consistent. * Simplified histograms CT flow and implemented proper CT on reset. TODO for next PRs: * NewConstSummary and NewConstHistogram - ability to specify CTs there. Signed-off-by: bwplotka <bwplotka@gmail.com> * Update prometheus/counter_test.go Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> --------- Signed-off-by: Arthur Silva Sens <arthur.sens@coralogix.com> Signed-off-by: bwplotka <bwplotka@gmail.com> Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com> Co-authored-by: bwplotka <bwplotka@gmail.com>
2023-09-21 12:46:54 +03:00
func TestHistogramCreatedTimestamp(t *testing.T) {
now := time.Now()
histogram := NewHistogram(HistogramOpts{
Name: "test",
Help: "test help",
Buckets: []float64{1, 2, 3, 4},
now: func() time.Time { return now },
})
var metric dto.Metric
if err := histogram.Write(&metric); err != nil {
t.Fatal(err)
}
if metric.Histogram.CreatedTimestamp.AsTime().Unix() != now.Unix() {
t.Errorf("expected created timestamp %d, got %d", now.Unix(), metric.Histogram.CreatedTimestamp.AsTime().Unix())
}
}
func TestHistogramVecCreatedTimestamp(t *testing.T) {
now := time.Now()
histogramVec := NewHistogramVec(HistogramOpts{
Name: "test",
Help: "test help",
Buckets: []float64{1, 2, 3, 4},
now: func() time.Time { return now },
}, []string{"label"})
histogram := histogramVec.WithLabelValues("value").(Histogram)
var metric dto.Metric
if err := histogram.Write(&metric); err != nil {
t.Fatal(err)
}
if metric.Histogram.CreatedTimestamp.AsTime().Unix() != now.Unix() {
t.Errorf("expected created timestamp %d, got %d", now.Unix(), metric.Histogram.CreatedTimestamp.AsTime().Unix())
}
}
func TestHistogramVecCreatedTimestampWithDeletes(t *testing.T) {
now := time.Now()
histogramVec := NewHistogramVec(HistogramOpts{
Name: "test",
Help: "test help",
Buckets: []float64{1, 2, 3, 4},
now: func() time.Time { return now },
}, []string{"label"})
// First use of "With" should populate CT.
histogramVec.WithLabelValues("1")
expected := map[string]time.Time{"1": now}
now = now.Add(1 * time.Hour)
expectCTsForMetricVecValues(t, histogramVec.MetricVec, dto.MetricType_HISTOGRAM, expected)
// Two more labels at different times.
histogramVec.WithLabelValues("2")
expected["2"] = now
now = now.Add(1 * time.Hour)
histogramVec.WithLabelValues("3")
expected["3"] = now
now = now.Add(1 * time.Hour)
expectCTsForMetricVecValues(t, histogramVec.MetricVec, dto.MetricType_HISTOGRAM, expected)
// Recreate metric instance should reset created timestamp to now.
histogramVec.DeleteLabelValues("1")
histogramVec.WithLabelValues("1")
expected["1"] = now
now = now.Add(1 * time.Hour)
expectCTsForMetricVecValues(t, histogramVec.MetricVec, dto.MetricType_HISTOGRAM, expected)
}
func TestNewConstHistogramWithCreatedTimestamp(t *testing.T) {
metricDesc := NewDesc(
"sample_value",
"sample value",
nil,
nil,
)
buckets := map[float64]uint64{25: 100, 50: 200}
createdTs := time.Unix(1719670764, 123)
h, err := NewConstHistogramWithCreatedTimestamp(metricDesc, 100, 200, buckets, createdTs)
if err != nil {
t.Fatal(err)
}
var metric dto.Metric
if err := h.Write(&metric); err != nil {
t.Fatal(err)
}
if metric.Histogram.CreatedTimestamp.AsTime().UnixMicro() != createdTs.UnixMicro() {
t.Errorf("Expected created timestamp %v, got %v", createdTs, &metric.Histogram.CreatedTimestamp)
}
}
func TestNativeHistogramExemplar(t *testing.T) {
// Test the histogram with positive NativeHistogramExemplarTTL and NativeHistogramMaxExemplars
h := NewHistogram(HistogramOpts{
Name: "test",
Help: "test help",
Buckets: []float64{1, 2, 3, 4},
NativeHistogramBucketFactor: 1.1,
NativeHistogramMaxExemplars: 3,
NativeHistogramExemplarTTL: 10 * time.Second,
}).(*histogram)
tcs := []struct {
name string
addFunc func(*histogram)
expectedValues []float64
}{
{
name: "add exemplars to the limit",
addFunc: func(h *histogram) {
h.ObserveWithExemplar(1, Labels{"id": "1"})
h.ObserveWithExemplar(3, Labels{"id": "1"})
h.ObserveWithExemplar(5, Labels{"id": "1"})
},
expectedValues: []float64{1, 3, 5},
},
{
name: "remove exemplar in closest pair, the removed index equals to inserted index",
addFunc: func(h *histogram) {
h.ObserveWithExemplar(4, Labels{"id": "1"})
},
expectedValues: []float64{1, 3, 4},
},
{
name: "remove exemplar in closest pair, the removed index is bigger than inserted index",
addFunc: func(h *histogram) {
h.ObserveWithExemplar(0, Labels{"id": "1"})
},
expectedValues: []float64{0, 1, 4},
},
{
name: "remove exemplar with oldest timestamp, the removed index is smaller than inserted index",
addFunc: func(h *histogram) {
h.now = func() time.Time { return time.Now().Add(time.Second * 11) }
h.ObserveWithExemplar(6, Labels{"id": "1"})
},
expectedValues: []float64{0, 4, 6},
},
}
for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
tc.addFunc(h)
compareNativeExemplarValues(t, h.nativeExemplars.exemplars, tc.expectedValues)
})
}
// Test the histogram with negative NativeHistogramExemplarTTL
h = NewHistogram(HistogramOpts{
Name: "test",
Help: "test help",
Buckets: []float64{1, 2, 3, 4},
NativeHistogramBucketFactor: 1.1,
NativeHistogramMaxExemplars: 3,
NativeHistogramExemplarTTL: -1 * time.Second,
}).(*histogram)
tcs = []struct {
name string
addFunc func(*histogram)
expectedValues []float64
}{
{
name: "add exemplars to the limit",
addFunc: func(h *histogram) {
h.ObserveWithExemplar(1, Labels{"id": "1"})
h.ObserveWithExemplar(3, Labels{"id": "1"})
h.ObserveWithExemplar(5, Labels{"id": "1"})
},
expectedValues: []float64{1, 3, 5},
},
{
name: "remove exemplar with oldest timestamp, the removed index is smaller than inserted index",
addFunc: func(h *histogram) {
h.ObserveWithExemplar(4, Labels{"id": "1"})
},
expectedValues: []float64{3, 4, 5},
},
{
name: "remove exemplar with oldest timestamp, the removed index equals to inserted index",
addFunc: func(h *histogram) {
h.ObserveWithExemplar(0, Labels{"id": "1"})
},
expectedValues: []float64{0, 4, 5},
},
{
name: "remove exemplar with oldest timestamp, the removed index is bigger than inserted index",
addFunc: func(h *histogram) {
h.ObserveWithExemplar(3, Labels{"id": "1"})
},
expectedValues: []float64{0, 3, 4},
},
}
for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
tc.addFunc(h)
compareNativeExemplarValues(t, h.nativeExemplars.exemplars, tc.expectedValues)
})
}
// Test the histogram with negative NativeHistogramMaxExemplars
h = NewHistogram(HistogramOpts{
Name: "test",
Help: "test help",
Buckets: []float64{1, 2, 3, 4},
NativeHistogramBucketFactor: 1.1,
NativeHistogramMaxExemplars: -1,
NativeHistogramExemplarTTL: -1 * time.Second,
}).(*histogram)
tcs = []struct {
name string
addFunc func(*histogram)
expectedValues []float64
}{
{
name: "add exemplars to the limit, but no effect",
addFunc: func(h *histogram) {
h.ObserveWithExemplar(1, Labels{"id": "1"})
h.ObserveWithExemplar(3, Labels{"id": "1"})
h.ObserveWithExemplar(5, Labels{"id": "1"})
},
expectedValues: []float64{},
},
}
for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
tc.addFunc(h)
compareNativeExemplarValues(t, h.nativeExemplars.exemplars, tc.expectedValues)
})
}
}
func compareNativeExemplarValues(t *testing.T, exps []*dto.Exemplar, values []float64) {
if len(exps) != len(values) {
t.Errorf("the count of exemplars is not %d", len(values))
}
for i, e := range exps {
if e.GetValue() != values[i] {
t.Errorf("the %dth exemplar value %v is not as expected: %v", i, e.GetValue(), values[i])
}
}
}
var resultFindBucket int
func benchmarkFindBucket(b *testing.B, l int) {
h := &histogram{upperBounds: make([]float64, l)}
for i := range h.upperBounds {
h.upperBounds[i] = float64(i)
}
v := float64(l / 2)
b.ResetTimer()
for i := 0; i < b.N; i++ {
resultFindBucket = h.findBucket(v)
}
}
func BenchmarkFindBucketShort(b *testing.B) {
benchmarkFindBucket(b, 20)
}
func BenchmarkFindBucketMid(b *testing.B) {
benchmarkFindBucket(b, 40)
}
func BenchmarkFindBucketLarge(b *testing.B) {
benchmarkFindBucket(b, 100)
}
func BenchmarkFindBucketHuge(b *testing.B) {
benchmarkFindBucket(b, 500)
}
func BenchmarkFindBucketInf(b *testing.B) {
h := &histogram{upperBounds: make([]float64, 500)}
for i := range h.upperBounds {
h.upperBounds[i] = float64(i)
}
v := 1000.5
b.ResetTimer()
for i := 0; i < b.N; i++ {
resultFindBucket = h.findBucket(v)
}
}
func BenchmarkFindBucketLow(b *testing.B) {
h := &histogram{upperBounds: make([]float64, 500)}
for i := range h.upperBounds {
h.upperBounds[i] = float64(i)
}
v := -1.1
b.ResetTimer()
for i := 0; i < b.N; i++ {
resultFindBucket = h.findBucket(v)
}
}
func TestFindBucket(t *testing.T) {
smallHistogram := &histogram{upperBounds: []float64{1, 2, 3, 4, 5}}
largeHistogram := &histogram{upperBounds: make([]float64, 50)}
for i := range largeHistogram.upperBounds {
largeHistogram.upperBounds[i] = float64(i)
}
tests := []struct {
h *histogram
v float64
expected int
}{
{smallHistogram, -1, 0},
{smallHistogram, 0.5, 0},
{smallHistogram, 2.5, 2},
{smallHistogram, 5.5, 5},
{largeHistogram, -1, 0},
{largeHistogram, 25.5, 26},
{largeHistogram, 49.5, 50},
{largeHistogram, 50.5, 50},
{largeHistogram, 5000.5, 50},
}
for _, tt := range tests {
result := tt.h.findBucket(tt.v)
if result != tt.expected {
t.Errorf("findBucket(%v) = %d; expected %d", tt.v, result, tt.expected)
}
}
}
Add native histograms Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Apply suggestions from code review Co-authored-by: Arthur Silva Sens <arthursens2005@gmail.com> Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Fix references and existing tests Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Review comments Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> fmt Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> validation Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Count validation Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Validation Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Review comments Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Space formatting Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Review comments Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Rename SyncMaptoMap -> SyncMapToMap Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Remove exemplars from parameters for constNativeHistogram function Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Update prometheus/histogram.go Co-authored-by: George Krajcsovits <krajorama@users.noreply.github.com> Signed-off-by: Shivanth MP <shivanth.metchem@deliveryhero.com> Update prometheus/histogram.go Co-authored-by: George Krajcsovits <krajorama@users.noreply.github.com> Signed-off-by: Shivanth MP <shivanth.metchem@deliveryhero.com> Update prometheus/histogram.go Co-authored-by: George Krajcsovits <krajorama@users.noreply.github.com> Signed-off-by: Shivanth MP <shivanth.metchem@deliveryhero.com> Update prometheus/histogram.go Co-authored-by: Björn Rabenstein <github@rabenste.in> Signed-off-by: Shivanth MP <shivanth.metchem@deliveryhero.com> Review comments Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com> Lint fix Signed-off-by: Shivanth <shivanth.metchem@deliveryhero.com>
2024-10-16 15:30:59 +03:00
func syncMapToMap(syncmap *sync.Map) (m map[int]int64) {
m = map[int]int64{}
syncmap.Range(func(key, value any) bool {
m[key.(int)] = *value.(*int64)
return true
})
return m
}
func TestConstNativeHistogram(t *testing.T) {
now := time.Now()
scenarios := []struct {
name string
observations []float64 // With simulated interval of 1m.
factor float64
zeroThreshold float64
maxBuckets uint32
minResetDuration time.Duration
maxZeroThreshold float64
want *dto.Histogram
}{
{
name: "no observations",
factor: 1.1,
want: &dto.Histogram{
SampleCount: proto.Uint64(0),
SampleSum: proto.Float64(0),
Schema: proto.Int32(3),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(0),
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "no observations and zero threshold of zero resulting in no-op span",
factor: 1.1,
zeroThreshold: NativeHistogramZeroThresholdZero,
want: &dto.Histogram{
SampleCount: proto.Uint64(0),
SampleSum: proto.Float64(0),
Schema: proto.Int32(3),
ZeroThreshold: proto.Float64(0),
ZeroCount: proto.Uint64(0),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(0)},
},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "factor 1.1 results in schema 3",
observations: []float64{0, 1, 2, 3},
factor: 1.1,
want: &dto.Histogram{
SampleCount: proto.Uint64(4),
SampleSum: proto.Float64(6),
Schema: proto.Int32(3),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(1)},
{Offset: proto.Int32(7), Length: proto.Uint32(1)},
{Offset: proto.Int32(4), Length: proto.Uint32(1)},
},
PositiveDelta: []int64{1, 0, 0},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "factor 1.2 results in schema 2",
observations: []float64{0, 1, 1.2, 1.4, 1.8, 2},
factor: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(6),
SampleSum: proto.Float64(7.4),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
PositiveDelta: []int64{1, -1, 2, -2, 2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "factor 4 results in schema -1",
observations: []float64{
0.0156251, 0.0625, // Bucket -2: (0.015625, 0.0625)
0.1, 0.25, // Bucket -1: (0.0625, 0.25]
0.5, 1, // Bucket 0: (0.25, 1]
1.5, 2, 3, 3.5, // Bucket 1: (1, 4]
5, 6, 7, // Bucket 2: (4, 16]
33.33, // Bucket 3: (16, 64]
},
factor: 4,
want: &dto.Histogram{
SampleCount: proto.Uint64(14),
SampleSum: proto.Float64(63.2581251),
Schema: proto.Int32(-1),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(0),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(-2), Length: proto.Uint32(6)},
},
PositiveDelta: []int64{2, 0, 0, 2, -1, -2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "factor 17 results in schema -2",
observations: []float64{
0.0156251, 0.0625, // Bucket -1: (0.015625, 0.0625]
0.1, 0.25, 0.5, 1, // Bucket 0: (0.0625, 1]
1.5, 2, 3, 3.5, 5, 6, 7, // Bucket 1: (1, 16]
33.33, // Bucket 2: (16, 256]
},
factor: 17,
want: &dto.Histogram{
SampleCount: proto.Uint64(14),
SampleSum: proto.Float64(63.2581251),
Schema: proto.Int32(-2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(0),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(-1), Length: proto.Uint32(4)},
},
PositiveDelta: []int64{2, 2, 3, -6},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "negative buckets",
observations: []float64{0, -1, -1.2, -1.4, -1.8, -2},
factor: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(6),
SampleSum: proto.Float64(-7.4),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
NegativeDelta: []int64{1, -1, 2, -2, 2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "negative and positive buckets",
observations: []float64{0, -1, -1.2, -1.4, -1.8, -2, 1, 1.2, 1.4, 1.8, 2},
factor: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(11),
SampleSum: proto.Float64(0),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
NegativeDelta: []int64{1, -1, 2, -2, 2},
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
PositiveDelta: []int64{1, -1, 2, -2, 2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "wide zero bucket",
observations: []float64{0, -1, -1.2, -1.4, -1.8, -2, 1, 1.2, 1.4, 1.8, 2},
factor: 1.2,
zeroThreshold: 1.4,
want: &dto.Histogram{
SampleCount: proto.Uint64(11),
SampleSum: proto.Float64(0),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(1.4),
ZeroCount: proto.Uint64(7),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(4), Length: proto.Uint32(1)},
},
NegativeDelta: []int64{2},
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(4), Length: proto.Uint32(1)},
},
PositiveDelta: []int64{2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "NaN observation",
observations: []float64{0, 1, 1.2, 1.4, 1.8, 2, math.NaN()},
factor: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(7),
SampleSum: proto.Float64(math.NaN()),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
PositiveDelta: []int64{1, -1, 2, -2, 2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "+Inf observation",
observations: []float64{0, 1, 1.2, 1.4, 1.8, 2, math.Inf(+1)},
factor: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(7),
SampleSum: proto.Float64(math.Inf(+1)),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
{Offset: proto.Int32(4092), Length: proto.Uint32(1)},
},
PositiveDelta: []int64{1, -1, 2, -2, 2, -1},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "-Inf observation",
observations: []float64{0, 1, 1.2, 1.4, 1.8, 2, math.Inf(-1)},
factor: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(7),
SampleSum: proto.Float64(math.Inf(-1)),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(4097), Length: proto.Uint32(1)},
},
NegativeDelta: []int64{1},
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
PositiveDelta: []int64{1, -1, 2, -2, 2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "limited buckets but nothing triggered",
observations: []float64{0, 1, 1.2, 1.4, 1.8, 2},
factor: 1.2,
maxBuckets: 4,
want: &dto.Histogram{
SampleCount: proto.Uint64(6),
SampleSum: proto.Float64(7.4),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
PositiveDelta: []int64{1, -1, 2, -2, 2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by halving resolution",
observations: []float64{0, 1, 1.1, 1.2, 1.4, 1.8, 2, 3},
factor: 1.2,
maxBuckets: 4,
want: &dto.Histogram{
SampleCount: proto.Uint64(8),
SampleSum: proto.Float64(11.5),
Schema: proto.Int32(1),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
PositiveDelta: []int64{1, 2, -1, -2, 1},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by widening the zero bucket",
observations: []float64{0, 1, 1.1, 1.2, 1.4, 1.8, 2, 3},
factor: 1.2,
maxBuckets: 4,
maxZeroThreshold: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(8),
SampleSum: proto.Float64(11.5),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(1),
ZeroCount: proto.Uint64(2),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(1), Length: proto.Uint32(7)},
},
PositiveDelta: []int64{1, 1, -2, 2, -2, 0, 1},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by widening the zero bucket twice",
observations: []float64{0, 1, 1.1, 1.2, 1.4, 1.8, 2, 3, 4},
factor: 1.2,
maxBuckets: 4,
maxZeroThreshold: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(9),
SampleSum: proto.Float64(15.5),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(1.189207115002721),
ZeroCount: proto.Uint64(3),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(2), Length: proto.Uint32(7)},
},
PositiveDelta: []int64{2, -2, 2, -2, 0, 1, 0},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by reset",
observations: []float64{0, 1, 1.1, 1.2, 1.4, 1.8, 2, 3, 4},
factor: 1.2,
maxBuckets: 4,
maxZeroThreshold: 1.2,
minResetDuration: 5 * time.Minute,
want: &dto.Histogram{
SampleCount: proto.Uint64(2),
SampleSum: proto.Float64(7),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(0),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(7), Length: proto.Uint32(2)},
},
PositiveDelta: []int64{1, 0},
CreatedTimestamp: timestamppb.New(now.Add(8 * time.Minute)), // We expect reset to happen after 8 observations.
},
},
{
name: "limited buckets but nothing triggered, negative observations",
observations: []float64{0, -1, -1.2, -1.4, -1.8, -2},
factor: 1.2,
maxBuckets: 4,
want: &dto.Histogram{
SampleCount: proto.Uint64(6),
SampleSum: proto.Float64(-7.4),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
NegativeDelta: []int64{1, -1, 2, -2, 2},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by halving resolution, negative observations",
observations: []float64{0, -1, -1.1, -1.2, -1.4, -1.8, -2, -3},
factor: 1.2,
maxBuckets: 4,
want: &dto.Histogram{
SampleCount: proto.Uint64(8),
SampleSum: proto.Float64(-11.5),
Schema: proto.Int32(1),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(1),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(0), Length: proto.Uint32(5)},
},
NegativeDelta: []int64{1, 2, -1, -2, 1},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by widening the zero bucket, negative observations",
observations: []float64{0, -1, -1.1, -1.2, -1.4, -1.8, -2, -3},
factor: 1.2,
maxBuckets: 4,
maxZeroThreshold: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(8),
SampleSum: proto.Float64(-11.5),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(1),
ZeroCount: proto.Uint64(2),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(1), Length: proto.Uint32(7)},
},
NegativeDelta: []int64{1, 1, -2, 2, -2, 0, 1},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by widening the zero bucket twice, negative observations",
observations: []float64{0, -1, -1.1, -1.2, -1.4, -1.8, -2, -3, -4},
factor: 1.2,
maxBuckets: 4,
maxZeroThreshold: 1.2,
want: &dto.Histogram{
SampleCount: proto.Uint64(9),
SampleSum: proto.Float64(-15.5),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(1.189207115002721),
ZeroCount: proto.Uint64(3),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(2), Length: proto.Uint32(7)},
},
NegativeDelta: []int64{2, -2, 2, -2, 0, 1, 0},
CreatedTimestamp: timestamppb.New(now),
},
},
{
name: "buckets limited by reset, negative observations",
observations: []float64{0, -1, -1.1, -1.2, -1.4, -1.8, -2, -3, -4},
factor: 1.2,
maxBuckets: 4,
maxZeroThreshold: 1.2,
minResetDuration: 5 * time.Minute,
want: &dto.Histogram{
SampleCount: proto.Uint64(2),
SampleSum: proto.Float64(-7),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(0),
NegativeSpan: []*dto.BucketSpan{
{Offset: proto.Int32(7), Length: proto.Uint32(2)},
},
NegativeDelta: []int64{1, 0},
CreatedTimestamp: timestamppb.New(now.Add(8 * time.Minute)), // We expect reset to happen after 8 observations.
},
},
{
name: "buckets limited by halving resolution, then reset",
observations: []float64{0, 1, 1.1, 1.2, 1.4, 1.8, 2, 5, 5.1, 3, 4},
factor: 1.2,
maxBuckets: 4,
minResetDuration: 9 * time.Minute,
want: &dto.Histogram{
SampleCount: proto.Uint64(3),
SampleSum: proto.Float64(12.1),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(0),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(7), Length: proto.Uint32(4)},
},
PositiveDelta: []int64{1, 0, -1, 1},
CreatedTimestamp: timestamppb.New(now.Add(9 * time.Minute)), // We expect reset to happen after 8 minutes.
},
},
{
name: "buckets limited by widening the zero bucket, then reset",
observations: []float64{0, 1, 1.1, 1.2, 1.4, 1.8, 2, 5, 5.1, 3, 4},
factor: 1.2,
maxBuckets: 4,
maxZeroThreshold: 1.2,
minResetDuration: 9 * time.Minute,
want: &dto.Histogram{
SampleCount: proto.Uint64(3),
SampleSum: proto.Float64(12.1),
Schema: proto.Int32(2),
ZeroThreshold: proto.Float64(2.938735877055719e-39),
ZeroCount: proto.Uint64(0),
PositiveSpan: []*dto.BucketSpan{
{Offset: proto.Int32(7), Length: proto.Uint32(4)},
},
PositiveDelta: []int64{1, 0, -1, 1},
CreatedTimestamp: timestamppb.New(now.Add(9 * time.Minute)), // We expect reset to happen after 8 minutes.
},
},
}
for _, s := range scenarios {
t.Run(s.name, func(t *testing.T) {
var (
ts = now
funcToCall func()
whenToCall time.Duration
)
his := NewHistogram(HistogramOpts{
Name: "name",
Help: "help",
NativeHistogramBucketFactor: s.factor,
NativeHistogramZeroThreshold: s.zeroThreshold,
NativeHistogramMaxBucketNumber: s.maxBuckets,
NativeHistogramMinResetDuration: s.minResetDuration,
NativeHistogramMaxZeroThreshold: s.maxZeroThreshold,
now: func() time.Time { return ts },
afterFunc: func(d time.Duration, f func()) *time.Timer {
funcToCall = f
whenToCall = d
return nil
},
})
ts = ts.Add(time.Minute)
for _, o := range s.observations {
his.Observe(o)
ts = ts.Add(time.Minute)
whenToCall -= time.Minute
if funcToCall != nil && whenToCall <= 0 {
funcToCall()
funcToCall = nil
}
}
_his := his.(*histogram)
n := atomic.LoadUint64(&_his.countAndHotIdx)
hotIdx := n >> 63
cold := _his.counts[hotIdx]
consthist, err := NewConstNativeHistogram(_his.Desc(),
cold.count,
math.Float64frombits(cold.sumBits),
syncMapToMap(&cold.nativeHistogramBucketsPositive),
syncMapToMap(&cold.nativeHistogramBucketsNegative),
cold.nativeHistogramZeroBucket,
cold.nativeHistogramSchema,
math.Float64frombits(cold.nativeHistogramZeroThresholdBits),
_his.lastResetTime,
)
if err != nil {
t.Fatal("unexpected error writing metric", err)
}
m2 := &dto.Metric{}
if err := consthist.Write(m2); err != nil {
t.Fatal("unexpected error writing metric", err)
}
got := m2.Histogram
if !proto.Equal(s.want, got) {
t.Errorf("want histogram %q, got %q", s.want, got)
}
})
}
}