Browse Source

Merge pull request #6996 from bergquist/pause_all_alerts

Pause all alerts
Carl Bergquist 9 years ago
parent
commit
9135abf3ae

+ 31 - 4
pkg/api/alerting.go

@@ -259,10 +259,11 @@ func NotificationTest(c *middleware.Context, dto dtos.NotificationTestCommand) R
 
 //POST /api/alerts/:alertId/pause
 func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response {
+	alertId := c.ParamsInt64("alertId")
 	cmd := models.PauseAlertCommand{
-		OrgId:   c.OrgId,
-		AlertId: c.ParamsInt64("alertId"),
-		Paused:  dto.Paused,
+		OrgId:    c.OrgId,
+		AlertIds: []int64{alertId},
+		Paused:   dto.Paused,
 	}
 
 	if err := bus.Dispatch(&cmd); err != nil {
@@ -277,10 +278,36 @@ func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response {
 	}
 
 	result := map[string]interface{}{
-		"alertId": cmd.AlertId,
+		"alertId": alertId,
 		"state":   response,
 		"message": "alert " + pausedState,
 	}
 
 	return Json(200, result)
 }
+
+//POST /api/admin/pause-all-alerts
+func PauseAllAlerts(c *middleware.Context, dto dtos.PauseAllAlertsCommand) Response {
+	updateCmd := models.PauseAllAlertCommand{
+		Paused: dto.Paused,
+	}
+
+	if err := bus.Dispatch(&updateCmd); err != nil {
+		return ApiError(500, "Failed to pause alerts", err)
+	}
+
+	var response models.AlertStateType = models.AlertStatePending
+	pausedState := "un paused"
+	if updateCmd.Paused {
+		response = models.AlertStatePaused
+		pausedState = "paused"
+	}
+
+	result := map[string]interface{}{
+		"state":          response,
+		"message":        "alert " + pausedState,
+		"alertsAffected": updateCmd.ResultCount,
+	}
+
+	return Json(200, result)
+}

+ 1 - 0
pkg/api/api.go

@@ -289,6 +289,7 @@ func Register(r *macaron.Macaron) {
 		r.Get("/users/:id/quotas", wrap(GetUserQuotas))
 		r.Put("/users/:id/quotas/:target", bind(m.UpdateUserQuotaCmd{}), wrap(UpdateUserQuota))
 		r.Get("/stats", AdminGetStats)
+		r.Post("/pause-all-alerts", bind(dtos.PauseAllAlertsCommand{}), wrap(PauseAllAlerts))
 	}, reqGrafanaAdmin)
 
 	// rendering

+ 4 - 0
pkg/api/dtos/alerting.go

@@ -64,3 +64,7 @@ type PauseAlertCommand struct {
 	AlertId int64 `json:"alertId"`
 	Paused  bool  `json:"paused"`
 }
+
+type PauseAllAlertsCommand struct {
+	Paused bool `json:"paused"`
+}

+ 15 - 3
pkg/models/alert.go

@@ -3,6 +3,8 @@ package models
 import (
 	"time"
 
+	"fmt"
+
 	"github.com/grafana/grafana/pkg/components/simplejson"
 )
 
@@ -31,6 +33,10 @@ const (
 	ExecutionErrorKeepState   ExecutionErrorOption = "keep_state"
 )
 
+var (
+	ErrCannotChangeStateOnPausedAlert error = fmt.Errorf("Cannot change state on pause alert")
+)
+
 func (s AlertStateType) IsValid() bool {
 	return s == AlertStateOK || s == AlertStateNoData || s == AlertStatePaused || s == AlertStatePending
 }
