@ -19,7 +19,6 @@ import (
"fmt"
"math"
"sort"
"strconv"
"strings"
"sync"
"testing"
@ -39,7 +38,6 @@ import (
"github.com/prometheus/prometheus/tsdb/chunkenc"
"github.com/prometheus/prometheus/util/annotations"
"github.com/prometheus/prometheus/util/stats"
"github.com/prometheus/prometheus/util/teststorage"
"github.com/prometheus/prometheus/util/testutil"
)
@ -3150,452 +3148,6 @@ func TestInstantQueryWithRangeVectorSelector(t *testing.T) {
}
}
func TestNativeHistogram_Sum_Count_Add_AvgOperator ( t * testing . T ) {
// TODO(codesome): Integrate histograms into the PromQL testing framework
// and write more tests there.
cases := [ ] struct {
histograms [ ] histogram . Histogram
expected histogram . FloatHistogram
expectedAvg histogram . FloatHistogram
} {
{
histograms : [ ] histogram . Histogram {
{
CounterResetHint : histogram . GaugeType ,
Schema : 0 ,
Count : 25 ,
Sum : 1234.5 ,
ZeroThreshold : 0.001 ,
ZeroCount : 4 ,
PositiveSpans : [ ] histogram . Span {
{ Offset : 0 , Length : 2 } ,
{ Offset : 1 , Length : 2 } ,
} ,
PositiveBuckets : [ ] int64 { 1 , 1 , - 1 , 0 } ,
NegativeSpans : [ ] histogram . Span {
{ Offset : 0 , Length : 2 } ,
{ Offset : 2 , Length : 2 } ,
} ,
NegativeBuckets : [ ] int64 { 2 , 2 , - 3 , 8 } ,
} ,
{
CounterResetHint : histogram . GaugeType ,
Schema : 0 ,
Count : 41 ,
Sum : 2345.6 ,
ZeroThreshold : 0.001 ,
ZeroCount : 5 ,
PositiveSpans : [ ] histogram . Span {
{ Offset : 0 , Length : 4 } ,
{ Offset : 0 , Length : 0 } ,
{ Offset : 0 , Length : 3 } ,
} ,
PositiveBuckets : [ ] int64 { 1 , 2 , - 2 , 1 , - 1 , 0 , 0 } ,
NegativeSpans : [ ] histogram . Span {
{ Offset : 1 , Length : 4 } ,
{ Offset : 2 , Length : 0 } ,
{ Offset : 2 , Length : 3 } ,
} ,
NegativeBuckets : [ ] int64 { 1 , 3 , - 2 , 5 , - 2 , 0 , - 3 } ,
} ,
{
CounterResetHint : histogram . GaugeType ,
Schema : 0 ,
Count : 41 ,
Sum : 1111.1 ,
ZeroThreshold : 0.001 ,
ZeroCount : 5 ,
PositiveSpans : [ ] histogram . Span {
{ Offset : 0 , Length : 4 } ,
{ Offset : 0 , Length : 0 } ,
{ Offset : 0 , Length : 3 } ,
} ,
PositiveBuckets : [ ] int64 { 1 , 2 , - 2 , 1 , - 1 , 0 , 0 } ,
NegativeSpans : [ ] histogram . Span {
{ Offset : 1 , Length : 4 } ,
{ Offset : 2 , Length : 0 } ,
{ Offset : 2 , Length : 3 } ,
} ,
NegativeBuckets : [ ] int64 { 1 , 3 , - 2 , 5 , - 2 , 0 , - 3 } ,
} ,
{
CounterResetHint : histogram . GaugeType ,
Schema : 1 , // Everything is 0 just to make the count 4 so avg has nicer numbers.
} ,
} ,
expected : histogram . FloatHistogram {
CounterResetHint : histogram . GaugeType ,
Schema : 0 ,
ZeroThreshold : 0.001 ,
ZeroCount : 14 ,
Count : 107 ,
Sum : 4691.2 ,
PositiveSpans : [ ] histogram . Span {
{ Offset : 0 , Length : 7 } ,
} ,
PositiveBuckets : [ ] float64 { 3 , 8 , 2 , 5 , 3 , 2 , 2 } ,
NegativeSpans : [ ] histogram . Span {
{ Offset : 0 , Length : 6 } ,
{ Offset : 3 , Length : 3 } ,
} ,
NegativeBuckets : [ ] float64 { 2 , 6 , 8 , 4 , 15 , 9 , 10 , 10 , 4 } ,
} ,
expectedAvg : histogram . FloatHistogram {
CounterResetHint : histogram . GaugeType ,
Schema : 0 ,
ZeroThreshold : 0.001 ,
ZeroCount : 3.5 ,
Count : 26.75 ,
Sum : 1172.8 ,
PositiveSpans : [ ] histogram . Span {
{ Offset : 0 , Length : 7 } ,
} ,
PositiveBuckets : [ ] float64 { 0.75 , 2 , 0.5 , 1.25 , 0.75 , 0.5 , 0.5 } ,
NegativeSpans : [ ] histogram . Span {
{ Offset : 0 , Length : 6 } ,
{ Offset : 3 , Length : 3 } ,
} ,
NegativeBuckets : [ ] float64 { 0.5 , 1.5 , 2 , 1 , 3.75 , 2.25 , 2.5 , 2.5 , 1 } ,
} ,
} ,
}
idx0 := int64 ( 0 )
for _ , c := range cases {
for _ , floatHisto := range [ ] bool { true , false } {
t . Run ( fmt . Sprintf ( "floatHistogram=%t %d" , floatHisto , idx0 ) , func ( t * testing . T ) {
storage := teststorage . New ( t )
t . Cleanup ( func ( ) { storage . Close ( ) } )
seriesName := "sparse_histogram_series"
seriesNameOverTime := "sparse_histogram_series_over_time"
engine := newTestEngine ( t )
ts := idx0 * int64 ( 10 * time . Minute / time . Millisecond )
app := storage . Appender ( context . Background ( ) )
_ , err := app . Append ( 0 , labels . FromStrings ( "__name__" , "float_series" , "idx" , "0" ) , ts , 42 )
require . NoError ( t , err )
for idx1 , h := range c . histograms {
lbls := labels . FromStrings ( "__name__" , seriesName , "idx" , strconv . Itoa ( idx1 ) )
// Since we mutate h later, we need to create a copy here.
var err error
if floatHisto {
_ , err = app . AppendHistogram ( 0 , lbls , ts , nil , h . Copy ( ) . ToFloat ( nil ) )
} else {
_ , err = app . AppendHistogram ( 0 , lbls , ts , h . Copy ( ) , nil )
}
require . NoError ( t , err )
lbls = labels . FromStrings ( "__name__" , seriesNameOverTime )
newTs := ts + int64 ( idx1 ) * int64 ( time . Minute / time . Millisecond )
// Since we mutate h later, we need to create a copy here.
if floatHisto {
_ , err = app . AppendHistogram ( 0 , lbls , newTs , nil , h . Copy ( ) . ToFloat ( nil ) )
} else {
_ , err = app . AppendHistogram ( 0 , lbls , newTs , h . Copy ( ) , nil )
}
require . NoError ( t , err )
}
require . NoError ( t , app . Commit ( ) )
queryAndCheck := func ( queryString string , ts int64 , exp promql . Vector ) {
qry , err := engine . NewInstantQuery ( context . Background ( ) , storage , nil , queryString , timestamp . Time ( ts ) )
require . NoError ( t , err )
res := qry . Exec ( context . Background ( ) )
require . NoError ( t , res . Err )
require . Empty ( t , res . Warnings )
vector , err := res . Vector ( )
require . NoError ( t , err )
testutil . RequireEqual ( t , exp , vector )
}
queryAndCheckAnnotations := func ( queryString string , ts int64 , expWarnings annotations . Annotations ) {
qry , err := engine . NewInstantQuery ( context . Background ( ) , storage , nil , queryString , timestamp . Time ( ts ) )
require . NoError ( t , err )
res := qry . Exec ( context . Background ( ) )
require . NoError ( t , res . Err )
require . Equal ( t , expWarnings , res . Warnings )
}
// sum().
queryString := fmt . Sprintf ( "sum(%s)" , seriesName )
queryAndCheck ( queryString , ts , [ ] promql . Sample { { T : ts , H : & c . expected , Metric : labels . EmptyLabels ( ) } } )
queryString = ` sum( { idx="0"}) `
var annos annotations . Annotations
annos . Add ( annotations . NewMixedFloatsHistogramsAggWarning ( posrange . PositionRange { Start : 4 , End : 13 } ) )
queryAndCheckAnnotations ( queryString , ts , annos )
// + operator.
queryString = fmt . Sprintf ( ` %s { idx="0"} ` , seriesName )
for idx := 1 ; idx < len ( c . histograms ) ; idx ++ {
queryString += fmt . Sprintf ( ` + ignoring(idx) %s { idx="%d"} ` , seriesName , idx )
}
queryAndCheck ( queryString , ts , [ ] promql . Sample { { T : ts , H : & c . expected , Metric : labels . EmptyLabels ( ) } } )
// count().
queryString = fmt . Sprintf ( "count(%s)" , seriesName )
queryAndCheck ( queryString , ts , [ ] promql . Sample { { T : ts , F : 4 , Metric : labels . EmptyLabels ( ) } } )
// avg().
queryString = fmt . Sprintf ( "avg(%s)" , seriesName )
queryAndCheck ( queryString , ts , [ ] promql . Sample { { T : ts , H : & c . expectedAvg , Metric : labels . EmptyLabels ( ) } } )
offset := int64 ( len ( c . histograms ) - 1 )
newTs := ts + offset * int64 ( time . Minute / time . Millisecond )
// sum_over_time().
queryString = fmt . Sprintf ( "sum_over_time(%s[%dm:1m])" , seriesNameOverTime , offset + 1 )
queryAndCheck ( queryString , newTs , [ ] promql . Sample { { T : newTs , H : & c . expected , Metric : labels . EmptyLabels ( ) , DropName : true } } )
// avg_over_time().
queryString = fmt . Sprintf ( "avg_over_time(%s[%dm:1m])" , seriesNameOverTime , offset + 1 )
queryAndCheck ( queryString , newTs , [ ] promql . Sample { { T : newTs , H : & c . expectedAvg , Metric : labels . EmptyLabels ( ) , DropName : true } } )
} )
idx0 ++
}
}
}
func TestNativeHistogram_SubOperator ( t * testing . T ) {
// TODO(codesome): Integrate histograms into the PromQL testing framework
// and write more tests there.
cases := [ ] struct {
histograms [ ] histogram . Histogram
expected histogram . FloatHistogram
} {
{
histograms : [ ] histogram . Histogram {
{
Schema : 0 ,
Count : 41 ,
Sum : 2345.6 ,
ZeroThreshold : 0.001 ,
ZeroCount : 5 ,
PositiveSpans : [ ] histogram . Span {
{ Offset : 0 , Length : 4 } ,
{ Offset : 0 , Length : 0 } ,
{ Offset : 0 , Length : 3 } ,
} ,
PositiveBuckets : [ ] int64 { 1 , 2 , - 2 , 1 , - 1 , 0 , 0 } ,
NegativeSpans : [ ] histogram . Span {
{ Offset : 1 , Length : 4 } ,
{ Offset : 2 , Length : 0 } ,
{ Offset : 2 , Length : 3 } ,
} ,
NegativeBuckets : [ ] int64 { 1 , 3 , - 2 , 5 , - 2 , 0 , - 3 } ,
} ,
{
Schema : 0 ,
Count : 11 ,
Sum : 1234.5 ,
ZeroThreshold : 0.001 ,
ZeroCount : 3 ,
PositiveSpans : [ ] histogram . Span {
{ Offset : 1 , Length : 2 } ,
} ,
PositiveBuckets : [ ] int64 { 2 , - 1 } ,
NegativeSpans : [ ] histogram . Span {
{ Offset : 2 , Length : 2 } ,
} ,
NegativeBuckets : [ ] int64 { 3 , - 1 } ,
} ,
} ,
expected : histogram . FloatHistogram {
Schema : 0 ,
Count : 30 ,
Sum : 1111.1 ,
ZeroThreshold : 0.001 ,
ZeroCount : 2 ,
PositiveSpans : [ ] histogram . Span {
{ Offset : 0 , Length : 2 } ,
{ Offset : 1 , Length : 4 } ,
} ,
PositiveBuckets : [ ] float64 { 1 , 1 , 2 , 1 , 1 , 1 } ,
NegativeSpans : [ ] histogram . Span {
{ Offset : 1 , Length : 2 } ,
{ Offset : 1 , Length : 1 } ,
{ Offset : 4 , Length : 3 } ,
} ,
NegativeBuckets : [ ] float64 { 1 , 1 , 7 , 5 , 5 , 2 } ,
} ,
} ,
{
histograms : [ ] histogram . Histogram {
{
Schema : 0 ,
Count : 41 ,
Sum : 2345.6 ,
ZeroThreshold : 0.001 ,
ZeroCount : 5 ,
PositiveSpans : [ ] histogram . Span {
{ Offset : 0 , Length : 4 } ,
{ Offset : 0 , Length : 0 } ,
{ Offset : 0 , Length : 3 } ,
} ,
PositiveBuckets : [ ] int64 { 1 , 2 , - 2 , 1 , - 1 , 0 , 0 } ,
NegativeSpans : [ ] histogram . Span {
{ Offset : 1 , Length : 4 } ,
{ Offset : 2 , Length : 0 } ,
{ Offset : 2 , Length : 3 } ,
} ,
NegativeBuckets : [ ] int64 { 1 , 3 , - 2 , 5 , - 2 , 0 , - 3 } ,
} ,
{
Schema : 1 ,
Count : 11 ,
Sum : 1234.5 ,
ZeroThreshold : 0.001 ,
ZeroCount : 3 ,
PositiveSpans : [ ] histogram . Span {
{ Offset : 1 , Length : 2 } ,
} ,
PositiveBuckets : [ ] int64 { 2 , - 1 } ,
NegativeSpans : [ ] histogram . Span {
{ Offset : 2 , Length : 2 } ,
} ,
NegativeBuckets : [ ] int64 { 3 , - 1 } ,
} ,
} ,
expected : histogram . FloatHistogram {
Schema : 0 ,
Count : 30 ,
Sum : 1111.1 ,
ZeroThreshold : 0.001 ,
ZeroCount : 2 ,
PositiveSpans : [ ] histogram . Span {
{ Offset : 0 , Length : 1 } ,
{ Offset : 1 , Length : 5 } ,
} ,
PositiveBuckets : [ ] float64 { 1 , 1 , 2 , 1 , 1 , 1 } ,
NegativeSpans : [ ] histogram . Span {
{ Offset : 1 , Length : 4 } ,
{ Offset : 4 , Length : 3 } ,
} ,
NegativeBuckets : [ ] float64 { - 2 , 2 , 2 , 7 , 5 , 5 , 2 } ,
} ,
} ,
{
histograms : [ ] histogram . Histogram {
{
Schema : 1 ,
Count : 11 ,
Sum : 1234.5 ,
ZeroThreshold : 0.001 ,
ZeroCount : 3 ,
PositiveSpans : [ ] histogram . Span {
{ Offset : 1 , Length : 2 } ,
} ,
PositiveBuckets : [ ] int64 { 2 , - 1 } ,
NegativeSpans : [ ] histogram . Span {
{ Offset : 2 , Length : 2 } ,
} ,
NegativeBuckets : [ ] int64 { 3 , - 1 } ,
} ,
{
Schema : 0 ,
Count : 41 ,
Sum : 2345.6 ,
ZeroThreshold : 0.001 ,
ZeroCount : 5 ,
PositiveSpans : [ ] histogram . Span {
{ Offset : 0 , Length : 4 } ,
{ Offset : 0 , Length : 0 } ,
{ Offset : 0 , Length : 3 } ,
} ,
PositiveBuckets : [ ] int64 { 1 , 2 , - 2 , 1 , - 1 , 0 , 0 } ,
NegativeSpans : [ ] histogram . Span {
{ Offset : 1 , Length : 4 } ,
{ Offset : 2 , Length : 0 } ,
{ Offset : 2 , Length : 3 } ,
} ,
NegativeBuckets : [ ] int64 { 1 , 3 , - 2 , 5 , - 2 , 0 , - 3 } ,
} ,
} ,
expected : histogram . FloatHistogram {
Schema : 0 ,
Count : - 30 ,
Sum : - 1111.1 ,
ZeroThreshold : 0.001 ,
ZeroCount : - 2 ,
PositiveSpans : [ ] histogram . Span {
{ Offset : 0 , Length : 1 } ,
{ Offset : 1 , Length : 5 } ,
} ,
PositiveBuckets : [ ] float64 { - 1 , - 1 , - 2 , - 1 , - 1 , - 1 } ,
NegativeSpans : [ ] histogram . Span {
{ Offset : 1 , Length : 4 } ,
{ Offset : 4 , Length : 3 } ,
} ,
NegativeBuckets : [ ] float64 { 2 , - 2 , - 2 , - 7 , - 5 , - 5 , - 2 } ,
} ,
} ,
}
idx0 := int64 ( 0 )
for _ , c := range cases {
for _ , floatHisto := range [ ] bool { true , false } {
t . Run ( fmt . Sprintf ( "floatHistogram=%t %d" , floatHisto , idx0 ) , func ( t * testing . T ) {
engine := newTestEngine ( t )
storage := teststorage . New ( t )
t . Cleanup ( func ( ) { storage . Close ( ) } )
seriesName := "sparse_histogram_series"
ts := idx0 * int64 ( 10 * time . Minute / time . Millisecond )
app := storage . Appender ( context . Background ( ) )
for idx1 , h := range c . histograms {
lbls := labels . FromStrings ( "__name__" , seriesName , "idx" , strconv . Itoa ( idx1 ) )
// Since we mutate h later, we need to create a copy here.
var err error
if floatHisto {
_ , err = app . AppendHistogram ( 0 , lbls , ts , nil , h . Copy ( ) . ToFloat ( nil ) )
} else {
_ , err = app . AppendHistogram ( 0 , lbls , ts , h . Copy ( ) , nil )
}
require . NoError ( t , err )
}
require . NoError ( t , app . Commit ( ) )
queryAndCheck := func ( queryString string , exp promql . Vector ) {
qry , err := engine . NewInstantQuery ( context . Background ( ) , storage , nil , queryString , timestamp . Time ( ts ) )
require . NoError ( t , err )
res := qry . Exec ( context . Background ( ) )
require . NoError ( t , res . Err )
vector , err := res . Vector ( )
require . NoError ( t , err )
if len ( vector ) == len ( exp ) {
for i , e := range exp {
got := vector [ i ] . H
if got != e . H {
// Error messages are better if we compare structs, not pointers.
require . Equal ( t , * e . H , * got )
}
}
}
testutil . RequireEqual ( t , exp , vector )
}
// - operator.
queryString := fmt . Sprintf ( ` %s { idx="0"} ` , seriesName )
for idx := 1 ; idx < len ( c . histograms ) ; idx ++ {
queryString += fmt . Sprintf ( ` - ignoring(idx) %s { idx="%d"} ` , seriesName , idx )
}
queryAndCheck ( queryString , [ ] promql . Sample { { T : ts , H : & c . expected , Metric : labels . EmptyLabels ( ) } } )
} )
}
idx0 ++
}
}
func TestQueryLookbackDelta ( t * testing . T ) {
var (
load = ` load 5 m