浏览代码

feat(alerting): progress on updating extractor to work with new alert model

Torkel Ödegaard 9 年之前
父节点
当前提交
2a30baef05
共有 3 个文件被更改,包括 103 次插入173 次删除
  1. 1 1
      pkg/services/alerting/alert_rule_test.go
  2. 36 25
      pkg/services/alerting/extractor.go
  3. 66 147
      pkg/services/alerting/extractor_test.go

+ 1 - 1
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]}

+ 36 - 25
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)
-
-				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()
-					}
-
-					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)
-					}
+			for _, condition := range jsonAlert.Get("conditions").MustArray() {
+				jsonCondition := simplejson.NewFromAny(condition)
+
+				jsonQuery := jsonCondition.Get("query")
+				queryRefId := jsonQuery.Get("params").MustArray()[0].(string)
+				panelQuery := findPanelQueryByRefId(panel, queryRefId)
+
+				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")
 			}
-
 		}
 	}
 

+ 66 - 147
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)")
+				})
 			})
 		})
 	})