Просмотр исходного кода

feat(alerting): separate operator and level

bergquist 9 лет назад
Родитель
Сommit
1624dc9dfd

+ 15 - 13
pkg/api/dtos/alerting.go

@@ -1,19 +1,21 @@
 package dtos
 package dtos
 
 
 type AlertRuleDTO struct {
 type AlertRuleDTO struct {
-	Id          int64  `json:"id"`
-	DashboardId int64  `json:"dashboardId"`
-	PanelId     int64  `json:"panelId"`
-	Query       string `json:"query"`
-	QueryRefId  string `json:"queryRefId"`
-	WarnLevel   string `json:"warnLevel"`
-	CritLevel   string `json:"critLevel"`
-	Interval    string `json:"interval"`
-	Title       string `json:"title"`
-	Description string `json:"description"`
-	QueryRange  string `json:"queryRange"`
-	Aggregator  string `json:"aggregator"`
-	State       string `json:"state"`
+	Id           int64  `json:"id"`
+	DashboardId  int64  `json:"dashboardId"`
+	PanelId      int64  `json:"panelId"`
+	Query        string `json:"query"`
+	QueryRefId   string `json:"queryRefId"`
+	WarnLevel    int64  `json:"warnLevel"`
+	CritLevel    int64  `json:"critLevel"`
+	WarnOperator string `json:"warnOperator"`
+	CritOperator string `json:"critOperator"`
+	Interval     string `json:"interval"`
+	Title        string `json:"title"`
+	Description  string `json:"description"`
+	QueryRange   string `json:"queryRange"`
+	Aggregator   string `json:"aggregator"`
+	State        string `json:"state"`
 
 
 	DashbboardUri string `json:"dashboardUri"`
 	DashbboardUri string `json:"dashboardUri"`
 }
 }

+ 30 - 26
pkg/models/alerts.go

