mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			283 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			283 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Go
		
	
	
	
| package alerting
 | |
| 
 | |
| import (
 | |
| 	"io/ioutil"
 | |
| 	"testing"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/grafana/grafana/pkg/bus"
 | |
| 	"github.com/grafana/grafana/pkg/components/simplejson"
 | |
| 	m "github.com/grafana/grafana/pkg/models"
 | |
| 	"github.com/grafana/grafana/pkg/services/sqlstore"
 | |
| 	. "github.com/smartystreets/goconvey/convey"
 | |
| )
 | |
| 
 | |
| func TestAlertRuleExtraction(t *testing.T) {
 | |
| 
 | |
| 	Convey("Parsing alert rules  from dashboard json", t, func() {
 | |
| 
 | |
| 		RegisterCondition("query", func(model *simplejson.Json, index int) (Condition, error) {
 | |
| 			return &FakeCondition{}, nil
 | |
| 		})
 | |
| 
 | |
| 		// mock data
 | |
| 		defaultDs := &m.DataSource{Id: 12, OrgId: 1, Name: "I am default", IsDefault: true}
 | |
| 		graphite2Ds := &m.DataSource{Id: 15, OrgId: 1, Name: "graphite2"}
 | |
| 		influxDBDs := &m.DataSource{Id: 16, OrgId: 1, Name: "InfluxDB"}
 | |
| 		prom := &m.DataSource{Id: 17, OrgId: 1, Name: "Prometheus"}
 | |
| 
 | |
| 		bus.AddHandler("test", func(query *m.GetDataSourcesQuery) error {
 | |
| 			query.Result = []*m.DataSource{defaultDs, graphite2Ds}
 | |
| 			return nil
 | |
| 		})
 | |
| 
 | |
| 		bus.AddHandler("test", func(query *m.GetDataSourceByNameQuery) error {
 | |
| 			if query.Name == defaultDs.Name {
 | |
| 				query.Result = defaultDs
 | |
| 			}
 | |
| 			if query.Name == graphite2Ds.Name {
 | |
| 				query.Result = graphite2Ds
 | |
| 			}
 | |
| 			if query.Name == influxDBDs.Name {
 | |
| 				query.Result = influxDBDs
 | |
| 			}
 | |
| 			if query.Name == prom.Name {
 | |
| 				query.Result = prom
 | |
| 			}
 | |
| 
 | |
| 			return nil
 | |
| 		})
 | |
| 
 | |
| 		json, err := ioutil.ReadFile("./testdata/graphite-alert.json")
 | |
| 		So(err, ShouldBeNil)
 | |
| 
 | |
| 		Convey("Extractor should not modify the original json", func() {
 | |
| 			dashJson, err := simplejson.NewJson(json)
 | |
| 			So(err, ShouldBeNil)
 | |
| 
 | |
| 			dash := m.NewDashboardFromJson(dashJson)
 | |
| 
 | |
| 			getTarget := func(j *simplejson.Json) string {
 | |
| 				rowObj := j.Get("rows").MustArray()[0]
 | |
| 				row := simplejson.NewFromAny(rowObj)
 | |
| 				panelObj := row.Get("panels").MustArray()[0]
 | |
| 				panel := simplejson.NewFromAny(panelObj)
 | |
| 				conditionObj := panel.Get("alert").Get("conditions").MustArray()[0]
 | |
| 				condition := simplejson.NewFromAny(conditionObj)
 | |
| 				return condition.Get("query").Get("model").Get("target").MustString()
 | |
| 			}
 | |
| 
 | |
| 			Convey("Dashboard json rows.panels.alert.query.model.target should be empty", func() {
 | |
| 				So(getTarget(dashJson), ShouldEqual, "")
 | |
| 			})
 | |
| 
 | |
| 			extractor := NewDashAlertExtractor(dash, 1, nil)
 | |
| 			_, _ = extractor.GetAlerts()
 | |
| 
 | |
| 			Convey("Dashboard json should not be updated after extracting rules", func() {
 | |
| 				So(getTarget(dashJson), ShouldEqual, "")
 | |
| 			})
 | |
| 		})
 | |
| 
 | |
| 		Convey("Parsing and validating dashboard containing graphite alerts", func() {
 | |
| 
 | |
| 			dashJson, err := simplejson.NewJson(json)
 | |
| 			So(err, ShouldBeNil)
 | |
| 
 | |
| 			dash := m.NewDashboardFromJson(dashJson)
 | |
| 			extractor := NewDashAlertExtractor(dash, 1, nil)
 | |
| 
 | |
| 			alerts, err := extractor.GetAlerts()
 | |
| 
 | |
| 			Convey("Get rules without error", func() {
 | |
| 				So(err, ShouldBeNil)
 | |
| 			})
 | |
| 
 | |
| 			Convey("all properties have been set", func() {
 | |
| 				So(len(alerts), ShouldEqual, 2)
 | |
| 
 | |
| 				for _, v := range alerts {
 | |
| 					So(v.DashboardId, ShouldEqual, 57)
 | |
| 					So(v.Name, ShouldNotBeEmpty)
 | |
| 					So(v.Message, ShouldNotBeEmpty)
 | |
| 
 | |
| 					settings := simplejson.NewFromAny(v.Settings)
 | |
| 					So(settings.Get("interval").MustString(""), ShouldEqual, "")
 | |
| 				}
 | |
| 
 | |
| 				Convey("should extract handler property", func() {
 | |
| 					So(alerts[0].Handler, ShouldEqual, 1)
 | |
| 					So(alerts[1].Handler, ShouldEqual, 0)
 | |
| 				})
 | |
| 
 | |
| 				Convey("should extract frequency in seconds", func() {
 | |
| 					So(alerts[0].Frequency, ShouldEqual, 60)
 | |
| 					So(alerts[1].Frequency, ShouldEqual, 60)
 | |
| 				})
 | |
| 
 | |
| 				Convey("should extract panel idc", func() {
 | |
| 					So(alerts[0].PanelId, ShouldEqual, 3)
 | |
| 					So(alerts[1].PanelId, ShouldEqual, 4)
 | |
| 				})
 | |
| 
 | |
| 				Convey("should extract for param", func() {
 | |
| 					So(alerts[0].For, ShouldEqual, time.Minute*2)
 | |
| 					So(alerts[1].For, ShouldEqual, time.Duration(0))
 | |
| 				})
 | |
| 
 | |
| 				Convey("should extract name and desc", func() {
 | |
| 					So(alerts[0].Name, ShouldEqual, "name1")
 | |
| 					So(alerts[0].Message, ShouldEqual, "desc1")
 | |
| 					So(alerts[1].Name, ShouldEqual, "name2")
 | |
| 					So(alerts[1].Message, 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)")
 | |
| 				})
 | |
| 			})
 | |
| 		})
 | |
| 
 | |
| 		Convey("Panels missing id should return error", func() {
 | |
| 			panelWithoutId, err := ioutil.ReadFile("./testdata/panels-missing-id.json")
 | |
| 			So(err, ShouldBeNil)
 | |
| 
 | |
| 			dashJson, err := simplejson.NewJson(panelWithoutId)
 | |
| 			So(err, ShouldBeNil)
 | |
| 			dash := m.NewDashboardFromJson(dashJson)
 | |
| 			extractor := NewDashAlertExtractor(dash, 1, nil)
 | |
| 
 | |
| 			_, err = extractor.GetAlerts()
 | |
| 
 | |
| 			Convey("panels without Id should return error", func() {
 | |
| 				So(err, ShouldNotBeNil)
 | |
| 			})
 | |
| 		})
 | |
| 
 | |
| 		Convey("Panel with id set to zero should return error", func() {
 | |
| 			panelWithIdZero, err := ioutil.ReadFile("./testdata/panel-with-id-0.json")
 | |
| 			So(err, ShouldBeNil)
 | |
| 
 | |
| 			dashJson, err := simplejson.NewJson(panelWithIdZero)
 | |
| 			So(err, ShouldBeNil)
 | |
| 			dash := m.NewDashboardFromJson(dashJson)
 | |
| 			extractor := NewDashAlertExtractor(dash, 1, nil)
 | |
| 
 | |
| 			_, err = extractor.GetAlerts()
 | |
| 
 | |
| 			Convey("panel with id 0 should return error", func() {
 | |
| 				So(err, ShouldNotBeNil)
 | |
| 			})
 | |
| 		})
 | |
| 
 | |
| 		Convey("Parse alerts from dashboard without rows", func() {
 | |
| 			json, err := ioutil.ReadFile("./testdata/v5-dashboard.json")
 | |
| 			So(err, ShouldBeNil)
 | |
| 
 | |
| 			dashJson, err := simplejson.NewJson(json)
 | |
| 			So(err, ShouldBeNil)
 | |
| 			dash := m.NewDashboardFromJson(dashJson)
 | |
| 			extractor := NewDashAlertExtractor(dash, 1, nil)
 | |
| 
 | |
| 			alerts, err := extractor.GetAlerts()
 | |
| 
 | |
| 			Convey("Get rules without error", func() {
 | |
| 				So(err, ShouldBeNil)
 | |
| 			})
 | |
| 
 | |
| 			Convey("Should have 2 alert rule", func() {
 | |
| 				So(len(alerts), ShouldEqual, 2)
 | |
| 			})
 | |
| 		})
 | |
| 
 | |
| 		Convey("Alert notifications are in DB", func() {
 | |
| 			sqlstore.InitTestDB(t)
 | |
| 			firstNotification := m.CreateAlertNotificationCommand{Uid: "notifier1", OrgId: 1, Name: "1"}
 | |
| 			err = sqlstore.CreateAlertNotificationCommand(&firstNotification)
 | |
| 			So(err, ShouldBeNil)
 | |
| 			secondNotification := m.CreateAlertNotificationCommand{Uid: "notifier2", OrgId: 1, Name: "2"}
 | |
| 			err = sqlstore.CreateAlertNotificationCommand(&secondNotification)
 | |
| 			So(err, ShouldBeNil)
 | |
| 
 | |
| 			Convey("Parse and validate dashboard containing influxdb alert", func() {
 | |
| 				json, err := ioutil.ReadFile("./testdata/influxdb-alert.json")
 | |
| 				So(err, ShouldBeNil)
 | |
| 
 | |
| 				dashJson, err := simplejson.NewJson(json)
 | |
| 				So(err, ShouldBeNil)
 | |
| 				dash := m.NewDashboardFromJson(dashJson)
 | |
| 				extractor := NewDashAlertExtractor(dash, 1, nil)
 | |
| 
 | |
| 				alerts, err := extractor.GetAlerts()
 | |
| 
 | |
| 				Convey("Get rules without error", func() {
 | |
| 					So(err, ShouldBeNil)
 | |
| 				})
 | |
| 
 | |
| 				Convey("should be able to read interval", func() {
 | |
| 					So(len(alerts), ShouldEqual, 1)
 | |
| 
 | |
| 					for _, alert := range alerts {
 | |
| 						So(alert.DashboardId, ShouldEqual, 4)
 | |
| 
 | |
| 						conditions := alert.Settings.Get("conditions").MustArray()
 | |
| 						cond := simplejson.NewFromAny(conditions[0])
 | |
| 
 | |
| 						So(cond.Get("query").Get("model").Get("interval").MustString(), ShouldEqual, ">10s")
 | |
| 					}
 | |
| 				})
 | |
| 			})
 | |
| 
 | |
| 			Convey("Should be able to extract collapsed panels", func() {
 | |
| 				json, err := ioutil.ReadFile("./testdata/collapsed-panels.json")
 | |
| 				So(err, ShouldBeNil)
 | |
| 
 | |
| 				dashJson, err := simplejson.NewJson(json)
 | |
| 				So(err, ShouldBeNil)
 | |
| 
 | |
| 				dash := m.NewDashboardFromJson(dashJson)
 | |
| 				extractor := NewDashAlertExtractor(dash, 1, nil)
 | |
| 
 | |
| 				alerts, err := extractor.GetAlerts()
 | |
| 
 | |
| 				Convey("Get rules without error", func() {
 | |
| 					So(err, ShouldBeNil)
 | |
| 				})
 | |
| 
 | |
| 				Convey("should be able to extract collapsed alerts", func() {
 | |
| 					So(len(alerts), ShouldEqual, 4)
 | |
| 				})
 | |
| 			})
 | |
| 
 | |
| 			Convey("Parse and validate dashboard without id and containing an alert", func() {
 | |
| 				json, err := ioutil.ReadFile("./testdata/dash-without-id.json")
 | |
| 				So(err, ShouldBeNil)
 | |
| 
 | |
| 				dashJSON, err := simplejson.NewJson(json)
 | |
| 				So(err, ShouldBeNil)
 | |
| 				dash := m.NewDashboardFromJson(dashJSON)
 | |
| 				extractor := NewDashAlertExtractor(dash, 1, nil)
 | |
| 
 | |
| 				err = extractor.ValidateAlerts()
 | |
| 
 | |
| 				Convey("Should validate without error", func() {
 | |
| 					So(err, ShouldBeNil)
 | |
| 				})
 | |
| 
 | |
| 				Convey("Should fail on save", func() {
 | |
| 					_, err := extractor.GetAlerts()
 | |
| 					So(err.Error(), ShouldEqual, "Alert validation error: Panel id is not correct, alertName=Influxdb, panelId=1")
 | |
| 				})
 | |
| 			})
 | |
| 		})
 | |
| 	})
 | |
| }
 |