|
@@ -5,8 +5,10 @@ import (
|
|
|
"testing"
|
|
"testing"
|
|
|
"time"
|
|
"time"
|
|
|
|
|
|
|
|
|
|
+ "github.com/stretchr/testify/assert"
|
|
|
|
|
+
|
|
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
|
|
- m "github.com/grafana/grafana/pkg/models"
|
|
|
|
|
|
|
+ "github.com/grafana/grafana/pkg/models"
|
|
|
"github.com/grafana/grafana/pkg/services/alerting"
|
|
"github.com/grafana/grafana/pkg/services/alerting"
|
|
|
. "github.com/smartystreets/goconvey/convey"
|
|
. "github.com/smartystreets/goconvey/convey"
|
|
|
)
|
|
)
|
|
@@ -16,76 +18,76 @@ func TestShouldSendAlertNotification(t *testing.T) {
|
|
|
|
|
|
|
|
tcs := []struct {
|
|
tcs := []struct {
|
|
|
name string
|
|
name string
|
|
|
- prevState m.AlertStateType
|
|
|
|
|
- newState m.AlertStateType
|
|
|
|
|
|
|
+ prevState models.AlertStateType
|
|
|
|
|
+ newState models.AlertStateType
|
|
|
sendReminder bool
|
|
sendReminder bool
|
|
|
frequency time.Duration
|
|
frequency time.Duration
|
|
|
- state *m.AlertNotificationState
|
|
|
|
|
|
|
+ state *models.AlertNotificationState
|
|
|
|
|
|
|
|
expect bool
|
|
expect bool
|
|
|
}{
|
|
}{
|
|
|
{
|
|
{
|
|
|
name: "pending -> ok should not trigger an notification",
|
|
name: "pending -> ok should not trigger an notification",
|
|
|
- newState: m.AlertStateOK,
|
|
|
|
|
- prevState: m.AlertStatePending,
|
|
|
|
|
|
|
+ newState: models.AlertStateOK,
|
|
|
|
|
+ prevState: models.AlertStatePending,
|
|
|
sendReminder: false,
|
|
sendReminder: false,
|
|
|
|
|
|
|
|
expect: false,
|
|
expect: false,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
name: "ok -> alerting should trigger an notification",
|
|
name: "ok -> alerting should trigger an notification",
|
|
|
- newState: m.AlertStateAlerting,
|
|
|
|
|
- prevState: m.AlertStateOK,
|
|
|
|
|
|
|
+ newState: models.AlertStateAlerting,
|
|
|
|
|
+ prevState: models.AlertStateOK,
|
|
|
sendReminder: false,
|
|
sendReminder: false,
|
|
|
|
|
|
|
|
expect: true,
|
|
expect: true,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
name: "ok -> pending should not trigger an notification",
|
|
name: "ok -> pending should not trigger an notification",
|
|
|
- newState: m.AlertStatePending,
|
|
|
|
|
- prevState: m.AlertStateOK,
|
|
|
|
|
|
|
+ newState: models.AlertStatePending,
|
|
|
|
|
+ prevState: models.AlertStateOK,
|
|
|
sendReminder: false,
|
|
sendReminder: false,
|
|
|
|
|
|
|
|
expect: false,
|
|
expect: false,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
name: "ok -> ok should not trigger an notification",
|
|
name: "ok -> ok should not trigger an notification",
|
|
|
- newState: m.AlertStateOK,
|
|
|
|
|
- prevState: m.AlertStateOK,
|
|
|
|
|
|
|
+ newState: models.AlertStateOK,
|
|
|
|
|
+ prevState: models.AlertStateOK,
|
|
|
sendReminder: false,
|
|
sendReminder: false,
|
|
|
|
|
|
|
|
expect: false,
|
|
expect: false,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
name: "ok -> ok with reminder should not trigger an notification",
|
|
name: "ok -> ok with reminder should not trigger an notification",
|
|
|
- newState: m.AlertStateOK,
|
|
|
|
|
- prevState: m.AlertStateOK,
|
|
|
|
|
|
|
+ newState: models.AlertStateOK,
|
|
|
|
|
+ prevState: models.AlertStateOK,
|
|
|
sendReminder: true,
|
|
sendReminder: true,
|
|
|
|
|
|
|
|
expect: false,
|
|
expect: false,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
name: "alerting -> ok should trigger an notification",
|
|
name: "alerting -> ok should trigger an notification",
|
|
|
- newState: m.AlertStateOK,
|
|
|
|
|
- prevState: m.AlertStateAlerting,
|
|
|
|
|
|
|
+ newState: models.AlertStateOK,
|
|
|
|
|
+ prevState: models.AlertStateAlerting,
|
|
|
sendReminder: false,
|
|
sendReminder: false,
|
|
|
|
|
|
|
|
expect: true,
|
|
expect: true,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
name: "alerting -> ok should trigger an notification when reminders enabled",
|
|
name: "alerting -> ok should trigger an notification when reminders enabled",
|
|
|
- newState: m.AlertStateOK,
|
|
|
|
|
- prevState: m.AlertStateAlerting,
|
|
|
|
|
|
|
+ newState: models.AlertStateOK,
|
|
|
|
|
+ prevState: models.AlertStateAlerting,
|
|
|
frequency: time.Minute * 10,
|
|
frequency: time.Minute * 10,
|
|
|
sendReminder: true,
|
|
sendReminder: true,
|
|
|
- state: &m.AlertNotificationState{UpdatedAt: tnow.Add(-time.Minute).Unix()},
|
|
|
|
|
|
|
+ state: &models.AlertNotificationState{UpdatedAt: tnow.Add(-time.Minute).Unix()},
|
|
|
|
|
|
|
|
expect: true,
|
|
expect: true,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
name: "alerting -> alerting with reminder and no state should trigger",
|
|
name: "alerting -> alerting with reminder and no state should trigger",
|
|
|
- newState: m.AlertStateAlerting,
|
|
|
|
|
- prevState: m.AlertStateAlerting,
|
|
|
|
|
|
|
+ newState: models.AlertStateAlerting,
|
|
|
|
|
+ prevState: models.AlertStateAlerting,
|
|
|
frequency: time.Minute * 10,
|
|
frequency: time.Minute * 10,
|
|
|
sendReminder: true,
|
|
sendReminder: true,
|
|
|
|
|
|
|
@@ -93,78 +95,84 @@ func TestShouldSendAlertNotification(t *testing.T) {
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
name: "alerting -> alerting with reminder and last notification sent 1 minute ago should not trigger",
|
|
name: "alerting -> alerting with reminder and last notification sent 1 minute ago should not trigger",
|
|
|
- newState: m.AlertStateAlerting,
|
|
|
|
|
- prevState: m.AlertStateAlerting,
|
|
|
|
|
|
|
+ newState: models.AlertStateAlerting,
|
|
|
|
|
+ prevState: models.AlertStateAlerting,
|
|
|
frequency: time.Minute * 10,
|
|
frequency: time.Minute * 10,
|
|
|
sendReminder: true,
|
|
sendReminder: true,
|
|
|
- state: &m.AlertNotificationState{UpdatedAt: tnow.Add(-time.Minute).Unix()},
|
|
|
|
|
|
|
+ state: &models.AlertNotificationState{UpdatedAt: tnow.Add(-time.Minute).Unix()},
|
|
|
|
|
|
|
|
expect: false,
|
|
expect: false,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
name: "alerting -> alerting with reminder and last notifciation sent 11 minutes ago should trigger",
|
|
name: "alerting -> alerting with reminder and last notifciation sent 11 minutes ago should trigger",
|
|
|
- newState: m.AlertStateAlerting,
|
|
|
|
|
- prevState: m.AlertStateAlerting,
|
|
|
|
|
|
|
+ newState: models.AlertStateAlerting,
|
|
|
|
|
+ prevState: models.AlertStateAlerting,
|
|
|
frequency: time.Minute * 10,
|
|
frequency: time.Minute * 10,
|
|
|
sendReminder: true,
|
|
sendReminder: true,
|
|
|
- state: &m.AlertNotificationState{UpdatedAt: tnow.Add(-11 * time.Minute).Unix()},
|
|
|
|
|
|
|
+ state: &models.AlertNotificationState{UpdatedAt: tnow.Add(-11 * time.Minute).Unix()},
|
|
|
|
|
|
|
|
expect: true,
|
|
expect: true,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
name: "OK -> alerting with notifciation state pending and updated 30 seconds ago should not trigger",
|
|
name: "OK -> alerting with notifciation state pending and updated 30 seconds ago should not trigger",
|
|
|
- newState: m.AlertStateAlerting,
|
|
|
|
|
- prevState: m.AlertStateOK,
|
|
|
|
|
- state: &m.AlertNotificationState{State: m.AlertNotificationStatePending, UpdatedAt: tnow.Add(-30 * time.Second).Unix()},
|
|
|
|
|
|
|
+ newState: models.AlertStateAlerting,
|
|
|
|
|
+ prevState: models.AlertStateOK,
|
|
|
|
|
+ state: &models.AlertNotificationState{State: models.AlertNotificationStatePending, UpdatedAt: tnow.Add(-30 * time.Second).Unix()},
|
|
|
|
|
|
|
|
expect: false,
|
|
expect: false,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
name: "OK -> alerting with notifciation state pending and updated 2 minutes ago should trigger",
|
|
name: "OK -> alerting with notifciation state pending and updated 2 minutes ago should trigger",
|
|
|
- newState: m.AlertStateAlerting,
|
|
|
|
|
- prevState: m.AlertStateOK,
|
|
|
|
|
- state: &m.AlertNotificationState{State: m.AlertNotificationStatePending, UpdatedAt: tnow.Add(-2 * time.Minute).Unix()},
|
|
|
|
|
|
|
+ newState: models.AlertStateAlerting,
|
|
|
|
|
+ prevState: models.AlertStateOK,
|
|
|
|
|
+ state: &models.AlertNotificationState{State: models.AlertNotificationStatePending, UpdatedAt: tnow.Add(-2 * time.Minute).Unix()},
|
|
|
|
|
|
|
|
expect: true,
|
|
expect: true,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
name: "unknown -> ok",
|
|
name: "unknown -> ok",
|
|
|
- prevState: m.AlertStateUnknown,
|
|
|
|
|
- newState: m.AlertStateOK,
|
|
|
|
|
|
|
+ prevState: models.AlertStateUnknown,
|
|
|
|
|
+ newState: models.AlertStateOK,
|
|
|
|
|
|
|
|
expect: false,
|
|
expect: false,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
name: "unknown -> pending",
|
|
name: "unknown -> pending",
|
|
|
- prevState: m.AlertStateUnknown,
|
|
|
|
|
- newState: m.AlertStatePending,
|
|
|
|
|
|
|
+ prevState: models.AlertStateUnknown,
|
|
|
|
|
+ newState: models.AlertStatePending,
|
|
|
|
|
|
|
|
expect: false,
|
|
expect: false,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
name: "unknown -> alerting",
|
|
name: "unknown -> alerting",
|
|
|
- prevState: m.AlertStateUnknown,
|
|
|
|
|
- newState: m.AlertStateAlerting,
|
|
|
|
|
|
|
+ prevState: models.AlertStateUnknown,
|
|
|
|
|
+ newState: models.AlertStateAlerting,
|
|
|
|
|
|
|
|
expect: true,
|
|
expect: true,
|
|
|
},
|
|
},
|
|
|
|
|
+ {
|
|
|
|
|
+ name: "no_data -> pending",
|
|
|
|
|
+ prevState: models.AlertStateNoData,
|
|
|
|
|
+ newState: models.AlertStatePending,
|
|
|
|
|
+
|
|
|
|
|
+ expect: false,
|
|
|
|
|
+ },
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range tcs {
|
|
for _, tc := range tcs {
|
|
|
- evalContext := alerting.NewEvalContext(context.TODO(), &alerting.Rule{
|
|
|
|
|
|
|
+ evalContext := alerting.NewEvalContext(context.Background(), &alerting.Rule{
|
|
|
State: tc.prevState,
|
|
State: tc.prevState,
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
if tc.state == nil {
|
|
if tc.state == nil {
|
|
|
- tc.state = &m.AlertNotificationState{}
|
|
|
|
|
|
|
+ tc.state = &models.AlertNotificationState{}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
evalContext.Rule.State = tc.newState
|
|
evalContext.Rule.State = tc.newState
|
|
|
nb := &NotifierBase{SendReminder: tc.sendReminder, Frequency: tc.frequency}
|
|
nb := &NotifierBase{SendReminder: tc.sendReminder, Frequency: tc.frequency}
|
|
|
|
|
|
|
|
- if nb.ShouldNotify(evalContext.Ctx, evalContext, tc.state) != tc.expect {
|
|
|
|
|
- t.Errorf("failed test %s.\n expected \n%+v \nto return: %v", tc.name, tc, tc.expect)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ r := nb.ShouldNotify(evalContext.Ctx, evalContext, tc.state)
|
|
|
|
|
+ assert.Equal(t, r, tc.expect, "failed test %s. expected %+v to return: %v", tc.name, tc, tc.expect)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -172,7 +180,7 @@ func TestBaseNotifier(t *testing.T) {
|
|
|
Convey("default constructor for notifiers", t, func() {
|
|
Convey("default constructor for notifiers", t, func() {
|
|
|
bJson := simplejson.New()
|
|
bJson := simplejson.New()
|
|
|
|
|
|
|
|
- model := &m.AlertNotification{
|
|
|
|
|
|
|
+ model := &models.AlertNotification{
|
|
|
Uid: "1",
|
|
Uid: "1",
|
|
|
Name: "name",
|
|
Name: "name",
|
|
|
Type: "email",
|
|
Type: "email",
|