feat(alerting): removes pause per datasource

pull/6996/head
bergquist 9 years ago
parent 6b9db0c0c5
commit ecdf1888c4
  1. 46
      pkg/api/alerting.go
  2. 2
      pkg/api/api.go
  3. 5
      pkg/api/dtos/alerting.go
  4. 2
      pkg/metrics/metrics.go
  5. 11
      pkg/models/alert.go
  6. 4
      pkg/services/alerting/conditions/query.go
  7. 1
      pkg/services/alerting/interfaces.go
  8. 4
      pkg/services/alerting/result_handler.go
  9. 4
      pkg/services/alerting/rule_test.go
  10. 38
      pkg/services/sqlstore/alert.go
  11. 31
      pkg/services/sqlstore/alert_test.go

@ -287,20 +287,11 @@ func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response {
} }
//POST /api/alerts/pause //POST /api/alerts/pause
func PauseAlerts(c *middleware.Context, dto dtos.PauseAlertsCommand) Response { func PauseAlerts(c *middleware.Context, dto dtos.PauseAllAlertsCommand) Response {
updateCmd := models.PauseAlertCommand{ updateCmd := models.PauseAllAlertCommand{
OrgId: c.OrgId,
Paused: dto.Paused, Paused: dto.Paused,
} }
if len(dto.DataSourceIds) > 0 {
alertIdsToUpdate, err := getAlertIdsToUpdate(dto)
if err != nil {
return ApiError(500, "Failed to pause alerts", err)
}
updateCmd.AlertIds = alertIdsToUpdate
}
if err := bus.Dispatch(&updateCmd); err != nil { if err := bus.Dispatch(&updateCmd); err != nil {
return ApiError(500, "Failed to pause alerts", err) return ApiError(500, "Failed to pause alerts", err)
} }
@ -320,36 +311,3 @@ func PauseAlerts(c *middleware.Context, dto dtos.PauseAlertsCommand) Response {
return Json(200, result) return Json(200, result)
} }
func getAlertIdsToUpdate(pauseAlertCmd dtos.PauseAlertsCommand) ([]int64, error) {
cmd := &models.GetAllAlertsQuery{}
if err := bus.Dispatch(cmd); err != nil {
return nil, err
}
var alertIdsToUpdate []int64
for _, alert := range cmd.Result {
alert, err := alerting.NewRuleFromDBAlert(alert)
if err != nil {
return nil, err
}
for _, condition := range alert.Conditions {
id, exist := condition.GetDatasourceId()
if exist && existInSlice(pauseAlertCmd.DataSourceIds, *id) {
alertIdsToUpdate = append(alertIdsToUpdate, alert.Id)
}
}
}
return alertIdsToUpdate, nil
}
func existInSlice(slice []int64, value int64) bool {
for _, v := range slice {
if v == value {
return true
}
}
return false
}

@ -256,7 +256,6 @@ func Register(r *macaron.Macaron) {
r.Group("/alerts", func() { r.Group("/alerts", func() {
r.Post("/test", bind(dtos.AlertTestCommand{}), wrap(AlertTest)) r.Post("/test", bind(dtos.AlertTestCommand{}), wrap(AlertTest))
r.Post("/:alertId/pause", bind(dtos.PauseAlertCommand{}), wrap(PauseAlert), reqEditorRole) r.Post("/:alertId/pause", bind(dtos.PauseAlertCommand{}), wrap(PauseAlert), reqEditorRole)
r.Post("/pause", bind(dtos.PauseAlertsCommand{}), wrap(PauseAlerts), reqGrafanaAdmin)
r.Get("/:alertId", ValidateOrgAlert, wrap(GetAlert)) r.Get("/:alertId", ValidateOrgAlert, wrap(GetAlert))
r.Get("/", wrap(GetAlerts)) r.Get("/", wrap(GetAlerts))
r.Get("/states-for-dashboard", wrap(GetAlertStatesForDashboard)) r.Get("/states-for-dashboard", wrap(GetAlertStatesForDashboard))
@ -290,6 +289,7 @@ func Register(r *macaron.Macaron) {
r.Get("/users/:id/quotas", wrap(GetUserQuotas)) r.Get("/users/:id/quotas", wrap(GetUserQuotas))
r.Put("/users/:id/quotas/:target", bind(m.UpdateUserQuotaCmd{}), wrap(UpdateUserQuota)) r.Put("/users/:id/quotas/:target", bind(m.UpdateUserQuotaCmd{}), wrap(UpdateUserQuota))
r.Get("/stats", AdminGetStats) r.Get("/stats", AdminGetStats)
r.Post("/pause-all-alerts", bind(dtos.PauseAllAlertsCommand{}), wrap(PauseAlerts))
}, reqGrafanaAdmin) }, reqGrafanaAdmin)
// rendering // rendering

@ -65,7 +65,6 @@ type PauseAlertCommand struct {
Paused bool `json:"paused"` Paused bool `json:"paused"`
} }
type PauseAlertsCommand struct { type PauseAllAlertsCommand struct {
DataSourceIds []int64 `json:"datasourceId"` Paused bool `json:"paused"`
Paused bool `json:"paused"`
} }

@ -50,7 +50,7 @@ var (
// Timers // Timers
M_DataSource_ProxyReq_Timer Timer M_DataSource_ProxyReq_Timer Timer
M_Alerting_Execution_Time Timer M_Alerting_Execution_Time Timer
// StatTotals // StatTotals
M_Alerting_Active_Alerts Gauge M_Alerting_Active_Alerts Gauge

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

@ -34,10 +34,6 @@ type AlertQuery struct {
To string To string
} }
func (c *QueryCondition) GetDatasourceId() (datasourceId *int64, exist bool) {
return &c.Query.DatasourceId, true
}
func (c *QueryCondition) Eval(context *alerting.EvalContext) (*alerting.ConditionResult, error) { func (c *QueryCondition) Eval(context *alerting.EvalContext) (*alerting.ConditionResult, error) {
timeRange := tsdb.NewTimeRange(c.Query.From, c.Query.To) timeRange := tsdb.NewTimeRange(c.Query.From, c.Query.To)

@ -30,5 +30,4 @@ type ConditionResult struct {
type Condition interface { type Condition interface {
Eval(result *EvalContext) (*ConditionResult, error) Eval(result *EvalContext) (*ConditionResult, error)
GetDatasourceId() (datasourceId *int64, exist bool)
} }

@ -86,6 +86,10 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error {
} }
if err := bus.Dispatch(cmd); err != nil { 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) handler.log.Error("Failed to save state", "error", err)
} }

@ -14,10 +14,6 @@ func (f *FakeCondition) Eval(context *EvalContext) (*ConditionResult, error) {
return &ConditionResult{}, nil return &ConditionResult{}, nil
} }
func (c *FakeCondition) GetDatasourceId() (datasourceId *int64, exist bool) {
return nil, false
}
func TestAlertRuleModel(t *testing.T) { func TestAlertRuleModel(t *testing.T) {
Convey("Testing alert rule", t, func() { Convey("Testing alert rule", t, func() {

@ -3,9 +3,8 @@ package sqlstore
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"time"
"strings" "strings"
"time"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
"github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/bus"
@ -21,6 +20,7 @@ func init() {
bus.AddHandler("sql", SetAlertState) bus.AddHandler("sql", SetAlertState)
bus.AddHandler("sql", GetAlertStatesForDashboard) bus.AddHandler("sql", GetAlertStatesForDashboard)
bus.AddHandler("sql", PauseAlertRule) bus.AddHandler("sql", PauseAlertRule)
bus.AddHandler("sql", PauseAllAlertRule)
} }
func GetAlertById(query *m.GetAlertByIdQuery) error { func GetAlertById(query *m.GetAlertByIdQuery) error {
@ -230,6 +230,10 @@ func SetAlertState(cmd *m.SetAlertStateCommand) error {
return fmt.Errorf("Could not find alert") return fmt.Errorf("Could not find alert")
} }
if alert.State == m.AlertStatePaused {
return m.ErrCannotChangeStateOnPausedAlert
}
alert.State = cmd.State alert.State = cmd.State
alert.StateChanges += 1 alert.StateChanges += 1
alert.NewStateDate = time.Now() alert.NewStateDate = time.Now()
@ -248,6 +252,10 @@ func SetAlertState(cmd *m.SetAlertStateCommand) error {
func PauseAlertRule(cmd *m.PauseAlertCommand) error { func PauseAlertRule(cmd *m.PauseAlertCommand) error {
return inTransaction(func(sess *xorm.Session) error { return inTransaction(func(sess *xorm.Session) error {
if len(cmd.AlertIds) == 0 {
return fmt.Errorf("command contains no alertids")
}
var buffer bytes.Buffer var buffer bytes.Buffer
params := make([]interface{}, 0) params := make([]interface{}, 0)
@ -258,11 +266,9 @@ func PauseAlertRule(cmd *m.PauseAlertCommand) error {
params = append(params, string(m.AlertStatePending)) params = append(params, string(m.AlertStatePending))
} }
if len(cmd.AlertIds) > 0 { buffer.WriteString(` WHERE id IN (?` + strings.Repeat(",?", len(cmd.AlertIds)-1) + `)`)
buffer.WriteString(` WHERE id IN (?` + strings.Repeat(",?", len(cmd.AlertIds)-1) + `)`) for _, v := range cmd.AlertIds {
for _, v := range cmd.AlertIds { params = append(params, v)
params = append(params, v)
}
} }
res, err := sess.Exec(buffer.String(), params...) res, err := sess.Exec(buffer.String(), params...)
@ -274,6 +280,24 @@ func PauseAlertRule(cmd *m.PauseAlertCommand) error {
}) })
} }
func PauseAllAlertRule(cmd *m.PauseAllAlertCommand) error {
return inTransaction(func(sess *xorm.Session) error {
var newState string
if cmd.Paused {
newState = string(m.AlertStatePaused)
} else {
newState = string(m.AlertStatePending)
}
res, err := sess.Exec(`UPDATE alert SET state = ?`, newState)
if err != nil {
return err
}
cmd.ResultCount, _ = res.RowsAffected()
return nil
})
}
func GetAlertStatesForDashboard(query *m.GetAlertStatesForDashboardQuery) error { func GetAlertStatesForDashboard(query *m.GetAlertStatesForDashboardQuery) error {
var rawSql = `SELECT var rawSql = `SELECT
id, id,

@ -39,6 +39,37 @@ func TestAlertingDataAccess(t *testing.T) {
So(err, ShouldBeNil) 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 = PauseAllAlertRule(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() { Convey("Can read properties", func() {
alertQuery := m.GetAlertsQuery{DashboardId: testDash.Id, PanelId: 1, OrgId: 1} alertQuery := m.GetAlertsQuery{DashboardId: testDash.Id, PanelId: 1, OrgId: 1}
err2 := HandleAlertsQuery(&alertQuery) err2 := HandleAlertsQuery(&alertQuery)

Loading…
Cancel
Save