From 19427b59f92db10ceb9e6092e5f2f2aff2766896 Mon Sep 17 00:00:00 2001 From: bergquist Date: Mon, 10 Oct 2016 13:29:10 +0200 Subject: [PATCH 1/6] feat(alerting): do not enqueue paused rules --- pkg/services/alerting/scheduler.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/services/alerting/scheduler.go b/pkg/services/alerting/scheduler.go index 9d20796f3dc..b6ef1a63ff8 100644 --- a/pkg/services/alerting/scheduler.go +++ b/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 } From 264590a9c293188e8361ae89cc20276b0ced906a Mon Sep 17 00:00:00 2001 From: bergquist Date: Mon, 10 Oct 2016 14:26:09 +0200 Subject: [PATCH 2/6] feat(alerting): add paused api endpoint --- pkg/api/alerting.go | 21 +++++++++++++++++++++ pkg/api/api.go | 1 + pkg/api/dtos/alerting.go | 6 ++++++ pkg/models/alert.go | 6 ++++++ pkg/services/sqlstore/alert.go | 24 ++++++++++++++++++++++++ 5 files changed, 58 insertions(+) diff --git a/pkg/api/alerting.go b/pkg/api/alerting.go index 460ad56e1ab..aaa5752c446 100644 --- a/pkg/api/alerting.go +++ b/pkg/api/alerting.go @@ -252,6 +252,27 @@ func NotificationTest(c *middleware.Context, dto dtos.NotificationTestCommand) R return ApiSuccess("Test notification sent") } +//POST /api/alerts/:alertId/pause +func PauseAlert(c *middleware.Context, cmd models.PauseAlertCommand) Response { + cmd.OrgId = c.OrgId + cmd.AlertId = c.ParamsInt64(":alertId") + + if cmd.AlertId == 0 { + return ApiError(400, "Missing alert id", nil) + } + + if err := bus.Dispatch(&cmd); err != nil { + return ApiError(500, "", err) + } + + response := "un paused" + if cmd.Paused { + response = "paused" + } + + return ApiSuccess("Alert " + response) +} + func getAlertIdForRequest(c *middleware.Context) (int64, error) { alertId := c.QueryInt64("alertId") panelId := c.QueryInt64("panelId") diff --git a/pkg/api/api.go b/pkg/api/api.go index deb29d730eb..bf9e427214a 100644 --- a/pkg/api/api.go +++ b/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(m.PauseAlertCommand{}), wrap(PauseAlert)) r.Get("/:alertId", ValidateOrgAlert, wrap(GetAlert)) r.Get("/", wrap(GetAlerts)) r.Get("/states-for-dashboard", wrap(GetAlertStatesForDashboard)) diff --git a/pkg/api/dtos/alerting.go b/pkg/api/dtos/alerting.go index e024768cd5e..a0aa632abd9 100644 --- a/pkg/api/dtos/alerting.go +++ b/pkg/api/dtos/alerting.go @@ -58,3 +58,9 @@ type NotificationTestCommand struct { Type string `json:"type"` Settings *simplejson.Json `json:"settings"` } + +type PauseAlertCommand struct { + AlertId int64 `json:"alertId"` + DashboardId int64 `json:"dashboardId"` + PanelId int64 `json:"panelId"` +} diff --git a/pkg/models/alert.go b/pkg/models/alert.go index 938be8ddbd4..419e832ae39 100644 --- a/pkg/models/alert.go +++ b/pkg/models/alert.go @@ -101,6 +101,12 @@ type SaveAlertsCommand struct { Alerts []*Alert } +type PauseAlertCommand struct { + OrgId int64 + AlertId int64 `json:"alertId"` + Paused bool `json:"bool"` +} + type SetAlertStateCommand struct { AlertId int64 OrgId int64 diff --git a/pkg/services/sqlstore/alert.go b/pkg/services/sqlstore/alert.go index 61397017943..76ea268bc04 100644 --- a/pkg/services/sqlstore/alert.go +++ b/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, From f3825263d4d9110052915b6cf961643d225421f5 Mon Sep 17 00:00:00 2001 From: bergquist Date: Mon, 10 Oct 2016 15:17:14 +0200 Subject: [PATCH 3/6] feat(alerting): add pause button in alert list --- pkg/api/alerting.go | 11 ++++++++--- pkg/models/alert.go | 2 +- public/app/features/alerting/alert_list_ctrl.ts | 15 ++++++++++++++- .../features/alerting/partials/alert_list.html | 3 +++ 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/pkg/api/alerting.go b/pkg/api/alerting.go index aaa5752c446..46a0df32f01 100644 --- a/pkg/api/alerting.go +++ b/pkg/api/alerting.go @@ -265,12 +265,17 @@ func PauseAlert(c *middleware.Context, cmd models.PauseAlertCommand) Response { return ApiError(500, "", err) } - response := "un paused" + var response models.AlertStateType = models.AlertStateNoData if cmd.Paused { - response = "paused" + response = models.AlertStatePaused } - return ApiSuccess("Alert " + response) + result := map[string]interface{}{ + "alertId": cmd.AlertId, + "state": response, + } + + return Json(200, result) } func getAlertIdForRequest(c *middleware.Context) (int64, error) { diff --git a/pkg/models/alert.go b/pkg/models/alert.go index 419e832ae39..de103143ac3 100644 --- a/pkg/models/alert.go +++ b/pkg/models/alert.go @@ -104,7 +104,7 @@ type SaveAlertsCommand struct { type PauseAlertCommand struct { OrgId int64 AlertId int64 `json:"alertId"` - Paused bool `json:"bool"` + Paused bool `json:"paused"` } type SetAlertStateCommand struct { diff --git a/public/app/features/alerting/alert_list_ctrl.ts b/public/app/features/alerting/alert_list_ctrl.ts index 4b429e961a7..5d62a0790cb 100644 --- a/public/app/features/alerting/alert_list_ctrl.ts +++ b/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/${alertId}/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', diff --git a/public/app/features/alerting/partials/alert_list.html b/public/app/features/alerting/partials/alert_list.html index a8678bc4cdc..da4e3b3a695 100644 --- a/public/app/features/alerting/partials/alert_list.html +++ b/public/app/features/alerting/partials/alert_list.html @@ -33,6 +33,9 @@ +
+ pause +
From 804797245d07ed06b5d5c163918c435302d7522a Mon Sep 17 00:00:00 2001 From: bergquist Date: Tue, 11 Oct 2016 08:40:38 +0200 Subject: [PATCH 4/6] feat(alerting): make it possible to pause from alert tab --- pkg/api/alerting.go | 24 +++++++++---------- pkg/api/api.go | 4 +++- pkg/api/dtos/alerting.go | 1 + pkg/models/alert.go | 4 ++-- .../app/features/alerting/alert_list_ctrl.ts | 5 ++-- 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/pkg/api/alerting.go b/pkg/api/alerting.go index 46a0df32f01..a8d2171344e 100644 --- a/pkg/api/alerting.go +++ b/pkg/api/alerting.go @@ -252,13 +252,17 @@ func NotificationTest(c *middleware.Context, dto dtos.NotificationTestCommand) R return ApiSuccess("Test notification sent") } -//POST /api/alerts/:alertId/pause -func PauseAlert(c *middleware.Context, cmd models.PauseAlertCommand) Response { - cmd.OrgId = c.OrgId - cmd.AlertId = c.ParamsInt64(":alertId") +//POST /api/pause-alert +func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response { + alertId, err := getAlertIdForRequest(c.OrgId, dto.AlertId, dto.PanelId, dto.DashboardId) + if err != nil { + return ApiError(400, "Bad request", err) + } - if cmd.AlertId == 0 { - return ApiError(400, "Missing alert id", nil) + cmd := models.PauseAlertCommand{ + OrgId: c.OrgId, + AlertId: alertId, + Paused: dto.Paused, } if err := bus.Dispatch(&cmd); err != nil { @@ -278,11 +282,7 @@ func PauseAlert(c *middleware.Context, cmd models.PauseAlertCommand) Response { return Json(200, result) } -func getAlertIdForRequest(c *middleware.Context) (int64, error) { - alertId := c.QueryInt64("alertId") - panelId := c.QueryInt64("panelId") - dashboardId := c.QueryInt64("dashboardId") - +func getAlertIdForRequest(orgId, alertId, panelId, dashboardId int64) (int64, error) { if alertId == 0 && dashboardId == 0 && panelId == 0 { return 0, fmt.Errorf("Missing alertId or dashboardId and panelId") } @@ -290,7 +290,7 @@ func getAlertIdForRequest(c *middleware.Context) (int64, error) { if alertId == 0 { //fetch alertId query := models.GetAlertsQuery{ - OrgId: c.OrgId, + OrgId: orgId, DashboardId: dashboardId, PanelId: panelId, } diff --git a/pkg/api/api.go b/pkg/api/api.go index bf9e427214a..9b938b3c942 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -252,12 +252,14 @@ func Register(r *macaron.Macaron) { r.Group("/alerts", func() { r.Post("/test", bind(dtos.AlertTestCommand{}), wrap(AlertTest)) - r.Post("/:alertId/pause", ValidateOrgAlert, bind(m.PauseAlertCommand{}), wrap(PauseAlert)) + r.Get("/:alertId", ValidateOrgAlert, wrap(GetAlert)) r.Get("/", wrap(GetAlerts)) r.Get("/states-for-dashboard", wrap(GetAlertStatesForDashboard)) }) + r.Post("/pause-alert", bind(dtos.PauseAlertCommand{}), wrap(PauseAlert)) + r.Get("/alert-notifications", wrap(GetAlertNotifications)) r.Group("/alert-notifications", func() { diff --git a/pkg/api/dtos/alerting.go b/pkg/api/dtos/alerting.go index a0aa632abd9..29f0b834d2d 100644 --- a/pkg/api/dtos/alerting.go +++ b/pkg/api/dtos/alerting.go @@ -63,4 +63,5 @@ type PauseAlertCommand struct { AlertId int64 `json:"alertId"` DashboardId int64 `json:"dashboardId"` PanelId int64 `json:"panelId"` + Paused bool `json:"paused"` } diff --git a/pkg/models/alert.go b/pkg/models/alert.go index de103143ac3..f50bb3193dc 100644 --- a/pkg/models/alert.go +++ b/pkg/models/alert.go @@ -103,8 +103,8 @@ type SaveAlertsCommand struct { type PauseAlertCommand struct { OrgId int64 - AlertId int64 `json:"alertId"` - Paused bool `json:"paused"` + AlertId int64 + Paused bool } type SetAlertStateCommand struct { diff --git a/public/app/features/alerting/alert_list_ctrl.ts b/public/app/features/alerting/alert_list_ctrl.ts index 5d62a0790cb..623cefaec19 100644 --- a/public/app/features/alerting/alert_list_ctrl.ts +++ b/public/app/features/alerting/alert_list_ctrl.ts @@ -47,10 +47,11 @@ export class AlertListCtrl { var alert = _.find(this.alerts, {id: alertId}); var payload = { - paused: alert.state !== "paused" + paused: alert.state !== "paused", + alertId: alert.id }; - this.backendSrv.post(`/api/alerts/${alertId}/pause`, payload).then(result => { + this.backendSrv.post(`/api/pause-alert`, payload).then(result => { alert.state = result.state; alert.stateModel = alertDef.getStateDisplayModel(result.state); }); From 4bbc2108f9d410a90bee15d2bd62833452d0b80b Mon Sep 17 00:00:00 2001 From: bergquist Date: Tue, 11 Oct 2016 09:45:38 +0200 Subject: [PATCH 5/6] feat(alerting): add pause button to alert list --- pkg/api/alerting.go | 3 +++ public/app/features/alerting/partials/alert_list.html | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pkg/api/alerting.go b/pkg/api/alerting.go index a8d2171344e..c0cba3a481e 100644 --- a/pkg/api/alerting.go +++ b/pkg/api/alerting.go @@ -270,13 +270,16 @@ func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response { } var response models.AlertStateType = models.AlertStateNoData + pausedState := "un paused" if cmd.Paused { response = models.AlertStatePaused + pausedState = "paused" } result := map[string]interface{}{ "alertId": cmd.AlertId, "state": response, + "message": "alert " + pausedState, } return Json(200, result) diff --git a/public/app/features/alerting/partials/alert_list.html b/public/app/features/alerting/partials/alert_list.html index da4e3b3a695..685aa1f2db8 100644 --- a/public/app/features/alerting/partials/alert_list.html +++ b/public/app/features/alerting/partials/alert_list.html @@ -29,13 +29,13 @@
From c6cf7647ffa3243a0334bc230dcbba3d11f89e8f Mon Sep 17 00:00:00 2001 From: bergquist Date: Tue, 11 Oct 2016 10:53:24 +0200 Subject: [PATCH 6/6] feat(alerting): pausing alerts requires alert id --- pkg/api/alerting.go | 36 ++----------------- pkg/api/api.go | 4 +-- pkg/api/dtos/alerting.go | 6 ++-- .../app/features/alerting/alert_list_ctrl.ts | 5 ++- 4 files changed, 7 insertions(+), 44 deletions(-) diff --git a/pkg/api/alerting.go b/pkg/api/alerting.go index c0cba3a481e..40b117835ec 100644 --- a/pkg/api/alerting.go +++ b/pkg/api/alerting.go @@ -252,16 +252,11 @@ func NotificationTest(c *middleware.Context, dto dtos.NotificationTestCommand) R return ApiSuccess("Test notification sent") } -//POST /api/pause-alert +//POST /api/:alertId/pause func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response { - alertId, err := getAlertIdForRequest(c.OrgId, dto.AlertId, dto.PanelId, dto.DashboardId) - if err != nil { - return ApiError(400, "Bad request", err) - } - cmd := models.PauseAlertCommand{ OrgId: c.OrgId, - AlertId: alertId, + AlertId: c.ParamsInt64("alertId"), Paused: dto.Paused, } @@ -284,30 +279,3 @@ func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response { return Json(200, result) } - -func getAlertIdForRequest(orgId, alertId, panelId, dashboardId int64) (int64, error) { - if alertId == 0 && dashboardId == 0 && panelId == 0 { - return 0, fmt.Errorf("Missing alertId or dashboardId and panelId") - } - - if alertId == 0 { - //fetch alertId - query := models.GetAlertsQuery{ - OrgId: orgId, - DashboardId: dashboardId, - PanelId: panelId, - } - - if err := bus.Dispatch(&query); err != nil { - return 0, err - } - - if len(query.Result) != 1 { - return 0, fmt.Errorf("PanelId is not unique on dashboard") - } - - alertId = query.Result[0].Id - } - - return alertId, nil -} diff --git a/pkg/api/api.go b/pkg/api/api.go index 9b938b3c942..5609536e213 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -252,14 +252,12 @@ 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)) }) - r.Post("/pause-alert", bind(dtos.PauseAlertCommand{}), wrap(PauseAlert)) - r.Get("/alert-notifications", wrap(GetAlertNotifications)) r.Group("/alert-notifications", func() { diff --git a/pkg/api/dtos/alerting.go b/pkg/api/dtos/alerting.go index 29f0b834d2d..bf4d7f4353e 100644 --- a/pkg/api/dtos/alerting.go +++ b/pkg/api/dtos/alerting.go @@ -60,8 +60,6 @@ type NotificationTestCommand struct { } type PauseAlertCommand struct { - AlertId int64 `json:"alertId"` - DashboardId int64 `json:"dashboardId"` - PanelId int64 `json:"panelId"` - Paused bool `json:"paused"` + AlertId int64 `json:"alertId"` + Paused bool `json:"paused"` } diff --git a/public/app/features/alerting/alert_list_ctrl.ts b/public/app/features/alerting/alert_list_ctrl.ts index 623cefaec19..b2287759a9b 100644 --- a/public/app/features/alerting/alert_list_ctrl.ts +++ b/public/app/features/alerting/alert_list_ctrl.ts @@ -47,11 +47,10 @@ export class AlertListCtrl { var alert = _.find(this.alerts, {id: alertId}); var payload = { - paused: alert.state !== "paused", - alertId: alert.id + paused: alert.state !== "paused" }; - this.backendSrv.post(`/api/pause-alert`, payload).then(result => { + this.backendSrv.post(`/api/alerts/${alert.id}/pause`, payload).then(result => { alert.state = result.state; alert.stateModel = alertDef.getStateDisplayModel(result.state); });