Browse Source

Merge branch 'pause_alert_rules'

closes #6135
bergquist 9 years ago
parent
commit
446bde2421

+ 20 - 23
pkg/api/alerting.go

@@ -252,33 +252,30 @@ func NotificationTest(c *middleware.Context, dto dtos.NotificationTestCommand) R
 	return ApiSuccess("Test notification sent")
 }
 
-func getAlertIdForRequest(c *middleware.Context) (int64, error) {
-	alertId := c.QueryInt64("alertId")
-	panelId := c.QueryInt64("panelId")
-	dashboardId := c.QueryInt64("dashboardId")
-
-	if alertId == 0 && dashboardId == 0 && panelId == 0 {
-		return 0, fmt.Errorf("Missing alertId or dashboardId and panelId")
+//POST /api/:alertId/pause
+func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response {
+	cmd := models.PauseAlertCommand{
+		OrgId:   c.OrgId,
+		AlertId: c.ParamsInt64("alertId"),
+		Paused:  dto.Paused,
 	}
 
-	if alertId == 0 {
-		//fetch alertId
-		query := models.GetAlertsQuery{
-			OrgId:       c.OrgId,
-			DashboardId: dashboardId,
-			PanelId:     panelId,
-		}
-
-		if err := bus.Dispatch(&query); err != nil {
-			return 0, err
-		}
+	if err := bus.Dispatch(&cmd); err != nil {
+		return ApiError(500, "", err)
+	}
 
-		if len(query.Result) != 1 {
-			return 0, fmt.Errorf("PanelId is not unique on dashboard")
-		}
+	var response models.AlertStateType = models.AlertStateNoData
+	pausedState := "un paused"
+	if cmd.Paused {
+		response = models.AlertStatePaused
+		pausedState = "paused"
+	}
 
-		alertId = query.Result[0].Id
+	result := map[string]interface{}{
+		"alertId": cmd.AlertId,
+		"state":   response,
+		"message": "alert " + pausedState,
 	}
 
-	return alertId, nil
+	return Json(200, result)
 }

+ 1 - 0
pkg/api/api.go

@@ -252,6 +252,7 @@ func Register(r *macaron.Macaron) {
 
 		r.Group("/alerts", func() {
 			r.Post("/test", bind(dtos.AlertTestCommand{}), wrap(AlertTest))
+			r.Post("/:alertId/pause", ValidateOrgAlert, bind(dtos.PauseAlertCommand{}), wrap(PauseAlert))
 			r.Get("/:alertId", ValidateOrgAlert, wrap(GetAlert))
 			r.Get("/", wrap(GetAlerts))
 			r.Get("/states-for-dashboard", wrap(GetAlertStatesForDashboard))

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

@@ -58,3 +58,8 @@ type NotificationTestCommand struct {
 	Type     string           `json:"type"`
 	Settings *simplejson.Json `json:"settings"`
 }
+
+type PauseAlertCommand struct {
+	AlertId int64 `json:"alertId"`
+	Paused  bool  `json:"paused"`
+}

+ 6 - 0
pkg/models/alert.go

@@ -101,6 +101,12 @@ type SaveAlertsCommand struct {
 	Alerts []*Alert
 }
 
+type PauseAlertCommand struct {
+	OrgId   int64
+	AlertId int64
+	Paused  bool
+}
+
 type SetAlertStateCommand struct {
 	AlertId  int64
 	OrgId    int64

+ 2 - 1
pkg/services/alerting/scheduler.go

@@ -5,6 +5,7 @@ import (
 	"time"
 
 	"github.com/grafana/grafana/pkg/log"
+	"github.com/grafana/grafana/pkg/models"
 )
 
 type SchedulerImpl struct {
@@ -48,7 +49,7 @@ func (s *SchedulerImpl) Tick(tickTime time.Time, execQueue chan *Job) {
 	now := tickTime.Unix()
 
 	for _, job := range s.jobs {
-		if job.Running {
+		if job.Running || job.Rule.State == models.AlertStatePaused {
 			continue
 		}
 

+ 24 - 0
pkg/services/sqlstore/alert.go

@@ -18,6 +18,7 @@ func init() {
 	bus.AddHandler("sql", GetAllAlertQueryHandler)
 	bus.AddHandler("sql", SetAlertState)
 	bus.AddHandler("sql", GetAlertStatesForDashboard)
+	bus.AddHandler("sql", PauseAlertRule)
 }
 
 func GetAlertById(query *m.GetAlertByIdQuery) error {
@@ -243,6 +244,29 @@ func SetAlertState(cmd *m.SetAlertStateCommand) error {
 	})
 }
 
+func PauseAlertRule(cmd *m.PauseAlertCommand) error {
+	return inTransaction(func(sess *xorm.Session) error {
+		alert := m.Alert{}
+
+		if has, err := sess.Id(cmd.AlertId).Get(&alert); err != nil {
+			return err
+		} else if !has {
+			return fmt.Errorf("Could not find alert")
+		}
+
+		var newState m.AlertStateType
+		if cmd.Paused {
+			newState = m.AlertStatePaused
+		} else {
+			newState = m.AlertStateNoData
+		}
+		alert.State = newState
+
+		sess.Id(alert.Id).Update(&alert)
+		return nil
+	})
+}
+
 func GetAlertStatesForDashboard(query *m.GetAlertStatesForDashboardQuery) error {
 	var rawSql = `SELECT
 	                id,

+ 14 - 1
public/app/features/alerting/alert_list_ctrl.ts

@@ -23,7 +23,7 @@ export class AlertListCtrl {
   };
 
   /** @ngInject */
-  constructor(private backendSrv, private $location) {
+  constructor(private backendSrv, private $location, private $scope) {
     var params = $location.search();
     this.filters.state = params.state || null;
     this.loadAlerts();
@@ -43,6 +43,19 @@ export class AlertListCtrl {
     });
   }
 
+  pauseAlertRule(alertId: any) {
+    var alert = _.find(this.alerts, {id: alertId});
+
+    var payload = {
+      paused: alert.state !== "paused"
+    };
+
+    this.backendSrv.post(`/api/alerts/${alert.id}/pause`, payload).then(result => {
+      alert.state = result.state;
+      alert.stateModel = alertDef.getStateDisplayModel(result.state);
+    });
+  }
+
   openHowTo() {
     appEvents.emit('show-modal', {
       src: 'public/app/features/alerting/partials/alert_howto.html',

+ 4 - 1
public/app/features/alerting/partials/alert_list.html

@@ -29,7 +29,10 @@
         <div class="card-item card-item--alert">
           <div class="card-item-header">
             <div class="card-item-type">
-              <a class="card-item-cog" href="dashboard/{{alert.dashboardUri}}?panelId={{alert.panelId}}&fullscreen&edit&tab=alert" bs-tooltip="'Edit alert rule'">
+              <a class="card-item-cog" bs-tooltip="'Pausing an alert rule prevents it from executing'" ng-click="ctrl.pauseAlertRule(alert.id)">
+								<i class="fa fa-pause"></i>
+							</a>
+							<a class="card-item-cog" href="dashboard/{{alert.dashboardUri}}?panelId={{alert.panelId}}&fullscreen&edit&tab=alert" bs-tooltip="'Edit alert rule'">
                 <i class="icon-gf icon-gf-settings"></i>
               </a>
             </div>