mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
wip: impl so that get alertstate also creates it if it does not exist
This commit is contained in:
@@ -46,7 +46,7 @@ type AlertmanagerNotifier struct {
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func (this *AlertmanagerNotifier) ShouldNotify(ctx context.Context, evalContext *alerting.EvalContext) bool {
|
||||
func (this *AlertmanagerNotifier) ShouldNotify(ctx context.Context, evalContext *alerting.EvalContext, notificationState *m.AlertNotificationState) bool {
|
||||
this.log.Debug("Should notify", "ruleId", evalContext.Rule.Id, "state", evalContext.Rule.State, "previousState", evalContext.PrevAlertState)
|
||||
|
||||
// Do not notify when we become OK for the first time.
|
||||
|
||||
@@ -2,12 +2,9 @@ package notifiers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
@@ -126,25 +123,27 @@ func TestShouldSendAlertNotification(t *testing.T) {
|
||||
|
||||
func TestShouldNotifyWhenNoJournalingIsFound(t *testing.T) {
|
||||
Convey("base notifier", t, func() {
|
||||
bus.ClearBusHandlers()
|
||||
//bus.ClearBusHandlers()
|
||||
//
|
||||
//notifier := NewNotifierBase(&m.AlertNotification{
|
||||
// Id: 1,
|
||||
// Name: "name",
|
||||
// Type: "email",
|
||||
// Settings: simplejson.New(),
|
||||
//})
|
||||
//evalContext := alerting.NewEvalContext(context.TODO(), &alerting.Rule{})
|
||||
//
|
||||
//Convey("should not notify query returns error", func() {
|
||||
// bus.AddHandlerCtx("", func(ctx context.Context, q *m.GetNotificationStateQuery) error {
|
||||
// return errors.New("some kind of error unknown error")
|
||||
// })
|
||||
//
|
||||
// if notifier.ShouldNotify(context.Background(), evalContext) {
|
||||
// t.Errorf("should not send notifications when query returns error")
|
||||
// }
|
||||
//})
|
||||
|
||||
notifier := NewNotifierBase(&m.AlertNotification{
|
||||
Id: 1,
|
||||
Name: "name",
|
||||
Type: "email",
|
||||
Settings: simplejson.New(),
|
||||
})
|
||||
evalContext := alerting.NewEvalContext(context.TODO(), &alerting.Rule{})
|
||||
|
||||
Convey("should not notify query returns error", func() {
|
||||
bus.AddHandlerCtx("", func(ctx context.Context, q *m.GetNotificationStateQuery) error {
|
||||
return errors.New("some kind of error unknown error")
|
||||
})
|
||||
|
||||
if notifier.ShouldNotify(context.Background(), evalContext) {
|
||||
t.Errorf("should not send notifications when query returns error")
|
||||
}
|
||||
})
|
||||
t.Error("might not need this anymore, at least not like this, control flow has changedd")
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ func handleNotificationTestCommand(cmd *NotificationTestCommand) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return notifier.sendNotifications(createTestEvalContext(cmd), []Notifier{notifiers})
|
||||
return notifier.sendNotifications(createTestEvalContext(cmd), NotifierStateSlice{{notifier: notifiers}})
|
||||
}
|
||||
|
||||
func createTestEvalContext(cmd *NotificationTestCommand) *EvalContext {
|
||||
|
||||
@@ -302,17 +302,20 @@ func GetAlertNotificationState(ctx context.Context, cmd *m.GetNotificationStateQ
|
||||
return withDbSession(ctx, func(sess *DBSession) error {
|
||||
nj := &m.AlertNotificationState{}
|
||||
|
||||
exist, err := sess.Desc("alert_notification_state.sent_at").
|
||||
Where("alert_notification_state.org_id = ?", cmd.OrgId).
|
||||
Where("alert_notification_state.alert_id = ?", cmd.AlertId).
|
||||
Where("alert_notification_state.notifier_id = ?", cmd.NotifierId).
|
||||
Get(nj)
|
||||
exist, err := getAlertNotificationState(sess, cmd, nj)
|
||||
|
||||
// if exists, return it, otherwise create it with default values
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if exist {
|
||||
cmd.Result = nj
|
||||
return nil
|
||||
}
|
||||
|
||||
// normally flow ends here
|
||||
|
||||
if !exist {
|
||||
notificationState := &m.AlertNotificationState{
|
||||
OrgId: cmd.OrgId,
|
||||
@@ -323,30 +326,38 @@ func GetAlertNotificationState(ctx context.Context, cmd *m.GetNotificationStateQ
|
||||
|
||||
_, err := sess.Insert(notificationState)
|
||||
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
uniqenessIndexFailureCodes := []string{
|
||||
"UNIQUE constraint failed",
|
||||
"pq: duplicate key value violates unique constraint",
|
||||
"Error 1062: Duplicate entry ",
|
||||
}
|
||||
|
||||
var alreadyExists bool
|
||||
|
||||
for _, code := range uniqenessIndexFailureCodes {
|
||||
if strings.HasPrefix(err.Error(), code) {
|
||||
alreadyExists = true
|
||||
exist, err = getAlertNotificationState(sess, cmd, nj)
|
||||
|
||||
if exist && err == nil {
|
||||
cmd.Result = nj
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
|
||||
return m.ErrAlertNotificationStateNotFound
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cmd.Result = nj
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func getAlertNotificationState(sess *DBSession, cmd *m.GetNotificationStateQuery, nj *m.AlertNotificationState) (bool, error) {
|
||||
exist, err := sess.Desc("alert_notification_state.sent_at").
|
||||
Where("alert_notification_state.org_id = ?", cmd.OrgId).
|
||||
Where("alert_notification_state.alert_id = ?", cmd.AlertId).
|
||||
Where("alert_notification_state.notifier_id = ?", cmd.NotifierId).
|
||||
Get(nj)
|
||||
return exist, err
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package sqlstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -14,55 +13,57 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
|
||||
Convey("Testing Alert notification sql access", t, func() {
|
||||
InitTestDB(t)
|
||||
|
||||
Convey("Alert notification state", func() {
|
||||
var alertId int64 = 7
|
||||
var orgId int64 = 5
|
||||
var notifierId int64 = 10
|
||||
//Convey("Alert notification state", func() {
|
||||
//var alertId int64 = 7
|
||||
//var orgId int64 = 5
|
||||
//var notifierId int64 = 10
|
||||
|
||||
Convey("Getting no existant state returns error", func() {
|
||||
query := &models.GetNotificationStateQuery{AlertId: alertId, OrgId: orgId, NotifierId: notifierId}
|
||||
err := GetAlertNotificationState(context.Background(), query)
|
||||
So(err, ShouldEqual, models.ErrAlertNotificationStateNotFound)
|
||||
})
|
||||
//Convey("Getting no existant state returns error", func() {
|
||||
// query := &models.GetNotificationStateQuery{AlertId: alertId, OrgId: orgId, NotifierId: notifierId}
|
||||
// err := GetAlertNotificationState(context.Background(), query)
|
||||
// So(err, ShouldEqual, models.ErrAlertNotificationStateNotFound)
|
||||
//})
|
||||
|
||||
Convey("Can insert new state for alert notifier", func() {
|
||||
createCmd := &models.InsertAlertNotificationCommand{
|
||||
AlertId: alertId,
|
||||
NotifierId: notifierId,
|
||||
OrgId: orgId,
|
||||
SentAt: 1,
|
||||
State: models.AlertNotificationStateCompleted,
|
||||
}
|
||||
|
||||
err := InsertAlertNotificationState(context.Background(), createCmd)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = InsertAlertNotificationState(context.Background(), createCmd)
|
||||
So(err, ShouldEqual, models.ErrAlertNotificationStateAlreadyExist)
|
||||
|
||||
Convey("should be able to update alert notifier state", func() {
|
||||
updateCmd := &models.SetAlertNotificationStateToPendingCommand{
|
||||
Id: 1,
|
||||
SentAt: 1,
|
||||
Version: 0,
|
||||
}
|
||||
|
||||
err := SetAlertNotificationStateToPendingCommand(context.Background(), updateCmd)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
Convey("should not be able to set pending on old version", func() {
|
||||
err = SetAlertNotificationStateToPendingCommand(context.Background(), updateCmd)
|
||||
So(err, ShouldEqual, models.ErrAlertNotificationStateVersionConflict)
|
||||
})
|
||||
|
||||
Convey("should be able to set state to completed", func() {
|
||||
cmd := &models.SetAlertNotificationStateToCompleteCommand{Id: 1}
|
||||
err = SetAlertNotificationStateToCompleteCommand(context.Background(), cmd)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
//Convey("Can insert new state for alert notifier", func() {
|
||||
// createCmd := &models.InsertAlertNotificationCommand{
|
||||
// AlertId: alertId,
|
||||
// NotifierId: notifierId,
|
||||
// OrgId: orgId,
|
||||
// SentAt: 1,
|
||||
// State: models.AlertNotificationStateCompleted,
|
||||
// }
|
||||
//
|
||||
// err := InsertAlertNotificationState(context.Background(), createCmd)
|
||||
// So(err, ShouldBeNil)
|
||||
//
|
||||
// err = InsertAlertNotificationState(context.Background(), createCmd)
|
||||
// So(err, ShouldEqual, models.ErrAlertNotificationStateAlreadyExist)
|
||||
//
|
||||
// Convey("should be able to update alert notifier state", func() {
|
||||
// updateCmd := &models.SetAlertNotificationStateToPendingCommand{
|
||||
// State: models.AlertNotificationState{
|
||||
// Id: 1,
|
||||
// SentAt: 1,
|
||||
// Version: 0,
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// err := SetAlertNotificationStateToPendingCommand(context.Background(), updateCmd)
|
||||
// So(err, ShouldBeNil)
|
||||
//
|
||||
// Convey("should not be able to set pending on old version", func() {
|
||||
// err = SetAlertNotificationStateToPendingCommand(context.Background(), updateCmd)
|
||||
// So(err, ShouldEqual, models.ErrAlertNotificationStateVersionConflict)
|
||||
// })
|
||||
//
|
||||
// Convey("should be able to set state to completed", func() {
|
||||
// cmd := &models.SetAlertNotificationStateToCompleteCommand{Id: 1}
|
||||
// err = SetAlertNotificationStateToCompleteCommand(context.Background(), cmd)
|
||||
// So(err, ShouldBeNil)
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
//})
|
||||
|
||||
Convey("Alert notifications should be empty", func() {
|
||||
cmd := &models.GetAlertNotificationsQuery{
|
||||
|
||||
Reference in New Issue
Block a user