mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Fixed the issue/bug of diff and percent_diff functions *Breaking change* (#21338)
fixes #16270 #10129
This commit is contained in:
parent
0606555ba1
commit
066d5cf4da
@ -96,8 +96,12 @@ func (s *queryReducer) Reduce(series *tsdb.TimeSeries) null.Float {
|
|||||||
}
|
}
|
||||||
case "diff":
|
case "diff":
|
||||||
allNull, value = calculateDiff(series, allNull, value, diff)
|
allNull, value = calculateDiff(series, allNull, value, diff)
|
||||||
|
case "diff_abs":
|
||||||
|
allNull, value = calculateDiff(series, allNull, value, diffAbs)
|
||||||
case "percent_diff":
|
case "percent_diff":
|
||||||
allNull, value = calculateDiff(series, allNull, value, percentDiff)
|
allNull, value = calculateDiff(series, allNull, value, percentDiff)
|
||||||
|
case "percent_diff_abs":
|
||||||
|
allNull, value = calculateDiff(series, allNull, value, percentDiffAbs)
|
||||||
case "count_non_null":
|
case "count_non_null":
|
||||||
for _, v := range series.Points {
|
for _, v := range series.Points {
|
||||||
if isValid(v[0]) {
|
if isValid(v[0]) {
|
||||||
@ -141,8 +145,7 @@ func calculateDiff(series *tsdb.TimeSeries, allNull bool, value float64, fn func
|
|||||||
for i := 0; i < len(points); i++ {
|
for i := 0; i < len(points); i++ {
|
||||||
if isValid(points[i][0]) {
|
if isValid(points[i][0]) {
|
||||||
allNull = false
|
allNull = false
|
||||||
val := fn(first, points[i][0].Float64)
|
value = fn(first, points[i][0].Float64)
|
||||||
value = math.Abs(val)
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,6 +161,14 @@ var diff = func(newest, oldest float64) float64 {
|
|||||||
return newest - oldest
|
return newest - oldest
|
||||||
}
|
}
|
||||||
|
|
||||||
var percentDiff = func(newest, oldest float64) float64 {
|
var diffAbs = func(newest, oldest float64) float64 {
|
||||||
return (newest - oldest) / oldest * 100
|
return math.Abs(newest - oldest)
|
||||||
|
}
|
||||||
|
|
||||||
|
var percentDiff = func(newest, oldest float64) float64 {
|
||||||
|
return (newest - oldest) / math.Abs(oldest) * 100
|
||||||
|
}
|
||||||
|
|
||||||
|
var percentDiffAbs = func(newest, oldest float64) float64 {
|
||||||
|
return math.Abs((newest - oldest) / oldest * 100)
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ func TestSimpleReducer(t *testing.T) {
|
|||||||
Convey("median should ignore null values", func() {
|
Convey("median should ignore null values", func() {
|
||||||
reducer := newSimpleReducer("median")
|
reducer := newSimpleReducer("median")
|
||||||
series := &tsdb.TimeSeries{
|
series := &tsdb.TimeSeries{
|
||||||
Name: "test time serie",
|
Name: "test time series",
|
||||||
}
|
}
|
||||||
|
|
||||||
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 1))
|
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 1))
|
||||||
@ -79,7 +79,7 @@ func TestSimpleReducer(t *testing.T) {
|
|||||||
Convey("avg with only nulls", func() {
|
Convey("avg with only nulls", func() {
|
||||||
reducer := newSimpleReducer("avg")
|
reducer := newSimpleReducer("avg")
|
||||||
series := &tsdb.TimeSeries{
|
series := &tsdb.TimeSeries{
|
||||||
Name: "test time serie",
|
Name: "test time series",
|
||||||
}
|
}
|
||||||
|
|
||||||
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 1))
|
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 1))
|
||||||
@ -90,7 +90,7 @@ func TestSimpleReducer(t *testing.T) {
|
|||||||
Convey("with null values and real values", func() {
|
Convey("with null values and real values", func() {
|
||||||
reducer := newSimpleReducer("count_non_null")
|
reducer := newSimpleReducer("count_non_null")
|
||||||
series := &tsdb.TimeSeries{
|
series := &tsdb.TimeSeries{
|
||||||
Name: "test time serie",
|
Name: "test time series",
|
||||||
}
|
}
|
||||||
|
|
||||||
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 1))
|
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 1))
|
||||||
@ -105,7 +105,7 @@ func TestSimpleReducer(t *testing.T) {
|
|||||||
Convey("with null values", func() {
|
Convey("with null values", func() {
|
||||||
reducer := newSimpleReducer("count_non_null")
|
reducer := newSimpleReducer("count_non_null")
|
||||||
series := &tsdb.TimeSeries{
|
series := &tsdb.TimeSeries{
|
||||||
Name: "test time serie",
|
Name: "test time series",
|
||||||
}
|
}
|
||||||
|
|
||||||
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 1))
|
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 1))
|
||||||
@ -118,7 +118,7 @@ func TestSimpleReducer(t *testing.T) {
|
|||||||
Convey("avg of number values and null values should ignore nulls", func() {
|
Convey("avg of number values and null values should ignore nulls", func() {
|
||||||
reducer := newSimpleReducer("avg")
|
reducer := newSimpleReducer("avg")
|
||||||
series := &tsdb.TimeSeries{
|
series := &tsdb.TimeSeries{
|
||||||
Name: "test time serie",
|
Name: "test time series",
|
||||||
}
|
}
|
||||||
|
|
||||||
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFrom(3), 1))
|
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFrom(3), 1))
|
||||||
@ -129,25 +129,61 @@ func TestSimpleReducer(t *testing.T) {
|
|||||||
So(reducer.Reduce(series).Float64, ShouldEqual, float64(3))
|
So(reducer.Reduce(series).Float64, ShouldEqual, float64(3))
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("diff one point", func() {
|
// diff function Test Suite
|
||||||
|
Convey("diff of one positive point", func() {
|
||||||
result := testReducer("diff", 30)
|
result := testReducer("diff", 30)
|
||||||
So(result, ShouldEqual, float64(0))
|
So(result, ShouldEqual, float64(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("diff two points", func() {
|
Convey("diff of one negative point", func() {
|
||||||
|
result := testReducer("diff", -30)
|
||||||
|
So(result, ShouldEqual, float64(0))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff of two positive points[1]", func() {
|
||||||
result := testReducer("diff", 30, 40)
|
result := testReducer("diff", 30, 40)
|
||||||
So(result, ShouldEqual, float64(10))
|
So(result, ShouldEqual, float64(10))
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("diff three points", func() {
|
Convey("diff of two positive points[2]", func() {
|
||||||
result := testReducer("diff", 30, 40, 40)
|
result := testReducer("diff", 30, 20)
|
||||||
So(result, ShouldEqual, float64(10))
|
So(result, ShouldEqual, float64(-10))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff of two negative points[1]", func() {
|
||||||
|
result := testReducer("diff", -30, -40)
|
||||||
|
So(result, ShouldEqual, float64(-10))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff of two negative points[2]", func() {
|
||||||
|
result := testReducer("diff", -30, -10)
|
||||||
|
So(result, ShouldEqual, float64(20))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff of one positive and one negative point", func() {
|
||||||
|
result := testReducer("diff", 30, -40)
|
||||||
|
So(result, ShouldEqual, float64(-70))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff of one negative and one positive point", func() {
|
||||||
|
result := testReducer("diff", -30, 40)
|
||||||
|
So(result, ShouldEqual, float64(70))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff of three positive points", func() {
|
||||||
|
result := testReducer("diff", 30, 40, 50)
|
||||||
|
So(result, ShouldEqual, float64(20))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff of three negative points", func() {
|
||||||
|
result := testReducer("diff", -30, -40, -50)
|
||||||
|
So(result, ShouldEqual, float64(-20))
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("diff with only nulls", func() {
|
Convey("diff with only nulls", func() {
|
||||||
reducer := newSimpleReducer("diff")
|
reducer := newSimpleReducer("diff")
|
||||||
series := &tsdb.TimeSeries{
|
series := &tsdb.TimeSeries{
|
||||||
Name: "test time serie",
|
Name: "test time series",
|
||||||
}
|
}
|
||||||
|
|
||||||
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 1))
|
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 1))
|
||||||
@ -156,25 +192,187 @@ func TestSimpleReducer(t *testing.T) {
|
|||||||
So(reducer.Reduce(series).Valid, ShouldEqual, false)
|
So(reducer.Reduce(series).Valid, ShouldEqual, false)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("percent_diff one point", func() {
|
// diff_abs function Test Suite
|
||||||
result := testReducer("percent_diff", 40)
|
Convey("diff_abs of one positive point", func() {
|
||||||
|
result := testReducer("diff_abs", 30)
|
||||||
So(result, ShouldEqual, float64(0))
|
So(result, ShouldEqual, float64(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("percent_diff two points", func() {
|
Convey("diff_abs of one negative point", func() {
|
||||||
|
result := testReducer("diff_abs", -30)
|
||||||
|
So(result, ShouldEqual, float64(0))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff_abs of two positive points[1]", func() {
|
||||||
|
result := testReducer("diff_abs", 30, 40)
|
||||||
|
So(result, ShouldEqual, float64(10))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff_abs of two positive points[2]", func() {
|
||||||
|
result := testReducer("diff_abs", 30, 20)
|
||||||
|
So(result, ShouldEqual, float64(10))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff_abs of two negative points[1]", func() {
|
||||||
|
result := testReducer("diff_abs", -30, -40)
|
||||||
|
So(result, ShouldEqual, float64(10))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff_abs of two negative points[2]", func() {
|
||||||
|
result := testReducer("diff_abs", -30, -10)
|
||||||
|
So(result, ShouldEqual, float64(20))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff_abs of one positive and one negative point", func() {
|
||||||
|
result := testReducer("diff_abs", 30, -40)
|
||||||
|
So(result, ShouldEqual, float64(70))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff_abs of one negative and one positive point", func() {
|
||||||
|
result := testReducer("diff_abs", -30, 40)
|
||||||
|
So(result, ShouldEqual, float64(70))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff_abs of three positive points", func() {
|
||||||
|
result := testReducer("diff_abs", 30, 40, 50)
|
||||||
|
So(result, ShouldEqual, float64(20))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff_abs of three negative points", func() {
|
||||||
|
result := testReducer("diff_abs", -30, -40, -50)
|
||||||
|
So(result, ShouldEqual, float64(20))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("diff_abs with only nulls", func() {
|
||||||
|
reducer := newSimpleReducer("diff_abs")
|
||||||
|
series := &tsdb.TimeSeries{
|
||||||
|
Name: "test time series",
|
||||||
|
}
|
||||||
|
|
||||||
|
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 1))
|
||||||
|
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 2))
|
||||||
|
|
||||||
|
So(reducer.Reduce(series).Valid, ShouldEqual, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
// percent_diff function Test Suite
|
||||||
|
Convey("percent_diff of one positive point", func() {
|
||||||
|
result := testReducer("percent_diff", 30)
|
||||||
|
So(result, ShouldEqual, float64(0))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff of one negative point", func() {
|
||||||
|
result := testReducer("percent_diff", -30)
|
||||||
|
So(result, ShouldEqual, float64(0))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff of two positive points[1]", func() {
|
||||||
result := testReducer("percent_diff", 30, 40)
|
result := testReducer("percent_diff", 30, 40)
|
||||||
So(result, ShouldEqual, float64(33.33333333333333))
|
So(result, ShouldEqual, float64(33.33333333333333))
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("percent_diff three points", func() {
|
Convey("percent_diff of two positive points[2]", func() {
|
||||||
result := testReducer("percent_diff", 30, 40, 40)
|
result := testReducer("percent_diff", 30, 20)
|
||||||
So(result, ShouldEqual, float64(33.33333333333333))
|
So(result, ShouldEqual, float64(-33.33333333333333))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff of two negative points[1]", func() {
|
||||||
|
result := testReducer("percent_diff", -30, -40)
|
||||||
|
So(result, ShouldEqual, float64(-33.33333333333333))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff of two negative points[2]", func() {
|
||||||
|
result := testReducer("percent_diff", -30, -10)
|
||||||
|
So(result, ShouldEqual, float64(66.66666666666666))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff of one positive and one negative point", func() {
|
||||||
|
result := testReducer("percent_diff", 30, -40)
|
||||||
|
So(result, ShouldEqual, float64(-233.33333333333334))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff of one negative and one positive point", func() {
|
||||||
|
result := testReducer("percent_diff", -30, 40)
|
||||||
|
So(result, ShouldEqual, float64(233.33333333333334))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff of three positive points", func() {
|
||||||
|
result := testReducer("percent_diff", 30, 40, 50)
|
||||||
|
So(result, ShouldEqual, float64(66.66666666666666))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff of three negative points", func() {
|
||||||
|
result := testReducer("percent_diff", -30, -40, -50)
|
||||||
|
So(result, ShouldEqual, float64(-66.66666666666666))
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("percent_diff with only nulls", func() {
|
Convey("percent_diff with only nulls", func() {
|
||||||
reducer := newSimpleReducer("percent_diff")
|
reducer := newSimpleReducer("percent_diff")
|
||||||
series := &tsdb.TimeSeries{
|
series := &tsdb.TimeSeries{
|
||||||
Name: "test time serie",
|
Name: "test time series",
|
||||||
|
}
|
||||||
|
|
||||||
|
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 1))
|
||||||
|
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 2))
|
||||||
|
|
||||||
|
So(reducer.Reduce(series).Valid, ShouldEqual, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
// percent_diff_abs function Test Suite
|
||||||
|
Convey("percent_diff_abs_abs of one positive point", func() {
|
||||||
|
result := testReducer("percent_diff_abs", 30)
|
||||||
|
So(result, ShouldEqual, float64(0))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff_abs of one negative point", func() {
|
||||||
|
result := testReducer("percent_diff_abs", -30)
|
||||||
|
So(result, ShouldEqual, float64(0))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff_abs of two positive points[1]", func() {
|
||||||
|
result := testReducer("percent_diff_abs", 30, 40)
|
||||||
|
So(result, ShouldEqual, float64(33.33333333333333))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff_abs of two positive points[2]", func() {
|
||||||
|
result := testReducer("percent_diff_abs", 30, 20)
|
||||||
|
So(result, ShouldEqual, float64(33.33333333333333))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff_abs of two negative points[1]", func() {
|
||||||
|
result := testReducer("percent_diff_abs", -30, -40)
|
||||||
|
So(result, ShouldEqual, float64(33.33333333333333))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff_abs of two negative points[2]", func() {
|
||||||
|
result := testReducer("percent_diff_abs", -30, -10)
|
||||||
|
So(result, ShouldEqual, float64(66.66666666666666))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff_abs of one positive and one negative point", func() {
|
||||||
|
result := testReducer("percent_diff_abs", 30, -40)
|
||||||
|
So(result, ShouldEqual, float64(233.33333333333334))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff_abs of one negative and one positive point", func() {
|
||||||
|
result := testReducer("percent_diff_abs", -30, 40)
|
||||||
|
So(result, ShouldEqual, float64(233.33333333333334))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff_abs of three positive points", func() {
|
||||||
|
result := testReducer("percent_diff_abs", 30, 40, 50)
|
||||||
|
So(result, ShouldEqual, float64(66.66666666666666))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff_abs of three negative points", func() {
|
||||||
|
result := testReducer("percent_diff_abs", -30, -40, -50)
|
||||||
|
So(result, ShouldEqual, float64(66.66666666666666))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("percent_diff_abs with only nulls", func() {
|
||||||
|
reducer := newSimpleReducer("percent_diff_abs")
|
||||||
|
series := &tsdb.TimeSeries{
|
||||||
|
Name: "test time series",
|
||||||
}
|
}
|
||||||
|
|
||||||
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 1))
|
series.Points = append(series.Points, tsdb.NewTimePoint(null.FloatFromPtr(nil), 1))
|
||||||
@ -203,7 +401,7 @@ func TestSimpleReducer(t *testing.T) {
|
|||||||
func testReducer(reducerType string, datapoints ...float64) float64 {
|
func testReducer(reducerType string, datapoints ...float64) float64 {
|
||||||
reducer := newSimpleReducer(reducerType)
|
reducer := newSimpleReducer(reducerType)
|
||||||
series := &tsdb.TimeSeries{
|
series := &tsdb.TimeSeries{
|
||||||
Name: "test time serie",
|
Name: "test time series",
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx := range datapoints {
|
for idx := range datapoints {
|
||||||
|
@ -47,7 +47,9 @@ const reducerTypes = [
|
|||||||
{ text: 'last()', value: 'last' },
|
{ text: 'last()', value: 'last' },
|
||||||
{ text: 'median()', value: 'median' },
|
{ text: 'median()', value: 'median' },
|
||||||
{ text: 'diff()', value: 'diff' },
|
{ text: 'diff()', value: 'diff' },
|
||||||
|
{ text: 'diff_abs()', value: 'diff_abs' },
|
||||||
{ text: 'percent_diff()', value: 'percent_diff' },
|
{ text: 'percent_diff()', value: 'percent_diff' },
|
||||||
|
{ text: 'percent_diff_abs()', value: 'percent_diff_abs' },
|
||||||
{ text: 'count_non_null()', value: 'count_non_null' },
|
{ text: 'count_non_null()', value: 'count_non_null' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user