From f60efed5d81ade682783c0a7421445f59f4684ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 19 Jul 2016 17:45:37 +0200 Subject: [PATCH] feat(alerting): progress on refactoring backend alert rule model --- pkg/services/alerting/alert_rule_test.go | 23 ++++++- pkg/services/alerting/conditions.go | 83 +++++++++++++++++++----- pkg/services/alerting/interfaces.go | 12 ++++ 3 files changed, 101 insertions(+), 17 deletions(-) diff --git a/pkg/services/alerting/alert_rule_test.go b/pkg/services/alerting/alert_rule_test.go index 9b75105579d..33ee04c416f 100644 --- a/pkg/services/alerting/alert_rule_test.go +++ b/pkg/services/alerting/alert_rule_test.go @@ -31,7 +31,7 @@ func TestAlertRuleModel(t *testing.T) { So(seconds, ShouldEqual, 1) }) - Convey("", func() { + Convey("can construct alert rule model", func() { json := ` { "name": "name2", @@ -70,6 +70,27 @@ func TestAlertRuleModel(t *testing.T) { So(err, ShouldBeNil) So(alertRule.Conditions, ShouldHaveLength, 1) + + Convey("Can read query condition from json model", func() { + queryCondition, ok := alertRule.Conditions[0].(*QueryCondition) + So(ok, ShouldBeTrue) + + So(queryCondition.Query.From, ShouldEqual, "5m") + So(queryCondition.Query.To, ShouldEqual, "now") + So(queryCondition.Query.DatasourceId, ShouldEqual, 1) + + Convey("Can read query reducer", func() { + reducer, ok := queryCondition.Reducer.(*SimpleReducer) + So(ok, ShouldBeTrue) + So(reducer.Type, ShouldEqual, "avg") + }) + + Convey("Can read evaluator", func() { + evaluator, ok := queryCondition.Evaluator.(*DefaultAlertEvaluator) + So(ok, ShouldBeTrue) + So(evaluator.Type, ShouldEqual, ">") + }) + }) }) }) } diff --git a/pkg/services/alerting/conditions.go b/pkg/services/alerting/conditions.go index 5fea9c81bd6..fc20f9517a2 100644 --- a/pkg/services/alerting/conditions.go +++ b/pkg/services/alerting/conditions.go @@ -1,32 +1,83 @@ package alerting -import "github.com/grafana/grafana/pkg/components/simplejson" +import ( + "encoding/json" + "errors" -type AlertCondition interface { - Eval() -} + "github.com/grafana/grafana/pkg/components/simplejson" +) type QueryCondition struct { Query AlertQuery - Reducer AlertReducerModel - Evaluator AlertEvaluatorModel + Reducer QueryReducer + Evaluator AlertEvaluator } func (c *QueryCondition) Eval() { } -type AlertReducerModel struct { - Type string - Params []interface{} -} - -type AlertEvaluatorModel struct { - Type string - Params []interface{} -} - func NewQueryCondition(model *simplejson.Json) (*QueryCondition, error) { condition := QueryCondition{} + queryJson := model.Get("query") + + condition.Query.Query = queryJson.Get("query").MustString() + condition.Query.From = queryJson.Get("params").MustArray()[1].(string) + condition.Query.To = queryJson.Get("params").MustArray()[2].(string) + condition.Query.DatasourceId = queryJson.Get("datasourceId").MustInt64() + + reducerJson := model.Get("reducer") + condition.Reducer = NewSimpleReducer(reducerJson.Get("type").MustString()) + + evaluatorJson := model.Get("evaluator") + evaluator, err := NewDefaultAlertEvaluator(evaluatorJson) + if err != nil { + return nil, err + } + + condition.Evaluator = evaluator return &condition, nil } + +type SimpleReducer struct { + Type string +} + +func (s *SimpleReducer) Reduce() float64 { + return 0 +} + +func NewSimpleReducer(typ string) *SimpleReducer { + return &SimpleReducer{Type: typ} +} + +type DefaultAlertEvaluator struct { + Type string + Threshold float64 +} + +func (e *DefaultAlertEvaluator) Eval() bool { + return true +} + +func NewDefaultAlertEvaluator(model *simplejson.Json) (*DefaultAlertEvaluator, error) { + evaluator := &DefaultAlertEvaluator{} + + evaluator.Type = model.Get("type").MustString() + if evaluator.Type == "" { + return nil, errors.New("Alert evaluator missing type property") + } + + params := model.Get("params").MustArray() + if len(params) == 0 { + return nil, errors.New("Alert evaluator missing threshold parameter") + } + + threshold, ok := params[0].(json.Number) + if !ok { + return nil, errors.New("Alert evaluator has invalid threshold parameter") + } + + evaluator.Threshold, _ = threshold.Float64() + return evaluator, nil +} diff --git a/pkg/services/alerting/interfaces.go b/pkg/services/alerting/interfaces.go index 87ded1a2631..fb9b0ba2c81 100644 --- a/pkg/services/alerting/interfaces.go +++ b/pkg/services/alerting/interfaces.go @@ -14,3 +14,15 @@ type Scheduler interface { type Notifier interface { Notify(alertResult *AlertResult) } + +type AlertCondition interface { + Eval() +} + +type QueryReducer interface { + Reduce() float64 +} + +type AlertEvaluator interface { + Eval() bool +}