Procházet zdrojové kódy

feat(alerting): adds within_range and outside_range evaluators

closes #5829
bergquist před 9 roky
rodič
revize
fb7f2ae2e2

+ 50 - 7
pkg/services/alerting/conditions/evaluator.go

@@ -28,11 +28,30 @@ func (e *DefaultAlertEvaluator) Eval(series *tsdb.TimeSeries, reducedValue float
 	return false
 }
 
-func NewDefaultAlertEvaluator(model *simplejson.Json) (*DefaultAlertEvaluator, error) {
-	evaluator := &DefaultAlertEvaluator{}
+type RangedAlertEvaluator struct {
+	Type  string
+	Lower float64
+	Upper float64
+}
+
+func (e *RangedAlertEvaluator) Eval(series *tsdb.TimeSeries, reducedValue float64) bool {
+	switch e.Type {
+	case "within_range":
+		return (e.Lower < reducedValue && e.Upper > reducedValue) || (e.Upper < reducedValue && e.Lower > reducedValue)
+	case "outside_range":
+		return (e.Upper < reducedValue && e.Lower < reducedValue) || (e.Upper > reducedValue && e.Lower > reducedValue)
+	}
+
+	return false
+}
+
+func NewAlertEvaluator(model *simplejson.Json) (AlertEvaluator, error) {
+	defaultTypes := []string{"gt", "lt"}
+	rangedTypes := []string{"within_range", "outside_range"}
 
-	evaluator.Type = model.Get("type").MustString()
-	if evaluator.Type == "" {
+	typ := model.Get("type").MustString()
+
+	if typ == "" {
 		return nil, alerting.ValidationError{Reason: "Evaluator missing type property"}
 	}
 
@@ -41,11 +60,35 @@ func NewDefaultAlertEvaluator(model *simplejson.Json) (*DefaultAlertEvaluator, e
 		return nil, alerting.ValidationError{Reason: "Evaluator missing threshold parameter"}
 	}
 
-	threshold, ok := params[0].(json.Number)
+	firstParam, ok := params[0].(json.Number)
 	if !ok {
 		return nil, alerting.ValidationError{Reason: "Evaluator has invalid threshold parameter"}
 	}
 
-	evaluator.Threshold, _ = threshold.Float64()
-	return evaluator, nil
+	if stringInSlice(typ, defaultTypes) {
+		evaluator := &DefaultAlertEvaluator{Type: typ}
+		evaluator.Threshold, _ = firstParam.Float64()
+		return evaluator, nil
+	} else if stringInSlice(typ, rangedTypes) {
+		secondParam, ok := params[1].(json.Number)
+		if !ok {
+			return nil, alerting.ValidationError{Reason: "Evaluator has invalid threshold parameter"}
+		}
+
+		evaluator := &RangedAlertEvaluator{Type: typ}
+		evaluator.Lower, _ = firstParam.Float64()
+		evaluator.Upper, _ = secondParam.Float64()
+		return evaluator, nil
+	}
+
+	return nil, alerting.ValidationError{Reason: "Evaludator invalid evaluator type"}
+}
+
+func stringInSlice(a string, list []string) bool {
+	for _, b := range list {
+		if b == a {
+			return true
+		}
+	}
+	return false
 }

+ 45 - 0
pkg/services/alerting/conditions/evaluator_test.go

@@ -0,0 +1,45 @@
+package conditions
+
+import (
+	"testing"
+
+	"github.com/grafana/grafana/pkg/components/simplejson"
+	"github.com/grafana/grafana/pkg/tsdb"
+	. "github.com/smartystreets/goconvey/convey"
+)
+
+func test(json string, reducedValue float64) bool {
+	jsonModel, err := simplejson.NewJson([]byte(json))
+	So(err, ShouldBeNil)
+
+	evaluator, err := NewAlertEvaluator(jsonModel)
+	So(err, ShouldBeNil)
+
+	return evaluator.Eval(&tsdb.TimeSeries{}, reducedValue)
+}
+
+func TestEvalutors(t *testing.T) {
+	Convey("greater then", t, func() {
+		So(test(`{"type": "gt", "params": [1] }`, 3), ShouldBeTrue)
+		So(test(`{"type": "gt", "params": [3] }`, 1), ShouldBeFalse)
+	})
+
+	Convey("less then", t, func() {
+		So(test(`{"type": "lt", "params": [1] }`, 3), ShouldBeFalse)
+		So(test(`{"type": "lt", "params": [3] }`, 1), ShouldBeTrue)
+	})
+
+	Convey("within_range", t, func() {
+		So(test(`{"type": "within_range", "params": [1, 100] }`, 3), ShouldBeTrue)
+		So(test(`{"type": "within_range", "params": [1, 100] }`, 300), ShouldBeFalse)
+		So(test(`{"type": "within_range", "params": [100, 1] }`, 3), ShouldBeTrue)
+		So(test(`{"type": "within_range", "params": [100, 1] }`, 300), ShouldBeFalse)
+	})
+
+	Convey("outside_range", t, func() {
+		So(test(`{"type": "outside_range", "params": [1, 100] }`, 1000), ShouldBeTrue)
+		So(test(`{"type": "outside_range", "params": [1, 100] }`, 50), ShouldBeFalse)
+		So(test(`{"type": "outside_range", "params": [100, 1] }`, 1000), ShouldBeTrue)
+		So(test(`{"type": "outside_range", "params": [100, 1] }`, 50), ShouldBeFalse)
+	})
+}

+ 1 - 1
pkg/services/alerting/conditions/query.go

@@ -133,7 +133,7 @@ func NewQueryCondition(model *simplejson.Json, index int) (*QueryCondition, erro
 	condition.Reducer = NewSimpleReducer(reducerJson.Get("type").MustString())
 
 	evaluatorJson := model.Get("evaluator")
-	evaluator, err := NewDefaultAlertEvaluator(evaluatorJson)
+	evaluator, err := NewAlertEvaluator(evaluatorJson)
 	if err != nil {
 		return nil, err
 	}