Browse Source

Merge pull request #10942 from grafana/pausing_alerts_updates_timestamp

Pausing/un alerts now updates new_state_date
Carl Bergquist 7 years ago
parent
commit
3f6e525755
2 changed files with 135 additions and 15 deletions
  1. 14 9
      pkg/services/sqlstore/alert.go
  2. 121 6
      pkg/services/sqlstore/alert_test.go

+ 14 - 9
pkg/services/sqlstore/alert.go

@@ -10,6 +10,9 @@ import (
 	m "github.com/grafana/grafana/pkg/models"
 )
 
+// timeNow makes it possible to test usage of time
+var timeNow = time.Now
+
 func init() {
 	bus.AddHandler("sql", SaveAlerts)
 	bus.AddHandler("sql", HandleAlertsQuery)
@@ -147,7 +150,7 @@ func SaveAlerts(cmd *m.SaveAlertsCommand) error {
 			return err
 		}
 
-		if err := upsertAlerts(existingAlerts, cmd, sess); err != nil {
+		if err := updateAlerts(existingAlerts, cmd, sess); err != nil {
 			return err
 		}
 
@@ -159,7 +162,7 @@ func SaveAlerts(cmd *m.SaveAlertsCommand) error {
 	})
 }
 
-func upsertAlerts(existingAlerts []*m.Alert, cmd *m.SaveAlertsCommand, sess *DBSession) error {
+func updateAlerts(existingAlerts []*m.Alert, cmd *m.SaveAlertsCommand, sess *DBSession) error {
 	for _, alert := range cmd.Alerts {
 		update := false
 		var alertToUpdate *m.Alert
@@ -175,7 +178,7 @@ func upsertAlerts(existingAlerts []*m.Alert, cmd *m.SaveAlertsCommand, sess *DBS
 
 		if update {
 			if alertToUpdate.ContainsUpdates(alert) {
-				alert.Updated = time.Now()
+				alert.Updated = timeNow()
 				alert.State = alertToUpdate.State
 				sess.MustCols("message")
 				_, err := sess.Id(alert.Id).Update(alert)
@@ -186,10 +189,10 @@ func upsertAlerts(existingAlerts []*m.Alert, cmd *m.SaveAlertsCommand, sess *DBS
 				sqlog.Debug("Alert updated", "name", alert.Name, "id", alert.Id)
 			}
 		} else {
-			alert.Updated = time.Now()
-			alert.Created = time.Now()
+			alert.Updated = timeNow()
+			alert.Created = timeNow()
 			alert.State = m.AlertStatePending
-			alert.NewStateDate = time.Now()
+			alert.NewStateDate = timeNow()
 
 			_, err := sess.Insert(alert)
 			if err != nil {
@@ -253,7 +256,7 @@ func SetAlertState(cmd *m.SetAlertStateCommand) error {
 
 		alert.State = cmd.State
 		alert.StateChanges += 1
-		alert.NewStateDate = time.Now()
+		alert.NewStateDate = timeNow()
 		alert.EvalData = cmd.EvalData
 
 		if cmd.Error == "" {
@@ -276,11 +279,13 @@ func PauseAlert(cmd *m.PauseAlertCommand) error {
 		var buffer bytes.Buffer
 		params := make([]interface{}, 0)
 
-		buffer.WriteString(`UPDATE alert SET state = ?`)
+		buffer.WriteString(`UPDATE alert SET state = ?, new_state_date = ?`)
 		if cmd.Paused {
 			params = append(params, string(m.AlertStatePaused))
+			params = append(params, timeNow())
 		} else {
 			params = append(params, string(m.AlertStatePending))
+			params = append(params, timeNow())
 		}
 
 		buffer.WriteString(` WHERE id IN (?` + strings.Repeat(",?", len(cmd.AlertIds)-1) + `)`)
@@ -306,7 +311,7 @@ func PauseAllAlerts(cmd *m.PauseAllAlertCommand) error {
 			newState = string(m.AlertStatePending)
 		}
 
-		res, err := sess.Exec(`UPDATE alert SET state = ?`, newState)
+		res, err := sess.Exec(`UPDATE alert SET state = ?, new_state_date = ?`, newState, timeNow())
 		if err != nil {
 			return err
 		}

+ 121 - 6
pkg/services/sqlstore/alert_test.go

@@ -6,9 +6,26 @@ import (
 	"github.com/grafana/grafana/pkg/components/simplejson"
 	m "github.com/grafana/grafana/pkg/models"
 	. "github.com/smartystreets/goconvey/convey"
+	"time"
 )
 
+func mockTimeNow() {
+	var timeSeed int64
+	timeNow = func() time.Time {
+		fakeNow := time.Unix(timeSeed, 0)
+		timeSeed += 1
+		return fakeNow
+	}
+}
+
+func resetTimeNow() {
+	timeNow = time.Now
+}
+
 func TestAlertingDataAccess(t *testing.T) {
+	mockTimeNow()
+	defer resetTimeNow()
+
 	Convey("Testing Alerting data access", t, func() {
 		InitTestDB(t)
 
@@ -50,13 +67,11 @@ func TestAlertingDataAccess(t *testing.T) {
 				So(err, ShouldBeNil)
 			})
 
-			Convey("can pause alert", func() {
-				cmd := &m.PauseAllAlertCommand{
-					Paused: true,
-				}
+			alert, _ := getAlertById(1)
+			stateDateBeforePause := alert.NewStateDate
 
-				err = PauseAllAlerts(cmd)
-				So(err, ShouldBeNil)
+			Convey("can pause all alerts", func() {
+				pauseAllAlerts(true)
 
 				Convey("cannot updated paused alert", func() {
 					cmd := &m.SetAlertStateCommand{
@@ -67,6 +82,19 @@ func TestAlertingDataAccess(t *testing.T) {
 					err = SetAlertState(cmd)
 					So(err, ShouldNotBeNil)
 				})
+
+				Convey("pausing alerts should update their NewStateDate", func() {
+					alert, _ = getAlertById(1)
+					stateDateAfterPause := alert.NewStateDate
+					So(stateDateBeforePause, ShouldHappenBefore, stateDateAfterPause)
+				})
+
+				Convey("unpausing alerts should update their NewStateDate again", func() {
+					pauseAllAlerts(false)
+					alert, _ = getAlertById(1)
+					stateDateAfterUnpause := alert.NewStateDate
+					So(stateDateBeforePause, ShouldHappenBefore, stateDateAfterUnpause)
+				})
 			})
 		})
 
@@ -214,3 +242,90 @@ func TestAlertingDataAccess(t *testing.T) {
 		})
 	})
 }
+
+func TestPausingAlerts(t *testing.T) {
+	mockTimeNow()
+	defer resetTimeNow()
+
+	Convey("Given an alert", t, func() {
+		InitTestDB(t)
+
+		testDash := insertTestDashboard("dashboard with alerts", 1, 0, false, "alert")
+		alert, _ := insertTestAlert("Alerting title", "Alerting message", testDash.OrgId, testDash.Id, simplejson.New())
+
+		stateDateBeforePause := alert.NewStateDate
+		stateDateAfterPause := stateDateBeforePause
+		Convey("when paused", func() {
+			pauseAlert(testDash.OrgId, 1, true)
+
+			Convey("the NewStateDate should be updated", func() {
+				alert, _ := getAlertById(1)
+
+				stateDateAfterPause = alert.NewStateDate
+				So(stateDateBeforePause, ShouldHappenBefore, stateDateAfterPause)
+			})
+		})
+
+		Convey("when unpaused", func() {
+			pauseAlert(testDash.OrgId, 1, false)
+
+			Convey("the NewStateDate should be updated again", func() {
+				alert, _ := getAlertById(1)
+
+				stateDateAfterUnpause := alert.NewStateDate
+				So(stateDateAfterPause, ShouldHappenBefore, stateDateAfterUnpause)
+			})
+		})
+	})
+}
+func pauseAlert(orgId int64, alertId int64, pauseState bool) (int64, error) {
+	cmd := &m.PauseAlertCommand{
+		OrgId:    orgId,
+		AlertIds: []int64{alertId},
+		Paused:   pauseState,
+	}
+	err := PauseAlert(cmd)
+	So(err, ShouldBeNil)
+	return cmd.ResultCount, err
+}
+func insertTestAlert(title string, message string, orgId int64, dashId int64, settings *simplejson.Json) (*m.Alert, error) {
+	items := []*m.Alert{
+		{
+			PanelId:     1,
+			DashboardId: dashId,
+			OrgId:       orgId,
+			Name:        title,
+			Message:     message,
+			Settings:    settings,
+			Frequency:   1,
+		},
+	}
+
+	cmd := m.SaveAlertsCommand{
+		Alerts:      items,
+		DashboardId: dashId,
+		OrgId:       orgId,
+		UserId:      1,
+	}
+
+	err := SaveAlerts(&cmd)
+	return cmd.Alerts[0], err
+}
+
+func getAlertById(id int64) (*m.Alert, error) {
+	q := &m.GetAlertByIdQuery{
+		Id: id,
+	}
+	err := GetAlertById(q)
+	So(err, ShouldBeNil)
+	return q.Result, err
+}
+
+func pauseAllAlerts(pauseState bool) error {
+	cmd := &m.PauseAllAlertCommand{
+		Paused: pauseState,
+	}
+	err := PauseAllAlerts(cmd)
+	So(err, ShouldBeNil)
+	return err
+}