mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(alerting): removed severity
This commit is contained in:
@@ -43,25 +43,20 @@ func (c *EvalContext) GetStateModel() *StateDescription {
|
||||
Color: "#36a64f",
|
||||
Text: "OK",
|
||||
}
|
||||
case m.AlertStateUnknown:
|
||||
case m.AlertStateNoData:
|
||||
return &StateDescription{
|
||||
Color: "#888888",
|
||||
Text: "UNKNOWN",
|
||||
Text: "No Data",
|
||||
}
|
||||
case m.AlertStateExeuctionError:
|
||||
case m.AlertStateExecError:
|
||||
return &StateDescription{
|
||||
Color: "#000",
|
||||
Text: "EXECUTION_ERROR",
|
||||
Text: "Execution Error",
|
||||
}
|
||||
case m.AlertStateWarning:
|
||||
return &StateDescription{
|
||||
Color: "#fd821b",
|
||||
Text: "WARNING",
|
||||
}
|
||||
case m.AlertStateCritical:
|
||||
case m.AlertStateAlerting:
|
||||
return &StateDescription{
|
||||
Color: "#D63232",
|
||||
Text: "CRITICAL",
|
||||
Text: "Alerting",
|
||||
}
|
||||
default:
|
||||
panic("Unknown rule state " + c.Rule.State)
|
||||
|
||||
@@ -88,14 +88,9 @@ func (e *DashAlertExtractor) GetAlerts() ([]*m.Alert, error) {
|
||||
Name: jsonAlert.Get("name").MustString(),
|
||||
Handler: jsonAlert.Get("handler").MustInt64(),
|
||||
Message: jsonAlert.Get("message").MustString(),
|
||||
Severity: m.AlertSeverityType(jsonAlert.Get("severity").MustString()),
|
||||
Frequency: getTimeDurationStringToSeconds(jsonAlert.Get("frequency").MustString()),
|
||||
}
|
||||
|
||||
if !alert.Severity.IsValid() {
|
||||
return nil, ValidationError{Reason: "Invalid alert Severity"}
|
||||
}
|
||||
|
||||
for _, condition := range jsonAlert.Get("conditions").MustArray() {
|
||||
jsonCondition := simplejson.NewFromAny(condition)
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@ package alerting
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
type EvalHandler interface {
|
||||
@@ -19,7 +17,7 @@ type Notifier interface {
|
||||
Notify(alertResult *EvalContext)
|
||||
GetType() string
|
||||
NeedsImage() bool
|
||||
MatchSeverity(result models.AlertSeverityType) bool
|
||||
PassesFilter(rule *Rule) bool
|
||||
}
|
||||
|
||||
type Condition interface {
|
||||
|
||||
@@ -28,7 +28,7 @@ func (n *RootNotifier) NeedsImage() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *RootNotifier) MatchSeverity(result m.AlertSeverityType) bool {
|
||||
func (n *RootNotifier) PassesFilter(rule *Rule) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ func shouldUseNotification(notifier Notifier, context *EvalContext) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
return notifier.MatchSeverity(context.Rule.Severity)
|
||||
return notifier.PassesFilter(context.Rule)
|
||||
}
|
||||
|
||||
type NotifierFactory func(notification *m.AlertNotification) (Notifier, error)
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
@@ -23,7 +24,7 @@ func (fn *FakeNotifier) NeedsImage() bool {
|
||||
|
||||
func (fn *FakeNotifier) Notify(alertResult *EvalContext) {}
|
||||
|
||||
func (fn *FakeNotifier) MatchSeverity(result models.AlertSeverityType) bool {
|
||||
func (fn *FakeNotifier) PassesFilter(rule *Rule) bool {
|
||||
return fn.FakeMatchResult
|
||||
}
|
||||
|
||||
@@ -34,7 +35,7 @@ func TestAlertNotificationExtraction(t *testing.T) {
|
||||
ctx := &EvalContext{
|
||||
Firing: false,
|
||||
Rule: &Rule{
|
||||
Severity: models.AlertSeverityCritical,
|
||||
State: m.AlertStateAlerting,
|
||||
},
|
||||
}
|
||||
notifier := &FakeNotifier{FakeMatchResult: false}
|
||||
@@ -42,12 +43,12 @@ func TestAlertNotificationExtraction(t *testing.T) {
|
||||
So(shouldUseNotification(notifier, ctx), ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("exeuction error cannot be ignored", func() {
|
||||
Convey("execution error cannot be ignored", func() {
|
||||
ctx := &EvalContext{
|
||||
Firing: true,
|
||||
Error: fmt.Errorf("I used to be a programmer just like you"),
|
||||
Rule: &Rule{
|
||||
Severity: models.AlertSeverityCritical,
|
||||
State: m.AlertStateOK,
|
||||
},
|
||||
}
|
||||
notifier := &FakeNotifier{FakeMatchResult: false}
|
||||
@@ -59,7 +60,7 @@ func TestAlertNotificationExtraction(t *testing.T) {
|
||||
ctx := &EvalContext{
|
||||
Firing: true,
|
||||
Rule: &Rule{
|
||||
Severity: models.AlertSeverityCritical,
|
||||
State: models.AlertStateAlerting,
|
||||
},
|
||||
}
|
||||
notifier := &FakeNotifier{FakeMatchResult: true}
|
||||
@@ -70,9 +71,7 @@ func TestAlertNotificationExtraction(t *testing.T) {
|
||||
Convey("firing alert that dont match", func() {
|
||||
ctx := &EvalContext{
|
||||
Firing: true,
|
||||
Rule: &Rule{
|
||||
Severity: models.AlertSeverityCritical,
|
||||
},
|
||||
Rule: &Rule{State: m.AlertStateOK},
|
||||
}
|
||||
notifier := &FakeNotifier{FakeMatchResult: false}
|
||||
|
||||
|
||||
@@ -2,33 +2,21 @@ package notifiers
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
)
|
||||
|
||||
type NotifierBase struct {
|
||||
Name string
|
||||
Type string
|
||||
SeverityFilter models.AlertSeverityType
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
func NewNotifierBase(name, notifierType string, model *simplejson.Json) NotifierBase {
|
||||
base := NotifierBase{Name: name, Type: notifierType}
|
||||
|
||||
severityFilter := models.AlertSeverityType(model.Get("severityFilter").MustString(""))
|
||||
|
||||
if severityFilter == models.AlertSeverityCritical || severityFilter == models.AlertSeverityWarning {
|
||||
base.SeverityFilter = severityFilter
|
||||
}
|
||||
|
||||
return base
|
||||
}
|
||||
|
||||
func (n *NotifierBase) MatchSeverity(result models.AlertSeverityType) bool {
|
||||
if !n.SeverityFilter.IsValid() {
|
||||
return true
|
||||
}
|
||||
|
||||
return n.SeverityFilter == result
|
||||
func (n *NotifierBase) PassesFilter(rule *alerting.Rule) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (n *NotifierBase) GetType() string {
|
||||
|
||||
@@ -3,34 +3,32 @@ package notifiers
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestBaseNotifier(t *testing.T) {
|
||||
Convey("Parsing base notification severity", t, func() {
|
||||
|
||||
Convey("matches", func() {
|
||||
json := `
|
||||
{
|
||||
"severityFilter": "critical"
|
||||
}`
|
||||
|
||||
settingsJSON, _ := simplejson.NewJson([]byte(json))
|
||||
not := NewNotifierBase("ops", "email", settingsJSON)
|
||||
So(not.MatchSeverity(m.AlertSeverityCritical), ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("does not match", func() {
|
||||
json := `
|
||||
{
|
||||
"severityFilter": "critical"
|
||||
}`
|
||||
|
||||
settingsJSON, _ := simplejson.NewJson([]byte(json))
|
||||
not := NewNotifierBase("ops", "email", settingsJSON)
|
||||
So(not.MatchSeverity(m.AlertSeverityWarning), ShouldBeFalse)
|
||||
})
|
||||
})
|
||||
// Convey("Parsing base notification state", t, func() {
|
||||
//
|
||||
// Convey("matches", func() {
|
||||
// json := `
|
||||
// {
|
||||
// "states": "critical"
|
||||
// }`
|
||||
//
|
||||
// settingsJSON, _ := simplejson.NewJson([]byte(json))
|
||||
// not := NewNotifierBase("ops", "email", settingsJSON)
|
||||
// So(not.MatchSeverity(m.AlertSeverityCritical), ShouldBeTrue)
|
||||
// })
|
||||
//
|
||||
// Convey("does not match", func() {
|
||||
// json := `
|
||||
// {
|
||||
// "severityFilter": "critical"
|
||||
// }`
|
||||
//
|
||||
// settingsJSON, _ := simplejson.NewJson([]byte(json))
|
||||
// not := NewNotifierBase("ops", "email", settingsJSON)
|
||||
// So(not.MatchSeverity(m.AlertSeverityWarning), ShouldBeFalse)
|
||||
// })
|
||||
// })
|
||||
}
|
||||
|
||||
@@ -47,16 +47,15 @@ func (this *EmailNotifier) Notify(context *alerting.EvalContext) {
|
||||
|
||||
cmd := &m.SendEmailCommand{
|
||||
Data: map[string]interface{}{
|
||||
"Title": context.GetNotificationTitle(),
|
||||
"State": context.Rule.State,
|
||||
"Name": context.Rule.Name,
|
||||
"Severity": context.Rule.Severity,
|
||||
"SeverityColor": context.GetStateModel().Color,
|
||||
"Message": context.Rule.Message,
|
||||
"RuleUrl": ruleUrl,
|
||||
"ImageLink": context.ImagePublicUrl,
|
||||
"AlertPageUrl": setting.AppUrl + "alerting",
|
||||
"EvalMatches": context.EvalMatches,
|
||||
"Title": context.GetNotificationTitle(),
|
||||
"State": context.Rule.State,
|
||||
"Name": context.Rule.Name,
|
||||
"StateModel": context.GetStateModel(),
|
||||
"Message": context.Rule.Message,
|
||||
"RuleUrl": ruleUrl,
|
||||
"ImageLink": context.ImagePublicUrl,
|
||||
"AlertPageUrl": setting.AppUrl + "alerting",
|
||||
"EvalMatches": context.EvalMatches,
|
||||
},
|
||||
To: this.Addresses,
|
||||
Template: "alert_notification.html",
|
||||
|
||||
@@ -45,7 +45,6 @@ func (this *WebhookNotifier) Notify(context *alerting.EvalContext) {
|
||||
bodyJSON.Set("ruleId", context.Rule.Id)
|
||||
bodyJSON.Set("ruleName", context.Rule.Name)
|
||||
bodyJSON.Set("state", context.Rule.State)
|
||||
bodyJSON.Set("severity", context.Rule.Severity)
|
||||
bodyJSON.Set("evalMatches", context.EvalMatches)
|
||||
|
||||
ruleUrl, err := context.GetRuleUrl()
|
||||
|
||||
@@ -34,11 +34,11 @@ func (handler *DefaultResultHandler) Handle(ctx *EvalContext) {
|
||||
annotationData := simplejson.New()
|
||||
if ctx.Error != nil {
|
||||
handler.log.Error("Alert Rule Result Error", "ruleId", ctx.Rule.Id, "error", ctx.Error)
|
||||
ctx.Rule.State = m.AlertStateExeuctionError
|
||||
ctx.Rule.State = m.AlertStateExecError
|
||||
exeuctionError = ctx.Error.Error()
|
||||
annotationData.Set("errorMessage", exeuctionError)
|
||||
} else if ctx.Firing {
|
||||
ctx.Rule.State = m.AlertStateType(ctx.Rule.Severity)
|
||||
ctx.Rule.State = m.AlertStateAlerting
|
||||
annotationData = simplejson.NewFromAny(ctx.EvalMatches)
|
||||
} else {
|
||||
// handle no data case
|
||||
@@ -90,17 +90,15 @@ func (handler *DefaultResultHandler) Handle(ctx *EvalContext) {
|
||||
|
||||
func countStateResult(state m.AlertStateType) {
|
||||
switch state {
|
||||
case m.AlertStateCritical:
|
||||
metrics.M_Alerting_Result_State_Critical.Inc(1)
|
||||
case m.AlertStateWarning:
|
||||
metrics.M_Alerting_Result_State_Warning.Inc(1)
|
||||
case m.AlertStateAlerting:
|
||||
metrics.M_Alerting_Result_State_Alerting.Inc(1)
|
||||
case m.AlertStateOK:
|
||||
metrics.M_Alerting_Result_State_Ok.Inc(1)
|
||||
case m.AlertStatePaused:
|
||||
metrics.M_Alerting_Result_State_Paused.Inc(1)
|
||||
case m.AlertStateUnknown:
|
||||
metrics.M_Alerting_Result_State_Unknown.Inc(1)
|
||||
case m.AlertStateExeuctionError:
|
||||
metrics.M_Alerting_Result_State_ExecutionError.Inc(1)
|
||||
case m.AlertStateNoData:
|
||||
metrics.M_Alerting_Result_State_NoData.Inc(1)
|
||||
case m.AlertStateExecError:
|
||||
metrics.M_Alerting_Result_State_ExecError.Inc(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ type Rule struct {
|
||||
Message string
|
||||
NoDataState m.AlertStateType
|
||||
State m.AlertStateType
|
||||
Severity m.AlertSeverityType
|
||||
Conditions []Condition
|
||||
Notifications []int64
|
||||
}
|
||||
@@ -66,9 +65,8 @@ func NewRuleFromDBAlert(ruleDef *m.Alert) (*Rule, error) {
|
||||
model.Name = ruleDef.Name
|
||||
model.Message = ruleDef.Message
|
||||
model.Frequency = ruleDef.Frequency
|
||||
model.Severity = ruleDef.Severity
|
||||
model.State = ruleDef.State
|
||||
model.NoDataState = m.AlertStateType(ruleDef.Settings.Get("noDataState").MustString("unknown"))
|
||||
model.NoDataState = m.AlertStateType(ruleDef.Settings.Get("noDataState").MustString("no_data"))
|
||||
|
||||
for _, v := range ruleDef.Settings.Get("notifications").MustArray() {
|
||||
jsonModel := simplejson.NewFromAny(v)
|
||||
|
||||
@@ -4,11 +4,11 @@ import (
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
type NotificationTestCommand struct {
|
||||
Severity string
|
||||
State m.AlertStateType
|
||||
Name string
|
||||
Type string
|
||||
Settings *simplejson.Json
|
||||
@@ -22,7 +22,7 @@ func init() {
|
||||
func handleNotificationTestCommand(cmd *NotificationTestCommand) error {
|
||||
notifier := NewRootNotifier()
|
||||
|
||||
model := &models.AlertNotification{
|
||||
model := &m.AlertNotification{
|
||||
Name: cmd.Name,
|
||||
Type: cmd.Type,
|
||||
Settings: cmd.Settings,
|
||||
@@ -35,23 +35,12 @@ func handleNotificationTestCommand(cmd *NotificationTestCommand) error {
|
||||
return err
|
||||
}
|
||||
|
||||
severity := models.AlertSeverityType(cmd.Severity)
|
||||
notifier.sendNotifications([]Notifier{notifiers}, createTestEvalContext(severity))
|
||||
notifier.sendNotifications([]Notifier{notifiers}, createTestEvalContext(cmd.State))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createTestEvalContext(severity models.AlertSeverityType) *EvalContext {
|
||||
state := models.AlertStateOK
|
||||
firing := false
|
||||
if severity == models.AlertSeverityCritical {
|
||||
state = models.AlertStateCritical
|
||||
firing = true
|
||||
}
|
||||
if severity == models.AlertSeverityWarning {
|
||||
state = models.AlertStateWarning
|
||||
firing = true
|
||||
}
|
||||
func createTestEvalContext(state m.AlertStateType) *EvalContext {
|
||||
|
||||
testRule := &Rule{
|
||||
DashboardId: 1,
|
||||
@@ -59,23 +48,22 @@ func createTestEvalContext(severity models.AlertSeverityType) *EvalContext {
|
||||
Name: "Test notification",
|
||||
Message: "Someone is testing the alert notification within grafana.",
|
||||
State: state,
|
||||
Severity: severity,
|
||||
}
|
||||
|
||||
ctx := NewEvalContext(testRule)
|
||||
ctx.ImagePublicUrl = "http://grafana.org/assets/img/blog/mixed_styles.png"
|
||||
|
||||
ctx.IsTestRun = true
|
||||
ctx.Firing = firing
|
||||
ctx.Firing = state == m.AlertStateAlerting
|
||||
ctx.Error = nil
|
||||
ctx.EvalMatches = evalMatchesBasedOnSeverity(severity)
|
||||
ctx.EvalMatches = evalMatchesBasedOnState(state)
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
||||
func evalMatchesBasedOnSeverity(severity models.AlertSeverityType) []*EvalMatch {
|
||||
func evalMatchesBasedOnState(state m.AlertStateType) []*EvalMatch {
|
||||
matches := make([]*EvalMatch, 0)
|
||||
if severity == models.AlertSeverityOK {
|
||||
if state == m.AlertStateOK {
|
||||
return matches
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user