mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'alerting_keeplast'
This commit is contained in:
commit
8bb2f11505
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
type AlertStateType string
|
type AlertStateType string
|
||||||
type AlertSeverityType string
|
type AlertSeverityType string
|
||||||
|
type NoDataOption string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AlertStateNoData AlertStateType = "no_data"
|
AlertStateNoData AlertStateType = "no_data"
|
||||||
@ -17,10 +18,25 @@ const (
|
|||||||
AlertStateOK AlertStateType = "ok"
|
AlertStateOK AlertStateType = "ok"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
NoDataSetNoData NoDataOption = "no_data"
|
||||||
|
NoDataSetAlerting NoDataOption = "alerting"
|
||||||
|
NoDataSetOK NoDataOption = "ok"
|
||||||
|
NoDataKeepState NoDataOption = "keep_state"
|
||||||
|
)
|
||||||
|
|
||||||
func (s AlertStateType) IsValid() bool {
|
func (s AlertStateType) IsValid() bool {
|
||||||
return s == AlertStateOK || s == AlertStateNoData || s == AlertStateExecError || s == AlertStatePaused
|
return s == AlertStateOK || s == AlertStateNoData || s == AlertStateExecError || s == AlertStatePaused
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s NoDataOption) IsValid() bool {
|
||||||
|
return s == NoDataSetNoData || s == NoDataSetAlerting || s == NoDataSetOK || s == NoDataKeepState
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s NoDataOption) ToAlertState() AlertStateType {
|
||||||
|
return AlertStateType(s)
|
||||||
|
}
|
||||||
|
|
||||||
type Alert struct {
|
type Alert struct {
|
||||||
Id int64
|
Id int64
|
||||||
Version int64
|
Version int64
|
||||||
|
@ -30,34 +30,35 @@ func NewResultHandler() *DefaultResultHandler {
|
|||||||
func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error {
|
func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error {
|
||||||
oldState := evalContext.Rule.State
|
oldState := evalContext.Rule.State
|
||||||
|
|
||||||
exeuctionError := ""
|
executionError := ""
|
||||||
annotationData := simplejson.New()
|
annotationData := simplejson.New()
|
||||||
if evalContext.Error != nil {
|
if evalContext.Error != nil {
|
||||||
handler.log.Error("Alert Rule Result Error", "ruleId", evalContext.Rule.Id, "error", evalContext.Error)
|
handler.log.Error("Alert Rule Result Error", "ruleId", evalContext.Rule.Id, "error", evalContext.Error)
|
||||||
evalContext.Rule.State = m.AlertStateExecError
|
evalContext.Rule.State = m.AlertStateExecError
|
||||||
exeuctionError = evalContext.Error.Error()
|
executionError = evalContext.Error.Error()
|
||||||
annotationData.Set("errorMessage", exeuctionError)
|
annotationData.Set("errorMessage", executionError)
|
||||||
} else if evalContext.Firing {
|
} else if evalContext.Firing {
|
||||||
evalContext.Rule.State = m.AlertStateAlerting
|
evalContext.Rule.State = m.AlertStateAlerting
|
||||||
annotationData = simplejson.NewFromAny(evalContext.EvalMatches)
|
annotationData = simplejson.NewFromAny(evalContext.EvalMatches)
|
||||||
} else {
|
} else {
|
||||||
// handle no data case
|
|
||||||
if evalContext.NoDataFound {
|
if evalContext.NoDataFound {
|
||||||
evalContext.Rule.State = evalContext.Rule.NoDataState
|
if evalContext.Rule.NoDataState != m.NoDataKeepState {
|
||||||
|
evalContext.Rule.State = evalContext.Rule.NoDataState.ToAlertState()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
evalContext.Rule.State = m.AlertStateOK
|
evalContext.Rule.State = m.AlertStateOK
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
countStateResult(evalContext.Rule.State)
|
countStateResult(evalContext.Rule.State)
|
||||||
if evalContext.Rule.State != oldState {
|
if handler.shouldUpdateAlertState(evalContext, oldState) {
|
||||||
handler.log.Info("New state change", "alertId", evalContext.Rule.Id, "newState", evalContext.Rule.State, "oldState", oldState)
|
handler.log.Info("New state change", "alertId", evalContext.Rule.Id, "newState", evalContext.Rule.State, "oldState", oldState)
|
||||||
|
|
||||||
cmd := &m.SetAlertStateCommand{
|
cmd := &m.SetAlertStateCommand{
|
||||||
AlertId: evalContext.Rule.Id,
|
AlertId: evalContext.Rule.Id,
|
||||||
OrgId: evalContext.Rule.OrgId,
|
OrgId: evalContext.Rule.OrgId,
|
||||||
State: evalContext.Rule.State,
|
State: evalContext.Rule.State,
|
||||||
Error: exeuctionError,
|
Error: executionError,
|
||||||
EvalData: annotationData,
|
EvalData: annotationData,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,6 +92,10 @@ func (handler *DefaultResultHandler) Handle(evalContext *EvalContext) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (handler *DefaultResultHandler) shouldUpdateAlertState(evalContext *EvalContext, oldState m.AlertStateType) bool {
|
||||||
|
return evalContext.Rule.State != oldState
|
||||||
|
}
|
||||||
|
|
||||||
func countStateResult(state m.AlertStateType) {
|
func countStateResult(state m.AlertStateType) {
|
||||||
switch state {
|
switch state {
|
||||||
case m.AlertStateAlerting:
|
case m.AlertStateAlerting:
|
||||||
|
@ -1,57 +1,29 @@
|
|||||||
package alerting
|
package alerting
|
||||||
|
|
||||||
// import (
|
// import (
|
||||||
|
// "context"
|
||||||
// "testing"
|
// "testing"
|
||||||
// "time"
|
|
||||||
//
|
|
||||||
// "github.com/grafana/grafana/pkg/bus"
|
|
||||||
// m "github.com/grafana/grafana/pkg/models"
|
|
||||||
// "github.com/grafana/grafana/pkg/services/alerting/alertstates"
|
|
||||||
//
|
//
|
||||||
|
// "github.com/grafana/grafana/pkg/models"
|
||||||
// . "github.com/smartystreets/goconvey/convey"
|
// . "github.com/smartystreets/goconvey/convey"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func TestAlertResultHandler(t *testing.T) {
|
// func TestAlertResultHandler(t *testing.T) {
|
||||||
// Convey("Test result Handler", t, func() {
|
// Convey("Test result Handler", t, func() {
|
||||||
// resultHandler := ResultHandlerImpl{}
|
//
|
||||||
// mockResult := &AlertResultContext{
|
// handler := NewResultHandler()
|
||||||
// Triggered: false,
|
// evalContext := NewEvalContext(context.TODO(), &Rule{})
|
||||||
// Rule: &AlertRule{
|
|
||||||
// Id: 1,
|
|
||||||
// OrgId 1,
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
// mockAlertState := &m.AlertState{}
|
|
||||||
// bus.ClearBusHandlers()
|
|
||||||
// bus.AddHandler("test", func(query *m.GetLastAlertStateQuery) error {
|
|
||||||
// query.Result = mockAlertState
|
|
||||||
// return nil
|
|
||||||
// })
|
|
||||||
//
|
//
|
||||||
// Convey("Should update", func() {
|
// Convey("Should update", func() {
|
||||||
//
|
//
|
||||||
// Convey("when no earlier alert state", func() {
|
// Convey("when no earlier alert state", func() {
|
||||||
// mockAlertState = nil
|
// oldState := models.AlertStateOK
|
||||||
// So(resultHandler.shouldUpdateState(mockResult), ShouldBeTrue)
|
|
||||||
// })
|
|
||||||
//
|
//
|
||||||
// Convey("alert state have changed", func() {
|
// evalContext.Rule.State = models.AlertStateAlerting
|
||||||
// mockAlertState = &m.AlertState{
|
// evalContext.Rule.NoDataState = models.NoDataKeepState
|
||||||
// State: alertstates.Critical,
|
// evalContext.NoDataFound = true
|
||||||
// }
|
|
||||||
// mockResult.Triggered = false
|
|
||||||
// So(resultHandler.shouldUpdateState(mockResult), ShouldBeTrue)
|
|
||||||
// })
|
|
||||||
//
|
//
|
||||||
// Convey("last alert state was 15min ago", func() {
|
// So(handler.shouldUpdateAlertState(evalContext, oldState), ShouldBeFalse)
|
||||||
// now := time.Now()
|
|
||||||
// mockAlertState = &m.AlertState{
|
|
||||||
// State: alertstates.Critical,
|
|
||||||
// Created: now.Add(time.Minute * -30),
|
|
||||||
// }
|
|
||||||
// mockResult.Triggered = true
|
|
||||||
// mockResult.StartTime = time.Now()
|
|
||||||
// So(resultHandler.shouldUpdateState(mockResult), ShouldBeTrue)
|
|
||||||
// })
|
// })
|
||||||
// })
|
// })
|
||||||
// })
|
// })
|
||||||
|
@ -18,7 +18,7 @@ type Rule struct {
|
|||||||
Frequency int64
|
Frequency int64
|
||||||
Name string
|
Name string
|
||||||
Message string
|
Message string
|
||||||
NoDataState m.AlertStateType
|
NoDataState m.NoDataOption
|
||||||
State m.AlertStateType
|
State m.AlertStateType
|
||||||
Conditions []Condition
|
Conditions []Condition
|
||||||
Notifications []int64
|
Notifications []int64
|
||||||
@ -76,7 +76,7 @@ func NewRuleFromDBAlert(ruleDef *m.Alert) (*Rule, error) {
|
|||||||
model.Message = ruleDef.Message
|
model.Message = ruleDef.Message
|
||||||
model.Frequency = ruleDef.Frequency
|
model.Frequency = ruleDef.Frequency
|
||||||
model.State = ruleDef.State
|
model.State = ruleDef.State
|
||||||
model.NoDataState = m.AlertStateType(ruleDef.Settings.Get("noDataState").MustString("no_data"))
|
model.NoDataState = m.NoDataOption(ruleDef.Settings.Get("noDataState").MustString("no_data"))
|
||||||
|
|
||||||
for _, v := range ruleDef.Settings.Get("notifications").MustArray() {
|
for _, v := range ruleDef.Settings.Get("notifications").MustArray() {
|
||||||
jsonModel := simplejson.NewFromAny(v)
|
jsonModel := simplejson.NewFromAny(v)
|
||||||
|
@ -40,6 +40,7 @@ var noDataModes = [
|
|||||||
{text: 'OK', value: 'ok'},
|
{text: 'OK', value: 'ok'},
|
||||||
{text: 'Alerting', value: 'alerting'},
|
{text: 'Alerting', value: 'alerting'},
|
||||||
{text: 'No Data', value: 'no_data'},
|
{text: 'No Data', value: 'no_data'},
|
||||||
|
{text: 'Keep Last', value: 'keep_last'},
|
||||||
];
|
];
|
||||||
|
|
||||||
function createReducerPart(model) {
|
function createReducerPart(model) {
|
||||||
|
Loading…
Reference in New Issue
Block a user