@@ -6,20 +6,22 @@ import (
 )
 )
 
 
 type AlertRule struct {
 type AlertRule struct {
-	Id          int64  `json:"id"`
-	OrgId       int64  `json:"-"`
-	DashboardId int64  `json:"dashboardId"`
-	PanelId     int64  `json:"panelId"`
-	Query       string `json:"query"`
-	QueryRefId  string `json:"queryRefId"`
-	WarnLevel   string `json:"warnLevel"`
-	CritLevel   string `json:"critLevel"`
-	Interval    string `json:"interval"`
-	Title       string `json:"title"`
-	Description string `json:"description"`
-	QueryRange  string `json:"queryRange"`
-	Aggregator  string `json:"aggregator"`
-	State       string `json:"state"`
+	Id           int64  `json:"id"`
+	OrgId        int64  `json:"-"`
+	DashboardId  int64  `json:"dashboardId"`
+	PanelId      int64  `json:"panelId"`
+	Query        string `json:"query"`
+	QueryRefId   string `json:"queryRefId"`
+	WarnLevel    int64  `json:"warnLevel"`
+	CritLevel    int64  `json:"critLevel"`
+	WarnOperator string `json:"warnOperator"`
+	CritOperator string `json:"critOperator"`
+	Interval     string `json:"interval"`
+	Title        string `json:"title"`
+	Description  string `json:"description"`
+	QueryRange   string `json:"queryRange"`
+	Aggregator   string `json:"aggregator"`
+	State        string `json:"state"`
 }
 }
 
 
 type AlertRuleChange struct {
 type AlertRuleChange struct {
@@ -40,18 +42,20 @@ func (cmd *SaveDashboardCommand) GetAlertModels() *[]AlertRule {
 
 
 			alerting := panel.Get("alerting")
 			alerting := panel.Get("alerting")
 			alert := AlertRule{
 			alert := AlertRule{
-				DashboardId: cmd.Result.Id,
-				OrgId:       cmd.Result.OrgId,
-				PanelId:     panel.Get("id").MustInt64(),
-				Id:          alerting.Get("id").MustInt64(),
-				QueryRefId:  alerting.Get("queryRef").MustString(),
-				WarnLevel:   alerting.Get("warnLevel").MustString(),
-				CritLevel:   alerting.Get("critLevel").MustString(),
-				Interval:    alerting.Get("interval").MustString(),
-				Title:       alerting.Get("title").MustString(),
-				Description: alerting.Get("description").MustString(),
-				QueryRange:  alerting.Get("queryRange").MustString(),
-				Aggregator:  alerting.Get("aggregator").MustString(),
+				DashboardId:  cmd.Result.Id,
+				OrgId:        cmd.Result.OrgId,
+				PanelId:      panel.Get("id").MustInt64(),
+				Id:           alerting.Get("id").MustInt64(),
+				QueryRefId:   alerting.Get("queryRef").MustString(),
+				WarnLevel:    alerting.Get("warnLevel").MustInt64(),
+				CritLevel:    alerting.Get("critLevel").MustInt64(),
+				WarnOperator: alerting.Get("warnOperator").MustString(),
+				CritOperator: alerting.Get("critOperator").MustString(),
+				Interval:     alerting.Get("interval").MustString(),
+				Title:        alerting.Get("title").MustString(),
+				Description:  alerting.Get("description").MustString(),
+				QueryRange:   alerting.Get("queryRange").MustString(),
+				Aggregator:   alerting.Get("aggregator").MustString(),
 			}
 			}
 
 
 			for _, targetsObj := range panel.Get("targets").MustArray() {
 			for _, targetsObj := range panel.Get("targets").MustArray() {

+ 17 - 8
pkg/models/alerts_test.go

@@ -101,8 +101,10 @@ func TestAlertModel(t *testing.T) {
           "seriesOverrides": [],
           "seriesOverrides": [],
           "alerting": {
           "alerting": {
             "queryRef": "A",
             "queryRef": "A",
-            "warnLevel": "> 30",
-            "critLevel": "> 50",
+            "warnLevel": 30,
+            "critLevel": 50,
+            "warnOperator": ">",
+            "critOperator": ">",
             "aggregator": "sum",
             "aggregator": "sum",
             "queryRange": "10m",
             "queryRange": "10m",
             "interval": "10s",
             "interval": "10s",
@@ -186,8 +188,10 @@ func TestAlertModel(t *testing.T) {
           "seriesOverrides": [],
           "seriesOverrides": [],
           "alerting": {
           "alerting": {
             "queryRef": "A",
             "queryRef": "A",
-            "warnLevel": "> 300",
-            "critLevel": "> 500",
+            "warnOperator": ">",
+            "critOperator": ">",
+            "warnLevel": 300,
+            "critLevel": 500,
             "aggregator": "avg",
             "aggregator": "avg",
             "queryRange": "10m",
             "queryRange": "10m",
             "interval": "10s",
             "interval": "10s",
@@ -363,11 +367,16 @@ func TestAlertModel(t *testing.T) {
 				So(v.Description, ShouldNotBeEmpty)
 				So(v.Description, ShouldNotBeEmpty)
 			}
 			}
 
 
-			So(alerts[0].WarnLevel, ShouldEqual, "> 30")
-			So(alerts[1].WarnLevel, ShouldEqual, "> 300")
+			So(alerts[0].WarnLevel, ShouldEqual, 30)
+			So(alerts[1].WarnLevel, ShouldEqual, 300)
 
 
-			So(alerts[0].CritLevel, ShouldEqual, "> 50")
-			So(alerts[1].CritLevel, ShouldEqual, "> 500")
+			So(alerts[0].CritLevel, ShouldEqual, 50)
+			So(alerts[1].CritLevel, ShouldEqual, 500)
+
+			So(alerts[0].CritOperator, ShouldEqual, ">")
+			So(alerts[1].CritOperator, ShouldEqual, ">")
+			So(alerts[0].WarnOperator, ShouldEqual, ">")
+			So(alerts[1].WarnOperator, ShouldEqual, ">")
 
 
 			So(alerts[0].Query, ShouldEqual, `{"refId":"A","target":"aliasByNode(statsd.fakesite.counters.session_start.desktop.count, 4)"}`)
 			So(alerts[0].Query, ShouldEqual, `{"refId":"A","target":"aliasByNode(statsd.fakesite.counters.session_start.desktop.count, 4)"}`)
 			So(alerts[1].Query, ShouldEqual, `{"refId":"A","target":"aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)"}`)
 			So(alerts[1].Query, ShouldEqual, `{"refId":"A","target":"aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)"}`)

+ 2 - 0
pkg/services/sqlstore/alert_rule.go

@@ -75,6 +75,8 @@ func alertIsDifferent(rule1, rule2 m.AlertRule) bool {
 	result = result || rule1.Aggregator != rule2.Aggregator
 	result = result || rule1.Aggregator != rule2.Aggregator
 	result = result || rule1.CritLevel != rule2.CritLevel
 	result = result || rule1.CritLevel != rule2.CritLevel
 	result = result || rule1.WarnLevel != rule2.WarnLevel
 	result = result || rule1.WarnLevel != rule2.WarnLevel
+	result = result || rule1.WarnOperator != rule2.WarnOperator
+	result = result || rule1.CritOperator != rule2.CritOperator
 	result = result || rule1.Query != rule2.Query
 	result = result || rule1.Query != rule2.Query
 	result = result || rule1.QueryRefId != rule2.QueryRefId
 	result = result || rule1.QueryRefId != rule2.QueryRefId
 	result = result || rule1.Interval != rule2.Interval
 	result = result || rule1.Interval != rule2.Interval

+ 14 - 12
pkg/services/sqlstore/alert_rule_changes_test.go

@@ -22,18 +22,20 @@ func TestAlertRuleChangesDataAccess(t *testing.T) {
 		Convey("When dashboard is removed", func() {
 		Convey("When dashboard is removed", func() {
 			items := []m.AlertRule{
 			items := []m.AlertRule{
 				{
 				{
-					PanelId:     1,
-					DashboardId: testDash.Id,
-					Query:       "Query",
-					QueryRefId:  "A",
-					WarnLevel:   "> 30",
-					CritLevel:   "> 50",
-					Interval:    "10",
-					Title:       "Alerting title",
-					Description: "Alerting description",
-					QueryRange:  "5m",
-					Aggregator:  "avg",
-					OrgId:       FakeOrgId,
+					PanelId:      1,
+					DashboardId:  testDash.Id,
+					Query:        "Query",
+					QueryRefId:   "A",
+					WarnLevel:    30,
+					CritLevel:    50,
+					WarnOperator: ">",
+					CritOperator: ">",
+					Interval:     "10",
+					Title:        "Alerting title",
+					Description:  "Alerting description",
+					QueryRange:   "5m",
+					Aggregator:   "avg",
+					OrgId:        FakeOrgId,
 				},
 				},
 			}
 			}
 
 

+ 32 - 26
pkg/services/sqlstore/alert_rule_test.go

@@ -16,19 +16,21 @@ func TestAlertingDataAccess(t *testing.T) {
 
 
 		items := []m.AlertRule{
 		items := []m.AlertRule{
 			{
 			{
-				PanelId:     1,
-				DashboardId: testDash.Id,
-				OrgId:       testDash.OrgId,
-				Query:       "Query",
-				QueryRefId:  "A",
-				WarnLevel:   "> 30",
-				CritLevel:   "> 50",
-				Interval:    "10",
-				Title:       "Alerting title",
-				Description: "Alerting description",
-				QueryRange:  "5m",
-				Aggregator:  "avg",
-				State:       "OK",
+				PanelId:      1,
+				DashboardId:  testDash.Id,
+				OrgId:        testDash.OrgId,
+				Query:        "Query",
+				QueryRefId:   "A",
+				WarnLevel:    30,
+				CritLevel:    50,
+				WarnOperator: ">",
+				CritOperator: ">",
+				Interval:     "10",
+				Title:        "Alerting title",
+				Description:  "Alerting description",
+				QueryRange:   "5m",
+				Aggregator:   "avg",
+				State:        "OK",
 			},
 			},
 		}
 		}
 
 
@@ -59,8 +61,10 @@ func TestAlertingDataAccess(t *testing.T) {
 
 
 			So(err2, ShouldBeNil)
 			So(err2, ShouldBeNil)
 			So(query.Result.Interval, ShouldEqual, "10")
 			So(query.Result.Interval, ShouldEqual, "10")
-			So(query.Result.WarnLevel, ShouldEqual, "> 30")
-			So(query.Result.CritLevel, ShouldEqual, "> 50")
+			So(query.Result.WarnLevel, ShouldEqual, 30)
+			So(query.Result.CritLevel, ShouldEqual, 50)
+			So(query.Result.WarnOperator, ShouldEqual, ">")
+			So(query.Result.CritOperator, ShouldEqual, ">")
 			So(query.Result.Query, ShouldEqual, "Query")
 			So(query.Result.Query, ShouldEqual, "Query")
 			So(query.Result.QueryRefId, ShouldEqual, "A")
 			So(query.Result.QueryRefId, ShouldEqual, "A")
 			So(query.Result.Title, ShouldEqual, "Alerting title")
 			So(query.Result.Title, ShouldEqual, "Alerting title")
@@ -177,17 +181,19 @@ func TestAlertingDataAccess(t *testing.T) {
 		Convey("When dashboard is removed", func() {
 		Convey("When dashboard is removed", func() {
 			items := []m.AlertRule{
 			items := []m.AlertRule{
 				{
 				{
-					PanelId:     1,
-					DashboardId: testDash.Id,
-					Query:       "Query",
-					QueryRefId:  "A",
-					WarnLevel:   "> 30",
-					CritLevel:   "> 50",
-					Interval:    "10",
-					Title:       "Alerting title",
-					Description: "Alerting description",
-					QueryRange:  "5m",
-					Aggregator:  "avg",
+					PanelId:      1,
+					DashboardId:  testDash.Id,
+					Query:        "Query",
+					QueryRefId:   "A",
+					WarnLevel:    30,
+					CritLevel:    50,
+					WarnOperator: ">",
+					CritOperator: ">",
+					Interval:     "10",
+					Title:        "Alerting title",
+					Description:  "Alerting description",
+					QueryRange:   "5m",
+					Aggregator:   "avg",
 				},
 				},
 			}
 			}
 
 

+ 14 - 12
pkg/services/sqlstore/alert_state_test.go

@@ -15,18 +15,20 @@ func TestAlertingStateAccess(t *testing.T) {
 
 
 		items := []m.AlertRule{
 		items := []m.AlertRule{
 			{
 			{
-				PanelId:     1,
-				DashboardId: testDash.Id,
-				OrgId:       testDash.OrgId,
-				Query:       "Query",
-				QueryRefId:  "A",
-				WarnLevel:   "> 30",
-				CritLevel:   "> 50",
-				Interval:    "10",
-				Title:       "Alerting title",
-				Description: "Alerting description",
-				QueryRange:  "5m",
-				Aggregator:  "avg",
+				PanelId:      1,
+				DashboardId:  testDash.Id,
+				OrgId:        testDash.OrgId,
+				Query:        "Query",
+				QueryRefId:   "A",
+				WarnLevel:    30,
+				CritLevel:    50,
+				WarnOperator: ">",
+				CritOperator: ">",
+				Interval:     "10",
+				Title:        "Alerting title",
+				Description:  "Alerting description",
+				QueryRange:   "5m",
+				Aggregator:   "avg",
 			},
 			},
 		}
 		}
 
 

+ 4 - 2
pkg/services/sqlstore/migrations/alert_mig.go

@@ -12,8 +12,10 @@ func addAlertMigrations(mg *Migrator) {
 			{Name: "org_id", Type: DB_BigInt, Nullable: false},
 			{Name: "org_id", Type: DB_BigInt, Nullable: false},
 			{Name: "query", Type: DB_Text, Nullable: false},
 			{Name: "query", Type: DB_Text, Nullable: false},
 			{Name: "query_ref_id", Type: DB_NVarchar, Length: 255, Nullable: false},
 			{Name: "query_ref_id", Type: DB_NVarchar, Length: 255, Nullable: false},
-			{Name: "warn_level", Type: DB_NVarchar, Length: 255, Nullable: false},
-			{Name: "crit_level", Type: DB_NVarchar, Length: 255, Nullable: false},
+			{Name: "warn_level", Type: DB_BigInt, Nullable: false},
+			{Name: "warn_operator", Type: DB_NVarchar, Length: 10, Nullable: false},
+			{Name: "crit_level", Type: DB_BigInt, Nullable: false},
+			{Name: "crit_operator", Type: DB_NVarchar, Length: 10, Nullable: false},
 			{Name: "interval", Type: DB_NVarchar, Length: 255, Nullable: false},
 			{Name: "interval", Type: DB_NVarchar, Length: 255, Nullable: false},
 			{Name: "title", Type: DB_NVarchar, Length: 255, Nullable: false},
 			{Name: "title", Type: DB_NVarchar, Length: 255, Nullable: false},
 			{Name: "description", Type: DB_NVarchar, Length: 255, Nullable: false},
 			{Name: "description", Type: DB_NVarchar, Length: 255, Nullable: false},

+ 7 - 18
public/app/plugins/panel/graph/alert_tab_ctrl.ts

@@ -24,36 +24,25 @@ export class AlertTabCtrl {
 
 
   convertThresholdsToAlertThresholds() {
   convertThresholdsToAlertThresholds() {
     if (this.panel.grid && this.panel.grid.threshold1) {
     if (this.panel.grid && this.panel.grid.threshold1) {
-      this.panel.alerting.warnLevel = '< ' + this.panel.grid.threshold1;
+      this.panel.alerting.warnOperator = '<';
+      this.panel.alerting.warnLevel = this.panel.grid.threshold1;
     }
     }
 
 
     if (this.panel.grid && this.panel.grid.threshold2) {
     if (this.panel.grid && this.panel.grid.threshold2) {
-      this.panel.alerting.critLevel = '< ' + this.panel.grid.threshold2;
+      this.panel.alerting.critOperator = '<';
+      this.panel.alerting.critLevel = this.panel.grid.threshold2;
     }
     }
   }
   }
 
 
   thresholdsUpdated() {
   thresholdsUpdated() {
     if (this.panel.alerting.warnLevel) {
     if (this.panel.alerting.warnLevel) {
-      var threshold = this.panel.alerting.warnLevel
-        .replace(' ', '')
-        .replace('>', '')
-        .replace('<', '')
-        .replace('>=', '')
-        .replace('<=', '');
-
-      this.panel.grid.threshold1 = parseInt(threshold);
+      this.panel.grid.threshold1 = parseInt(this.panel.alerting.warnLevel);
     }
     }
 
 
     if (this.panel.alerting.critLevel) {
     if (this.panel.alerting.critLevel) {
-      var threshold = this.panel.alerting.critLevel
-        .replace(' ', '')
-        .replace('>', '')
-        .replace('<', '')
-        .replace('>=', '')
-        .replace('<=', '');
-
-      this.panel.grid.threshold2 = parseInt(threshold);
+      this.panel.grid.threshold2 = parseInt(this.panel.alerting.critLevel);
     }
     }
+
     this.panelCtrl.render();
     this.panelCtrl.render();
   }
   }
 }
 }

+ 8 - 2
public/app/plugins/panel/graph/partials/tab_alerting.html

@@ -16,14 +16,20 @@
         <i class="icon-gf icon-gf-warn alert-state-warn"></i>
         <i class="icon-gf icon-gf-warn alert-state-warn"></i>
         Warn level
         Warn level
       </span>
       </span>
-      <input class="gf-form-input max-width-7" type="text" ng-model="ctrl.panel.alerting.warnLevel" ng-change="alertTab.thresholdsUpdated()"></input>
+      <div class="gf-form-select-wrapper max-width-10">
+        <select class="gf-form-input" ng-model="ctrl.panel.alerting.warnOperator" ng-options="oper as oper for oper in ['>', '<', '<=', '>=']"></select>
+      </div>
+      <input class="gf-form-input max-width-7" type="number" ng-model="ctrl.panel.alerting.warnLevel" ng-change="alertTab.thresholdsUpdated()"></input>
     </div>
     </div>
     <div class="gf-form">
     <div class="gf-form">
       <span class="gf-form-label width-9">
       <span class="gf-form-label width-9">
         <i class="icon-gf icon-gf-critical alert-state-critical"></i>
         <i class="icon-gf icon-gf-critical alert-state-critical"></i>
         Critical level
         Critical level
       </span>
       </span>
-      <input class="gf-form-input max-width-7" type="text" ng-model="ctrl.panel.alerting.critLevel" ng-change="alertTab.thresholdsUpdated()"></input>
+      <div class="gf-form-select-wrapper max-width-10">
+        <select class="gf-form-input" ng-model="ctrl.panel.alerting.critOperator" ng-options="oper as oper for oper in ['>', '<', '<=', '>=']"></select>
+      </div>
+      <input class="gf-form-input max-width-7" type="number" ng-model="ctrl.panel.alerting.critLevel" ng-change="alertTab.thresholdsUpdated()"></input>
     </div>
     </div>
   </div>
   </div>
 
 

+ 0 - 3
public/sass/components/_alerts.scss

@@ -8,17 +8,14 @@
 
 
 
 
 .alert-state-online {
 .alert-state-online {
-  //background-image: url('/img/online.svg');
   color: $online;
   color: $online;
 }
 }
 
 
 .alert-state-warn {
 .alert-state-warn {
-  //background-image: url('/img/warn-tiny.svg');
   color: $warn;
   color: $warn;
 }
 }
 
 
 .alert-state-critical {
 .alert-state-critical {
-  //background-image: url('/img/critical.svg');
   color: $critical;
   color: $critical;
 }
 }