@@ -132,9 +138,15 @@ type SaveAlertsCommand struct {
 }
 
 type PauseAlertCommand struct {
-	OrgId   int64
-	AlertId int64
-	Paused  bool
+	OrgId       int64
+	AlertIds    []int64
+	ResultCount int64
+	Paused      bool
+}
+
+type PauseAllAlertCommand struct {
+	ResultCount int64
+	Paused      bool
 }
 
 type SetAlertStateCommand struct {

+ 4 - 0
pkg/services/alerting/result_handler.go

@@ -86,6 +86,10 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error {
 		}
 
 		if err := bus.Dispatch(cmd); err != nil {
+			if err == m.ErrCannotChangeStateOnPausedAlert {
+				handler.log.Error("Cannot change state on alert thats pause", "error", err)
+				return err
+			}
 			handler.log.Error("Failed to save state", "error", err)
 		}
 

+ 40 - 11
pkg/services/sqlstore/alert.go

@@ -3,6 +3,7 @@ package sqlstore
 import (
 	"bytes"
 	"fmt"
+	"strings"
 	"time"
 
 	"github.com/go-xorm/xorm"
@@ -18,7 +19,8 @@ func init() {
 	bus.AddHandler("sql", GetAllAlertQueryHandler)
 	bus.AddHandler("sql", SetAlertState)
 	bus.AddHandler("sql", GetAlertStatesForDashboard)
-	bus.AddHandler("sql", PauseAlertRule)
+	bus.AddHandler("sql", PauseAlert)
+	bus.AddHandler("sql", PauseAllAlerts)
 }
 
 func GetAlertById(query *m.GetAlertByIdQuery) error {
@@ -228,6 +230,10 @@ func SetAlertState(cmd *m.SetAlertStateCommand) error {
 			return fmt.Errorf("Could not find alert")
 		}
 
+		if alert.State == m.AlertStatePaused {
+			return m.ErrCannotChangeStateOnPausedAlert
+		}
+
 		alert.State = cmd.State
 		alert.StateChanges += 1
 		alert.NewStateDate = time.Now()
@@ -244,27 +250,50 @@ func SetAlertState(cmd *m.SetAlertStateCommand) error {
 	})
 }
 
-func PauseAlertRule(cmd *m.PauseAlertCommand) error {
+func PauseAlert(cmd *m.PauseAlertCommand) error {
 	return inTransaction(func(sess *xorm.Session) error {
-		alert := m.Alert{}
+		if len(cmd.AlertIds) == 0 {
+			return fmt.Errorf("command contains no alertids")
+		}
+
+		var buffer bytes.Buffer
+		params := make([]interface{}, 0)
 
-		has, err := x.Where("id = ? AND org_id=?", cmd.AlertId, cmd.OrgId).Get(&alert)
+		buffer.WriteString(`UPDATE alert SET state = ?`)
+		if cmd.Paused {
+			params = append(params, string(m.AlertStatePaused))
+		} else {
+			params = append(params, string(m.AlertStatePending))
+		}
+
+		buffer.WriteString(` WHERE id IN (?` + strings.Repeat(",?", len(cmd.AlertIds)-1) + `)`)
+		for _, v := range cmd.AlertIds {
+			params = append(params, v)
+		}
 
+		res, err := sess.Exec(buffer.String(), params...)
 		if err != nil {
 			return err
-		} else if !has {
-			return fmt.Errorf("Could not find alert")
 		}
+		cmd.ResultCount, _ = res.RowsAffected()
+		return nil
+	})
+}
 
-		var newState m.AlertStateType
+func PauseAllAlerts(cmd *m.PauseAllAlertCommand) error {
+	return inTransaction(func(sess *xorm.Session) error {
+		var newState string
 		if cmd.Paused {
-			newState = m.AlertStatePaused
+			newState = string(m.AlertStatePaused)
 		} else {
-			newState = m.AlertStatePending
+			newState = string(m.AlertStatePending)
 		}
-		alert.State = newState
 
-		sess.Id(alert.Id).Update(&alert)
+		res, err := sess.Exec(`UPDATE alert SET state = ?`, newState)
+		if err != nil {
+			return err
+		}
+		cmd.ResultCount, _ = res.RowsAffected()
 		return nil
 	})
 }

+ 0 - 18
pkg/services/sqlstore/alert_heartbeat_test.go

@@ -1,18 +0,0 @@
-package sqlstore
-
-import (
-	"testing"
-
-	//	m "github.com/grafana/grafana/pkg/models"
-	. "github.com/smartystreets/goconvey/convey"
-)
-
-func TestAlertingHeartbeatDataAccess(t *testing.T) {
-
-	Convey("Testing Alerting data access", t, func() {
-		InitTestDB(t)
-		//send heartbeat from server 1
-		//send heartbeat from server 2
-
-	})
-}

+ 31 - 0
pkg/services/sqlstore/alert_test.go

@@ -39,6 +39,37 @@ func TestAlertingDataAccess(t *testing.T) {
 			So(err, ShouldBeNil)
 		})
 
+		Convey("Can set new states", func() {
+			Convey("new state ok", func() {
+				cmd := &m.SetAlertStateCommand{
+					AlertId: 1,
+					State:   m.AlertStateOK,
+				}
+
+				err = SetAlertState(cmd)
+				So(err, ShouldBeNil)
+			})
+
+			Convey("can pause alert", func() {
+				cmd := &m.PauseAllAlertCommand{
+					Paused: true,
+				}
+
+				err = PauseAllAlerts(cmd)
+				So(err, ShouldBeNil)
+
+				Convey("cannot updated paused alert", func() {
+					cmd := &m.SetAlertStateCommand{
+						AlertId: 1,
+						State:   m.AlertStateOK,
+					}
+
+					err = SetAlertState(cmd)
+					So(err, ShouldNotBeNil)
+				})
+			})
+		})
+
 		Convey("Can read properties", func() {
 			alertQuery := m.GetAlertsQuery{DashboardId: testDash.Id, PanelId: 1, OrgId: 1}
 			err2 := HandleAlertsQuery(&alertQuery)