Skip to content

Commit

Permalink
nflog: use alert set instead of hash for deduplication
Browse files Browse the repository at this point in the history
Building a hash over an entire set of alerts causes problems, because
the hash differs, on any change, whereas we only want to send
notifications if the alert and it's state have changed. Therefore this
introduces a list of alerts that are active and a list of alerts that
are resolved. If the currently active alerts of a group are a subset of
the ones that have been notified about before then they are
deduplicated. The resolved notifications work the same way, with a
separate list of resolved notifications that have already been sent.
  • Loading branch information
brancz committed Apr 11, 2017
1 parent eaeeab8 commit 1a5b131
Show file tree
Hide file tree
Showing 9 changed files with 321 additions and 191 deletions.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,7 @@ promu:
GOARCH=$(subst x86_64,amd64,$(patsubst i%86,386,$(shell uname -m))) \
$(GO) get -u github.com/prometheus/promu

proto:
scripts/genproto.sh

.PHONY: all style format build test vet assets tarball docker promu
.PHONY: all style format build test vet assets tarball docker promu proto
25 changes: 7 additions & 18 deletions nflog/nflog.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ type Log interface {
// The Log* methods store a notification log entry for
// a fully qualified receiver and a given IDs identifying the
// alert object.
LogActive(r *pb.Receiver, key, hash []byte) error
LogResolved(r *pb.Receiver, key, hash []byte) error
Log(r *pb.Receiver, key []byte, firing, resolved []uint64) error

// Query the log along the given Paramteres.
//
Expand Down Expand Up @@ -325,23 +324,13 @@ Loop:
}
}

// LogActive implements the Log interface.
func (l *nlog) LogActive(r *pb.Receiver, key, hash []byte) error {
return l.log(r, key, hash, false)
}

// LogResolved implements the Log interface.
func (l *nlog) LogResolved(r *pb.Receiver, key, hash []byte) error {
return l.log(r, key, hash, true)
}

// stateKey returns a string key for a log entry consisting of the group key
// and receiver.
func stateKey(k []byte, r *pb.Receiver) string {
return fmt.Sprintf("%s:%s", k, r)
}

func (l *nlog) log(r *pb.Receiver, gkey, ghash []byte, resolved bool) error {
func (l *nlog) Log(r *pb.Receiver, gkey []byte, firingAlerts, resolvedAlerts []uint64) error {
// Write all st with the same timestamp.
now := l.now()
key := stateKey(gkey, r)
Expand Down Expand Up @@ -372,11 +361,11 @@ func (l *nlog) log(r *pb.Receiver, gkey, ghash []byte, resolved bool) error {

e := &pb.MeshEntry{
Entry: &pb.Entry{
Receiver: r,
GroupKey: gkey,
GroupHash: ghash,
Resolved: resolved,
Timestamp: ts,
Receiver: r,
GroupKey: gkey,
Timestamp: ts,
FiringAlerts: firingAlerts,
ResolvedAlerts: resolvedAlerts,
},
ExpiresAt: expts,
}
Expand Down
105 changes: 85 additions & 20 deletions nflog/nflogpb/nflog.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions nflog/nflogpb/nflog.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,17 @@ message Entry {
// The receiver that was notified.
Receiver receiver = 2;
// Hash over the state of the group at notification time.
// Deprecated in favor of FiringAlerts field, but kept for compatibility.
bytes group_hash = 3;
// Whether the notification was about a resolved alert.
// Deprecated in favor of ResolvedAlerts field, but kept for compatibility.
bool resolved = 4;
// Timestamp of the succeeding notification.
google.protobuf.Timestamp timestamp = 5;
// FiringAlerts list of hashes of firing alerts at last notification.
repeated uint64 firing_alerts = 6;
// ResolvedAlerts list hashes of resolved alerts at last notification.
repeated uint64 resolved_alerts = 7;
}

// MeshEntry is a wrapper message to communicate a notify log
Expand Down
30 changes: 30 additions & 0 deletions nflog/nflogpb/set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package nflogpb

func (m *Entry) IsFiringSubset(subset map[uint64]struct{}) bool {
set := map[uint64]struct{}{}
for i := range m.FiringAlerts {
set[m.FiringAlerts[i]] = struct{}{}
}

return isSubset(set, subset)
}

func (m *Entry) IsResolvedSubset(subset map[uint64]struct{}) bool {
set := map[uint64]struct{}{}
for i := range m.ResolvedAlerts {
set[m.ResolvedAlerts[i]] = struct{}{}
}

return isSubset(set, subset)
}

func isSubset(set, subset map[uint64]struct{}) bool {
for k, _ := range subset {
_, exists := set[k]
if !exists {
return false
}
}

return true
}
Loading

0 comments on commit 1a5b131

Please sign in to comment.