func TestDedupingNotifier(t *testing.T) { var ( record = &recordNotifier{} notifies = provider.NewMemNotifies(provider.NewMemData()) deduper = Dedup(notifies, record) ctx = context.Background() ) now := time.Now() ctx = WithReceiver(ctx, "name") ctx = WithRepeatInterval(ctx, time.Duration(100*time.Minute)) ctx = WithNow(ctx, now) alerts := []*types.Alert{ { Alert: model.Alert{ Labels: model.LabelSet{"alertname": "0"}, }, }, { Alert: model.Alert{ Labels: model.LabelSet{"alertname": "1"}, EndsAt: now.Add(-5 * time.Minute), }, }, } // Set an initial NotifyInfo to ensure that on notification failure // nothing changes. nsBefore := []*types.NotifyInfo{ nil, { Alert: alerts[1].Fingerprint(), Receiver: "name", Resolved: false, Timestamp: now.Add(-10 * time.Minute), }, } if err := notifies.Set(nsBefore...); err != nil { t.Fatalf("Setting notifies failed: %s", err) } deduper.notifier = &failNotifier{} if err := deduper.Notify(ctx, alerts...); err == nil { t.Fatalf("Fail notifier did not fail") } // After a failing notify the notifies data must be unchanged. nsCur, err := notifies.Get("name", alerts[0].Fingerprint(), alerts[1].Fingerprint()) if err != nil { t.Fatalf("Error getting notify info: %s", err) } if !reflect.DeepEqual(nsBefore, nsCur) { t.Fatalf("Notify info data has changed unexpectedly") } deduper.notifier = record if err := deduper.Notify(ctx, alerts...); err != nil { t.Fatalf("Notify failed: %s", err) } if !reflect.DeepEqual(record.alerts, alerts) { t.Fatalf("Expected alerts %v, got %v", alerts, record.alerts) } nsCur, err = notifies.Get("name", alerts[0].Fingerprint(), alerts[1].Fingerprint()) if err != nil { t.Fatalf("Error getting notifies: %s", err) } nsAfter := []*types.NotifyInfo{ { Alert: alerts[0].Fingerprint(), Receiver: "name", Resolved: false, Timestamp: now, }, { Alert: alerts[1].Fingerprint(), Receiver: "name", Resolved: true, Timestamp: now, }, } for i, after := range nsAfter { cur := nsCur[i] // Hack correct timestamps back in if they are sane. if cur != nil && after.Timestamp.IsZero() { if cur.Timestamp.Before(now) { t.Fatalf("Wrong timestamp for notify %v", cur) } after.Timestamp = cur.Timestamp } if !reflect.DeepEqual(after, cur) { t.Errorf("Unexpected notifies, expected: %v, got: %v", after, cur) } } }
func TestDedupingNotifier(t *testing.T) { var ( record = &recordNotifier{} notifies = provider.NewMemNotifies(provider.NewMemData()) deduper = Dedup(notifies, record) ctx = context.Background() ) now := time.Now() ctx = WithReceiver(ctx, "name") ctx = WithRepeatInterval(ctx, time.Duration(100*time.Minute)) ctx = WithNow(ctx, now) alerts := []*types.Alert{ { Alert: model.Alert{ Labels: model.LabelSet{"alertname": "0"}, }, }, { Alert: model.Alert{ Labels: model.LabelSet{"alertname": "1"}, EndsAt: now.Add(-5 * time.Minute), }, }, { Alert: model.Alert{ Labels: model.LabelSet{"alertname": "2"}, EndsAt: now.Add(-9 * time.Minute), }, }, { Alert: model.Alert{ Labels: model.LabelSet{"alertname": "3"}, EndsAt: now.Add(-10 * time.Minute), }, }, { Alert: model.Alert{ Labels: model.LabelSet{"alertname": "4"}, }, }, { Alert: model.Alert{ Labels: model.LabelSet{"alertname": "5"}, }, }, } var fps []model.Fingerprint for _, a := range alerts { fps = append(fps, a.Fingerprint()) } nsBefore := []*types.NotifyInfo{ // The first a new alert starting now. nil, // The second alert was not previously notified about and // is already resolved. nil, // The third alert is an attempt to resolve a previously // firing alert. { Alert: fps[2], Receiver: "name", Resolved: false, Timestamp: now.Add(-10 * time.Minute), }, // The fourth alert is an attempt to resolve an alert again // even though the previous notification succeeded. { Alert: fps[3], Receiver: "name", Resolved: true, Timestamp: now.Add(-10 * time.Minute), }, // The fifth alert resends a previously successful notification // that was longer than ago than the repeat interval. { Alert: fps[4], Receiver: "name", Resolved: false, Timestamp: now.Add(-110 * time.Minute), }, // The sixth alert is a firing again after being resolved before. { Alert: fps[5], Receiver: "name", Resolved: true, Timestamp: now.Add(3 * time.Minute), }, } if err := notifies.Set(nsBefore...); err != nil { t.Fatalf("Setting notifies failed: %s", err) } deduper.notifier = &failNotifier{} if err := deduper.Notify(ctx, alerts...); err == nil { t.Fatalf("Fail notifier did not fail") } // After a failing notify the notifies data must be unchanged. nsCur, err := notifies.Get("name", fps...) if err != nil { t.Fatalf("Error getting notify info: %s", err) } if !reflect.DeepEqual(nsBefore, nsCur) { t.Fatalf("Notify info data has changed unexpectedly") } deduper.notifier = record if err := deduper.Notify(ctx, alerts...); err != nil { t.Fatalf("Notify failed: %s", err) } alertsExp := []*types.Alert{ alerts[0], alerts[2], alerts[4], alerts[5], } nsAfter := []*types.NotifyInfo{ { Alert: fps[0], Receiver: "name", Resolved: false, }, nil, { Alert: fps[2], Receiver: "name", Resolved: true, }, nsBefore[3], { Alert: fps[4], Receiver: "name", Resolved: false, }, { Alert: fps[5], Receiver: "name", Resolved: false, }, } if !reflect.DeepEqual(record.alerts, alertsExp) { t.Fatalf("Expected alerts %v, got %v", alertsExp, record.alerts) } nsCur, err = notifies.Get("name", fps...) if err != nil { t.Fatalf("Error getting notifies: %s", err) } for i, after := range nsAfter { cur := nsCur[i] // Hack correct timestamps back in if they are sane. if cur != nil && after.Timestamp.IsZero() { if cur.Timestamp.Before(now) { t.Fatalf("Wrong timestamp for notify %v", cur) } after.Timestamp = cur.Timestamp } if !reflect.DeepEqual(after, cur) { t.Errorf("Unexpected notifies, expected: %v, got: %v", after, cur) } } }