From 2a30baef05cde19bab763e9f90239c2721894585 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 19 Jul 2016 21:00:41 +0200 Subject: [PATCH] feat(alerting): progress on updating extractor to work with new alert model --- pkg/services/alerting/alert_rule_test.go | 2 +- pkg/services/alerting/extractor.go | 57 +++--- pkg/services/alerting/extractor_test.go | 213 +++++++---------------- 3 files changed, 101 insertions(+), 171 deletions(-) diff --git a/pkg/services/alerting/alert_rule_test.go b/pkg/services/alerting/alert_rule_test.go index 33ee04c416f..7bcb3e3233a 100644 --- a/pkg/services/alerting/alert_rule_test.go +++ b/pkg/services/alerting/alert_rule_test.go @@ -45,7 +45,7 @@ func TestAlertRuleModel(t *testing.T) { "query": { "params": ["A", "5m", "now"], "datasourceId": 1, - "query": "aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)" + "model": {"target": "aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)"} }, "reducer": {"type": "avg", "params": []}, "evaluator": {"type": ">", "params": [100]} diff --git a/pkg/services/alerting/extractor.go b/pkg/services/alerting/extractor.go index 196af8ae171..7783db75f06 100644 --- a/pkg/services/alerting/extractor.go +++ b/pkg/services/alerting/extractor.go @@ -2,6 +2,7 @@ package alerting import ( "errors" + "fmt" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/components/simplejson" @@ -47,6 +48,17 @@ func (e *DashAlertExtractor) lookupDatasourceId(dsName string) (*m.DataSource, e return nil, errors.New("Could not find datasource id for " + dsName) } +func findPanelQueryByRefId(panel *simplejson.Json, refId string) *simplejson.Json { + for _, targetsObj := range panel.Get("targets").MustArray() { + target := simplejson.NewFromAny(targetsObj) + + if target.Get("refId").MustString() == refId { + return target + } + } + return nil +} + func (e *DashAlertExtractor) GetAlerts() ([]*m.Alert, error) { e.log.Debug("GetAlerts") @@ -81,31 +93,31 @@ func (e *DashAlertExtractor) GetAlerts() ([]*m.Alert, error) { Frequency: getTimeDurationStringToSeconds(jsonAlert.Get("frequency").MustString()), } - valueQuery := jsonAlert.Get("query") - valueQueryRef := valueQuery.Get("refId").MustString() - for _, targetsObj := range panel.Get("targets").MustArray() { - target := simplejson.NewFromAny(targetsObj) + for _, condition := range jsonAlert.Get("conditions").MustArray() { + jsonCondition := simplejson.NewFromAny(condition) - if target.Get("refId").MustString() == valueQueryRef { - dsName := "" - if target.Get("datasource").MustString() != "" { - dsName = target.Get("datasource").MustString() - } else if panel.Get("datasource").MustString() != "" { - dsName = panel.Get("datasource").MustString() - } + jsonQuery := jsonCondition.Get("query") + queryRefId := jsonQuery.Get("params").MustArray()[0].(string) + panelQuery := findPanelQueryByRefId(panel, queryRefId) - if datasource, err := e.lookupDatasourceId(dsName); err != nil { - return nil, err - } else { - valueQuery.SetPath([]string{"datasourceId"}, datasource.Id) - valueQuery.SetPath([]string{"datasourceType"}, datasource.Type) - } - - targetQuery := target.Get("target").MustString() - if targetQuery != "" { - jsonAlert.SetPath([]string{"query", "query"}, targetQuery) - } + if panelQuery == nil { + return nil, fmt.Errorf("Alert referes to query %s, that could not be found", queryRefId) } + + dsName := "" + if panelQuery.Get("datasource").MustString() != "" { + dsName = panelQuery.Get("datasource").MustString() + } else if panel.Get("datasource").MustString() != "" { + dsName = panel.Get("datasource").MustString() + } + + if datasource, err := e.lookupDatasourceId(dsName); err != nil { + return nil, err + } else { + jsonQuery.SetPath([]string{"datasourceId"}, datasource.Id) + } + + jsonQuery.Set("model", panelQuery.Interface()) } alert.Settings = jsonAlert @@ -118,7 +130,6 @@ func (e *DashAlertExtractor) GetAlerts() ([]*m.Alert, error) { e.log.Error("Failed to extract alerts from dashboard", "error", err) return nil, errors.New("Failed to extract alerts from dashboard") } - } } diff --git a/pkg/services/alerting/extractor_test.go b/pkg/services/alerting/extractor_test.go index 88fab4bf70d..7fb87338f88 100644 --- a/pkg/services/alerting/extractor_test.go +++ b/pkg/services/alerting/extractor_test.go @@ -14,162 +14,69 @@ func TestAlertRuleExtraction(t *testing.T) { Convey("Parsing alert rules from dashboard json", t, func() { Convey("Parsing and validating alerts from dashboards", func() { json := `{ - "id": 57, - "title": "Graphite 4", - "originalTitle": "Graphite 4", - "tags": [ - "graphite" - ], - "rows": [ - { - - "panels": [ + "id": 57, + "title": "Graphite 4", + "originalTitle": "Graphite 4", + "tags": ["graphite"], + "rows": [ { - "title": "Active desktop users", - "editable": true, - "type": "graph", - "id": 3, - "targets": [ + "panels": [ + { + "title": "Active desktop users", + "editable": true, + "type": "graph", + "id": 3, + "targets": [ { "refId": "A", "target": "aliasByNode(statsd.fakesite.counters.session_start.desktop.count, 4)" } - ], - "datasource": null, - "alert": { - "name": "name1", - "description": "desc1", - "handler": 1, - "enabled": true, - "critical": { - "value": 20, - "op": ">" - }, - "frequency": "60s", - "query": { - "from": "5m", - "refId": "A", - "to": "now" - }, - "transform": { - "type": "avg", - "name": "aggregation" - }, - "warn": { - "value": 10, - "op": ">" - } - } - }, - { - "title": "Active mobile users", - "id": 4, - "targets": [ - { - "refId": "A", - "target": "aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)" - } - ], - "datasource": "graphite2", - "alert": { - "name": "name2", - "description": "desc2", - "handler": 0, - "enabled": true, - "critical": { - "value": 20, - "op": ">" - }, - "frequency": "60s", - "query": { - "from": "5m", - "refId": "A", - "to": "now" - }, - "transform": { - "type": "avg", - "name": "aggregation" - }, - "warn": { - "value": 10, - "op": ">" - } - } - } - ], - "title": "Row" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [ - { - "datasource": "InfluxDB", - "id": 2, - "alert": { - "name": "name2", - "description": "desc2", - "enabled": false, - "critical": { - "level": 20, - "op": ">" - }, - "warn": { - "level": 10, - "op": ">" + ], + "datasource": null, + "alert": { + "name": "name1", + "description": "desc1", + "handler": 1, + "enabled": true, + "frequency": "60s", + "conditions": [ + { + "type": "query", + "query": {"params": ["A", "5m", "now"]}, + "reducer": {"type": "avg", "params": []}, + "evaluator": {"type": ">", "params": [100]} + } + ] } }, - "targets": [ - { - "dsType": "influxdb", - "groupBy": [ - { - "params": [ - "$interval" - ], - "type": "time" - }, - { - "params": [ - "null" - ], - "type": "fill" - } - ], - "measurement": "cpu", - "policy": "default", - "query": "SELECT mean(\"value\") FROM \"cpu\" WHERE $timeFilter GROUP BY time($interval) fill(null)", - "refId": "A", - "resultFormat": "table", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "mean" - } - ] - ], - "tags": [], - "target": "" + { + "title": "Active mobile users", + "id": 4, + "targets": [ + {"refId": "A", "target": ""}, + {"refId": "B", "target": "aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)"} + ], + "datasource": "graphite2", + "alert": { + "name": "name2", + "description": "desc2", + "handler": 0, + "enabled": true, + "frequency": "60s", + "conditions": [ + { + "type": "query", + "query": {"params": ["B", "5m", "now"]}, + "reducer": {"type": "avg", "params": []}, + "evaluator": {"type": ">", "params": [100]} + } + ] } - ], - "title": "Broken influxdb panel", - "transform": "table", - "type": "table" + } + ] } - ], - "title": "New row" - } - ] - -}` + ] + }` dashJson, err := simplejson.NewJson([]byte(json)) So(err, ShouldBeNil) @@ -231,6 +138,18 @@ func TestAlertRuleExtraction(t *testing.T) { So(alerts[1].Name, ShouldEqual, "name2") So(alerts[1].Description, ShouldEqual, "desc2") }) + + Convey("should set datasourceId", func() { + condition := simplejson.NewFromAny(alerts[0].Settings.Get("conditions").MustArray()[0]) + query := condition.Get("query") + So(query.Get("datasourceId").MustInt64(), ShouldEqual, 12) + }) + + Convey("should copy query model to condition", func() { + condition := simplejson.NewFromAny(alerts[0].Settings.Get("conditions").MustArray()[0]) + model := condition.Get("query").Get("model") + So(model.Get("target").MustString(), ShouldEqual, "aliasByNode(statsd.fakesite.counters.session_start.desktop.count, 4)") + }) }) }) })