feat(alerting): removed severity

This commit is contained in:
Torkel Ödegaard
2016-09-13 15:09:55 +02:00
parent 6375418d8c
commit b0c7e61ef8
23 changed files with 143 additions and 238 deletions

View File

@@ -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)

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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}

View File

@@ -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 {

View File

@@ -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)
// })
// })
}

View File

@@ -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",

View File

@@ -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()

View File

@@ -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)
}
}

View File

@@ -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)

View File

@@ -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
}