Skip to content

Commit 8d58576

Browse files
committed
refactor(tsdb): changed tsdb time series model to use null.Float instead of pointers
1 parent 63caedb commit 8d58576

File tree

11 files changed

+101
-89
lines changed

11 files changed

+101
-89
lines changed

pkg/services/alerting/conditions/evaluator.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/grafana/grafana/pkg/components/simplejson"
77
"github.com/grafana/grafana/pkg/services/alerting"
8+
"gopkg.in/guregu/null.v3"
89
)
910

1011
var (
@@ -13,13 +14,13 @@ var (
1314
)
1415

1516
type AlertEvaluator interface {
16-
Eval(reducedValue *float64) bool
17+
Eval(reducedValue null.Float) bool
1718
}
1819

1920
type NoDataEvaluator struct{}
2021

21-
func (e *NoDataEvaluator) Eval(reducedValue *float64) bool {
22-
return reducedValue == nil
22+
func (e *NoDataEvaluator) Eval(reducedValue null.Float) bool {
23+
return reducedValue.Valid == false
2324
}
2425

2526
type ThresholdEvaluator struct {
@@ -43,16 +44,16 @@ func newThresholdEvaludator(typ string, model *simplejson.Json) (*ThresholdEvalu
4344
return defaultEval, nil
4445
}
4546

46-
func (e *ThresholdEvaluator) Eval(reducedValue *float64) bool {
47-
if reducedValue == nil {
47+
func (e *ThresholdEvaluator) Eval(reducedValue null.Float) bool {
48+
if reducedValue.Valid == false {
4849
return false
4950
}
5051

5152
switch e.Type {
5253
case "gt":
53-
return *reducedValue > e.Threshold
54+
return reducedValue.Float64 > e.Threshold
5455
case "lt":
55-
return *reducedValue < e.Threshold
56+
return reducedValue.Float64 < e.Threshold
5657
}
5758

5859
return false
@@ -86,16 +87,18 @@ func newRangedEvaluator(typ string, model *simplejson.Json) (*RangedEvaluator, e
8687
return rangedEval, nil
8788
}
8889

89-
func (e *RangedEvaluator) Eval(reducedValue *float64) bool {
90-
if reducedValue == nil {
90+
func (e *RangedEvaluator) Eval(reducedValue null.Float) bool {
91+
if reducedValue.Valid == false {
9192
return false
9293
}
9394

95+
floatValue := reducedValue.Float64
96+
9497
switch e.Type {
9598
case "within_range":
96-
return (e.Lower < *reducedValue && e.Upper > *reducedValue) || (e.Upper < *reducedValue && e.Lower > *reducedValue)
99+
return (e.Lower < floatValue && e.Upper > floatValue) || (e.Upper < floatValue && e.Lower > floatValue)
97100
case "outside_range":
98-
return (e.Upper < *reducedValue && e.Lower < *reducedValue) || (e.Upper > *reducedValue && e.Lower > *reducedValue)
101+
return (e.Upper < floatValue && e.Lower < floatValue) || (e.Upper > floatValue && e.Lower > floatValue)
99102
}
100103

101104
return false

pkg/services/alerting/conditions/evaluator_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package conditions
33
import (
44
"testing"
55

6+
"gopkg.in/guregu/null.v3"
7+
68
"github.com/grafana/grafana/pkg/components/simplejson"
79
. "github.com/smartystreets/goconvey/convey"
810
)
@@ -14,7 +16,7 @@ func evalutorScenario(json string, reducedValue float64, datapoints ...float64)
1416
evaluator, err := NewAlertEvaluator(jsonModel)
1517
So(err, ShouldBeNil)
1618

17-
return evaluator.Eval(&reducedValue)
19+
return evaluator.Eval(null.FloatFrom(reducedValue))
1820
}
1921

2022
func TestEvalutors(t *testing.T) {
@@ -51,6 +53,6 @@ func TestEvalutors(t *testing.T) {
5153
evaluator, err := NewAlertEvaluator(jsonModel)
5254
So(err, ShouldBeNil)
5355

54-
So(evaluator.Eval(nil), ShouldBeTrue)
56+
So(evaluator.Eval(null.FloatFromPtr(nil)), ShouldBeTrue)
5557
})
5658
}

pkg/services/alerting/conditions/query.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,21 @@ func (c *QueryCondition) Eval(context *alerting.EvalContext) {
4646
reducedValue := c.Reducer.Reduce(series)
4747
evalMatch := c.Evaluator.Eval(reducedValue)
4848

49-
if reducedValue == nil {
49+
if reducedValue.Valid == false {
5050
emptySerieCount++
5151
continue
5252
}
5353

5454
if context.IsTestRun {
5555
context.Logs = append(context.Logs, &alerting.ResultLogEntry{
56-
Message: fmt.Sprintf("Condition[%d]: Eval: %v, Metric: %s, Value: %1.3f", c.Index, evalMatch, series.Name, *reducedValue),
56+
Message: fmt.Sprintf("Condition[%d]: Eval: %v, Metric: %s, Value: %1.3f", c.Index, evalMatch, series.Name, reducedValue.Float64),
5757
})
5858
}
5959

6060
if evalMatch {
6161
context.EvalMatches = append(context.EvalMatches, &alerting.EvalMatch{
6262
Metric: series.Name,
63-
Value: *reducedValue,
63+
Value: reducedValue.Float64,
6464
})
6565
}
6666
}

pkg/services/alerting/conditions/query_test.go

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package conditions
33
import (
44
"testing"
55

6+
null "gopkg.in/guregu/null.v3"
7+
68
"github.com/grafana/grafana/pkg/bus"
79
"github.com/grafana/grafana/pkg/components/simplejson"
810
m "github.com/grafana/grafana/pkg/models"
@@ -41,31 +43,27 @@ func TestQueryCondition(t *testing.T) {
4143
})
4244

4345
Convey("should fire when avg is above 100", func() {
44-
one := float64(120)
45-
two := float64(0)
46-
ctx.series = tsdb.TimeSeriesSlice{tsdb.NewTimeSeries("test1", [][2]*float64{{&one, &two}})}
46+
points := tsdb.NewTimeSeriesPointsFromArgs(120, 0)
47+
ctx.series = tsdb.TimeSeriesSlice{tsdb.NewTimeSeries("test1", points)}
4748
ctx.exec()
4849

4950
So(ctx.result.Error, ShouldBeNil)
5051
So(ctx.result.Firing, ShouldBeTrue)
5152
})
5253

5354
Convey("Should not fire when avg is below 100", func() {
54-
one := float64(90)
55-
two := float64(0)
56-
ctx.series = tsdb.TimeSeriesSlice{tsdb.NewTimeSeries("test1", [][2]*float64{{&one, &two}})}
55+
points := tsdb.NewTimeSeriesPointsFromArgs(90, 0)
56+
ctx.series = tsdb.TimeSeriesSlice{tsdb.NewTimeSeries("test1", points)}
5757
ctx.exec()
5858

5959
So(ctx.result.Error, ShouldBeNil)
6060
So(ctx.result.Firing, ShouldBeFalse)
6161
})
6262

6363
Convey("Should fire if only first serie matches", func() {
64-
one := float64(120)
65-
two := float64(0)
6664
ctx.series = tsdb.TimeSeriesSlice{
67-
tsdb.NewTimeSeries("test1", [][2]*float64{{&one, &two}}),
68-
tsdb.NewTimeSeries("test2", [][2]*float64{{&two, &two}}),
65+
tsdb.NewTimeSeries("test1", tsdb.NewTimeSeriesPointsFromArgs(120, 0)),
66+
tsdb.NewTimeSeries("test2", tsdb.NewTimeSeriesPointsFromArgs(0, 0)),
6967
}
7068
ctx.exec()
7169

@@ -76,8 +74,8 @@ func TestQueryCondition(t *testing.T) {
7674
Convey("Empty series", func() {
7775
Convey("Should set NoDataFound both series are empty", func() {
7876
ctx.series = tsdb.TimeSeriesSlice{
79-
tsdb.NewTimeSeries("test1", [][2]*float64{}),
80-
tsdb.NewTimeSeries("test2", [][2]*float64{}),
77+
tsdb.NewTimeSeries("test1", tsdb.NewTimeSeriesPointsFromArgs()),
78+
tsdb.NewTimeSeries("test2", tsdb.NewTimeSeriesPointsFromArgs()),
8179
}
8280
ctx.exec()
8381

@@ -86,10 +84,9 @@ func TestQueryCondition(t *testing.T) {
8684
})
8785

8886
Convey("Should set NoDataFound both series contains null", func() {
89-
one := float64(120)
9087
ctx.series = tsdb.TimeSeriesSlice{
91-
tsdb.NewTimeSeries("test1", [][2]*float64{{nil, &one}}),
92-
tsdb.NewTimeSeries("test2", [][2]*float64{{nil, &one}}),
88+
tsdb.NewTimeSeries("test1", tsdb.TimeSeriesPoints{tsdb.TimePoint{null.FloatFromPtr(nil), null.FloatFrom(0)}}),
89+
tsdb.NewTimeSeries("test2", tsdb.TimeSeriesPoints{tsdb.TimePoint{null.FloatFromPtr(nil), null.FloatFrom(0)}}),
9390
}
9491
ctx.exec()
9592

@@ -98,11 +95,9 @@ func TestQueryCondition(t *testing.T) {
9895
})
9996

10097
Convey("Should not set NoDataFound if one serie is empty", func() {
101-
one := float64(120)
102-
two := float64(0)
10398
ctx.series = tsdb.TimeSeriesSlice{
104-
tsdb.NewTimeSeries("test1", [][2]*float64{}),
105-
tsdb.NewTimeSeries("test2", [][2]*float64{{&one, &two}}),
99+
tsdb.NewTimeSeries("test1", tsdb.NewTimeSeriesPointsFromArgs()),
100+
tsdb.NewTimeSeries("test2", tsdb.NewTimeSeriesPointsFromArgs(120, 0)),
106101
}
107102
ctx.exec()
108103

pkg/services/alerting/conditions/reducer.go

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@ import (
44
"math"
55

66
"github.com/grafana/grafana/pkg/tsdb"
7+
"gopkg.in/guregu/null.v3"
78
)
89

910
type QueryReducer interface {
10-
Reduce(timeSeries *tsdb.TimeSeries) *float64
11+
Reduce(timeSeries *tsdb.TimeSeries) null.Float
1112
}
1213

1314
type SimpleReducer struct {
1415
Type string
1516
}
1617

17-
func (s *SimpleReducer) Reduce(series *tsdb.TimeSeries) *float64 {
18+
func (s *SimpleReducer) Reduce(series *tsdb.TimeSeries) null.Float {
1819
if len(series.Points) == 0 {
19-
return nil
20+
return null.FloatFromPtr(nil)
2021
}
2122

2223
value := float64(0)
@@ -25,36 +26,36 @@ func (s *SimpleReducer) Reduce(series *tsdb.TimeSeries) *float64 {
2526
switch s.Type {
2627
case "avg":
2728
for _, point := range series.Points {
28-
if point[0] != nil {
29-
value += *point[0]
29+
if point[0].Valid {
30+
value += point[0].Float64
3031
allNull = false
3132
}
3233
}
3334
value = value / float64(len(series.Points))
3435
case "sum":
3536
for _, point := range series.Points {
36-
if point[0] != nil {
37-
value += *point[0]
37+
if point[0].Valid {
38+
value += point[0].Float64
3839
allNull = false
3940
}
4041
}
4142
case "min":
4243
value = math.MaxFloat64
4344
for _, point := range series.Points {
44-
if point[0] != nil {
45+
if point[0].Valid {
4546
allNull = false
46-
if value > *point[0] {
47-
value = *point[0]
47+
if value > point[0].Float64 {
48+
value = point[0].Float64
4849
}
4950
}
5051
}
5152
case "max":
5253
value = -math.MaxFloat64
5354
for _, point := range series.Points {
54-
if point[0] != nil {
55+
if point[0].Valid {
5556
allNull = false
56-
if value < *point[0] {
57-
value = *point[0]
57+
if value < point[0].Float64 {
58+
value = point[0].Float64
5859
}
5960
}
6061
}
@@ -64,10 +65,10 @@ func (s *SimpleReducer) Reduce(series *tsdb.TimeSeries) *float64 {
6465
}
6566

6667
if allNull {
67-
return nil
68+
return null.FloatFromPtr(nil)
6869
}
6970

70-
return &value
71+
return null.FloatFrom(value)
7172
}
7273

7374
func NewSimpleReducer(typ string) *SimpleReducer {

pkg/services/alerting/conditions/reducer_test.go

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,44 +10,41 @@ import (
1010
func TestSimpleReducer(t *testing.T) {
1111
Convey("Test simple reducer by calculating", t, func() {
1212
Convey("avg", func() {
13-
result := *testReducer("avg", 1, 2, 3)
13+
result := testReducer("avg", 1, 2, 3)
1414
So(result, ShouldEqual, float64(2))
1515
})
1616

1717
Convey("sum", func() {
18-
result := *testReducer("sum", 1, 2, 3)
18+
result := testReducer("sum", 1, 2, 3)
1919
So(result, ShouldEqual, float64(6))
2020
})
2121

2222
Convey("min", func() {
23-
result := *testReducer("min", 3, 2, 1)
23+
result := testReducer("min", 3, 2, 1)
2424
So(result, ShouldEqual, float64(1))
2525
})
2626

2727
Convey("max", func() {
28-
result := *testReducer("max", 1, 2, 3)
28+
result := testReducer("max", 1, 2, 3)
2929
So(result, ShouldEqual, float64(3))
3030
})
3131

3232
Convey("count", func() {
33-
result := *testReducer("count", 1, 2, 3000)
33+
result := testReducer("count", 1, 2, 3000)
3434
So(result, ShouldEqual, float64(3))
3535
})
3636
})
3737
}
3838

39-
func testReducer(typ string, datapoints ...float64) *float64 {
39+
func testReducer(typ string, datapoints ...float64) float64 {
4040
reducer := NewSimpleReducer(typ)
41-
var timeserie [][2]*float64
42-
dummieTimestamp := float64(521452145)
41+
series := &tsdb.TimeSeries{
42+
Name: "test time serie",
43+
}
4344

4445
for idx := range datapoints {
45-
timeserie = append(timeserie, [2]*float64{&datapoints[idx], &dummieTimestamp})
46+
series.Points = append(series.Points, tsdb.NewTimePoint(datapoints[idx], 1234134))
4647
}
4748

48-
tsdb := &tsdb.TimeSeries{
49-
Name: "test time serie",
50-
Points: timeserie,
51-
}
52-
return reducer.Reduce(tsdb)
49+
return reducer.Reduce(series).Float64
5350
}

pkg/tsdb/graphite/graphite.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ func (e *GraphiteExecutor) Execute(queries tsdb.QuerySlice, context *tsdb.QueryC
8080

8181
result.QueryResults = make(map[string]*tsdb.QueryResult)
8282
queryRes := &tsdb.QueryResult{}
83+
8384
for _, series := range data {
8485
queryRes.Series = append(queryRes.Series, &tsdb.TimeSeries{
8586
Name: series.Target,

pkg/tsdb/graphite/types.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package graphite
22

3+
import "github.com/grafana/grafana/pkg/tsdb"
4+
35
type TargetResponseDTO struct {
4-
Target string `json:"target"`
5-
DataPoints [][2]*float64 `json:"datapoints"`
6+
Target string `json:"target"`
7+
DataPoints tsdb.TimeSeriesPoints `json:"datapoints"`
68
}

0 commit comments

Comments
 (0)