Commit 7f1d7cef by bergquist

reminder: uses UpdatedAt to track state changes.

parent 9e09b2b9
...@@ -19,6 +19,7 @@ type AlertNotificationStateType string ...@@ -19,6 +19,7 @@ type AlertNotificationStateType string
var ( var (
AlertNotificationStatePending = AlertNotificationStateType("pending") AlertNotificationStatePending = AlertNotificationStateType("pending")
AlertNotificationStateCompleted = AlertNotificationStateType("completed") AlertNotificationStateCompleted = AlertNotificationStateType("completed")
AlertNotificationStateUnknown = AlertNotificationStateType("unknown")
) )
type AlertNotification struct { type AlertNotification struct {
...@@ -90,10 +91,10 @@ type AlertNotificationState struct { ...@@ -90,10 +91,10 @@ type AlertNotificationState struct {
OrgId int64 OrgId int64
AlertId int64 AlertId int64
NotifierId int64 NotifierId int64
SentAt int64
State AlertNotificationStateType State AlertNotificationStateType
Version int64 Version int64
UpdatedAt int64 UpdatedAt int64
AlertRuleStateUpdatedVersion int64
} }
type SetAlertNotificationStateToPendingCommand struct { type SetAlertNotificationStateToPendingCommand struct {
......
...@@ -68,7 +68,7 @@ func (n *notificationService) sendAndMarkAsComplete(evalContext *EvalContext, no ...@@ -68,7 +68,7 @@ func (n *notificationService) sendAndMarkAsComplete(evalContext *EvalContext, no
if err != nil { if err != nil {
n.log.Error("failed to send notification", "id", not.GetNotifierId()) n.log.Error("failed to send notification", "id", not.GetNotifierId())
} else { } else {
notifierState.state.SentAt = time.Now().UTC().Unix() notifierState.state.UpdatedAt = time.Now().UTC().Unix()
} }
if evalContext.IsTestRun { if evalContext.IsTestRun {
...@@ -185,7 +185,7 @@ func (n *notificationService) getNeededNotifiers(orgId int64, notificationIds [] ...@@ -185,7 +185,7 @@ func (n *notificationService) getNeededNotifiers(orgId int64, notificationIds []
err = bus.DispatchCtx(evalContext.Ctx, query) err = bus.DispatchCtx(evalContext.Ctx, query)
if err != nil { if err != nil {
n.log.Error("Could not get notification state.", "notifier", notification.Id) n.log.Error("Could not get notification state.", "notifier", notification.Id, "error", err)
continue continue
} }
......
...@@ -53,8 +53,8 @@ func defaultShouldNotify(context *alerting.EvalContext, sendReminder bool, frequ ...@@ -53,8 +53,8 @@ func defaultShouldNotify(context *alerting.EvalContext, sendReminder bool, frequ
if context.PrevAlertState == context.Rule.State && sendReminder { if context.PrevAlertState == context.Rule.State && sendReminder {
// Do not notify if interval has not elapsed // Do not notify if interval has not elapsed
lastNotify := time.Unix(notificationState.SentAt, 0) lastNotify := time.Unix(notificationState.UpdatedAt, 0)
if notificationState.SentAt != 0 && lastNotify.Add(frequency).After(time.Now()) { if notificationState.UpdatedAt != 0 && lastNotify.Add(frequency).After(time.Now()) {
return false return false
} }
......
...@@ -84,7 +84,7 @@ func TestShouldSendAlertNotification(t *testing.T) { ...@@ -84,7 +84,7 @@ func TestShouldSendAlertNotification(t *testing.T) {
prevState: m.AlertStateAlerting, prevState: m.AlertStateAlerting,
frequency: time.Minute * 10, frequency: time.Minute * 10,
sendReminder: true, sendReminder: true,
state: &m.AlertNotificationState{SentAt: tnow.Add(-time.Minute).Unix()}, state: &m.AlertNotificationState{UpdatedAt: tnow.Add(-time.Minute).Unix()},
expect: true, expect: true,
}, },
...@@ -104,7 +104,7 @@ func TestShouldSendAlertNotification(t *testing.T) { ...@@ -104,7 +104,7 @@ func TestShouldSendAlertNotification(t *testing.T) {
prevState: m.AlertStateAlerting, prevState: m.AlertStateAlerting,
frequency: time.Minute * 10, frequency: time.Minute * 10,
sendReminder: true, sendReminder: true,
state: &m.AlertNotificationState{SentAt: tnow.Add(-time.Minute).Unix()}, state: &m.AlertNotificationState{UpdatedAt: tnow.Add(-time.Minute).Unix()},
expect: false, expect: false,
}, },
...@@ -114,7 +114,7 @@ func TestShouldSendAlertNotification(t *testing.T) { ...@@ -114,7 +114,7 @@ func TestShouldSendAlertNotification(t *testing.T) {
prevState: m.AlertStateAlerting, prevState: m.AlertStateAlerting,
frequency: time.Minute * 10, frequency: time.Minute * 10,
sendReminder: true, sendReminder: true,
state: &m.AlertNotificationState{SentAt: tnow.Add(-11 * time.Minute).Unix()}, state: &m.AlertNotificationState{UpdatedAt: tnow.Add(-11 * time.Minute).Unix()},
expect: true, expect: true,
}, },
......
...@@ -102,6 +102,7 @@ func NewRuleFromDBAlert(ruleDef *m.Alert) (*Rule, error) { ...@@ -102,6 +102,7 @@ func NewRuleFromDBAlert(ruleDef *m.Alert) (*Rule, error) {
model.State = ruleDef.State model.State = ruleDef.State
model.NoDataState = m.NoDataOption(ruleDef.Settings.Get("noDataState").MustString("no_data")) model.NoDataState = m.NoDataOption(ruleDef.Settings.Get("noDataState").MustString("no_data"))
model.ExecutionErrorState = m.ExecutionErrorOption(ruleDef.Settings.Get("executionErrorState").MustString("alerting")) model.ExecutionErrorState = m.ExecutionErrorOption(ruleDef.Settings.Get("executionErrorState").MustString("alerting"))
model.StateChanges = ruleDef.StateChanges
for _, v := range ruleDef.Settings.Get("notifications").MustArray() { for _, v := range ruleDef.Settings.Get("notifications").MustArray() {
jsonModel := simplejson.NewFromAny(v) jsonModel := simplejson.NewFromAny(v)
......
...@@ -249,12 +249,11 @@ func SetAlertNotificationStateToCompleteCommand(ctx context.Context, cmd *m.SetA ...@@ -249,12 +249,11 @@ func SetAlertNotificationStateToCompleteCommand(ctx context.Context, cmd *m.SetA
sql := `UPDATE alert_notification_state SET sql := `UPDATE alert_notification_state SET
state = ?, state = ?,
version = ?, version = ?,
sent_at = ?,
updated_at = ? updated_at = ?
WHERE WHERE
id = ?` id = ?`
_, err := sess.Exec(sql, cmd.State.State, cmd.State.Version, cmd.State.SentAt, timeNow().Unix(), cmd.State.Id) _, err := sess.Exec(sql, cmd.State.State, cmd.State.Version, timeNow().Unix(), cmd.State.Id)
if err != nil { if err != nil {
return err return err
...@@ -325,7 +324,7 @@ func GetAlertNotificationState(ctx context.Context, cmd *m.GetNotificationStateQ ...@@ -325,7 +324,7 @@ func GetAlertNotificationState(ctx context.Context, cmd *m.GetNotificationStateQ
OrgId: cmd.OrgId, OrgId: cmd.OrgId,
AlertId: cmd.AlertId, AlertId: cmd.AlertId,
NotifierId: cmd.NotifierId, NotifierId: cmd.NotifierId,
State: "unknown", State: m.AlertNotificationStateUnknown,
UpdatedAt: timeNow().Unix(), UpdatedAt: timeNow().Unix(),
} }
...@@ -354,10 +353,9 @@ func GetAlertNotificationState(ctx context.Context, cmd *m.GetNotificationStateQ ...@@ -354,10 +353,9 @@ func GetAlertNotificationState(ctx context.Context, cmd *m.GetNotificationStateQ
} }
func getAlertNotificationState(sess *DBSession, cmd *m.GetNotificationStateQuery, nj *m.AlertNotificationState) (bool, error) { func getAlertNotificationState(sess *DBSession, cmd *m.GetNotificationStateQuery, nj *m.AlertNotificationState) (bool, error) {
exist, err := sess. return sess.
Where("alert_notification_state.org_id = ?", cmd.OrgId). Where("alert_notification_state.org_id = ?", cmd.OrgId).
Where("alert_notification_state.alert_id = ?", cmd.AlertId). Where("alert_notification_state.alert_id = ?", cmd.AlertId).
Where("alert_notification_state.notifier_id = ?", cmd.NotifierId). Where("alert_notification_state.notifier_id = ?", cmd.NotifierId).
Get(nj) Get(nj)
return exist, err
} }
...@@ -117,10 +117,10 @@ func addAlertMigrations(mg *Migrator) { ...@@ -117,10 +117,10 @@ func addAlertMigrations(mg *Migrator) {
{Name: "org_id", Type: DB_BigInt, Nullable: false}, {Name: "org_id", Type: DB_BigInt, Nullable: false},
{Name: "alert_id", Type: DB_BigInt, Nullable: false}, {Name: "alert_id", Type: DB_BigInt, Nullable: false},
{Name: "notifier_id", Type: DB_BigInt, Nullable: false}, {Name: "notifier_id", Type: DB_BigInt, Nullable: false},
{Name: "sent_at", Type: DB_BigInt, Nullable: false},
{Name: "state", Type: DB_NVarchar, Length: 50, Nullable: false}, {Name: "state", Type: DB_NVarchar, Length: 50, Nullable: false},
{Name: "version", Type: DB_BigInt, Nullable: false}, {Name: "version", Type: DB_BigInt, Nullable: false},
{Name: "updated_at", Type: DB_BigInt, Nullable: false}, {Name: "updated_at", Type: DB_BigInt, Nullable: false},
{Name: "alert_rule_state_updated_version", Type: DB_BigInt, Nullable: false},
}, },
Indices: []*Index{ Indices: []*Index{
{Cols: []string{"org_id", "alert_id", "notifier_id"}, Type: UniqueIndex}, {Cols: []string{"org_id", "alert_id", "notifier_id"}, Type: UniqueIndex},
...@@ -130,8 +130,4 @@ func addAlertMigrations(mg *Migrator) { ...@@ -130,8 +130,4 @@ func addAlertMigrations(mg *Migrator) {
mg.AddMigration("create alert_notification_state table v1", NewAddTableMigration(alert_notification_state)) mg.AddMigration("create alert_notification_state table v1", NewAddTableMigration(alert_notification_state))
mg.AddMigration("add index alert_notification_state org_id & alert_id & notifier_id", mg.AddMigration("add index alert_notification_state org_id & alert_id & notifier_id",
NewAddIndexMigration(alert_notification_state, alert_notification_state.Indices[0])) NewAddIndexMigration(alert_notification_state, alert_notification_state.Indices[0]))
mg.AddMigration("Add alert_rule_state_updated_version to alert_notification_state", NewAddColumnMigration(alert_notification_state, &Column{
Name: "alert_rule_state_updated_version", Type: DB_BigInt, Nullable: true,
}))
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment