From 12671bd261fe75fb77acb952a49c7647c19ffe2d Mon Sep 17 00:00:00 2001 From: beorn7 Date: Mon, 25 Feb 2019 17:11:43 +0100 Subject: [PATCH] Improve doc comments for Marker and friends This clarifies a bunch of things I have run into during code reading in preparation for some performance improvements around muting. It also moves doc comments from places where they don't show up in godoc to visible places. It also fixes golint warnings. Signed-off-by: beorn7 --- inhibit/inhibit.go | 13 ++++++---- types/types.go | 63 +++++++++++++++++++++++++++++++++++----------- 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/inhibit/inhibit.go b/inhibit/inhibit.go index bb2fa60e..e49eb42a 100644 --- a/inhibit/inhibit.go +++ b/inhibit/inhibit.go @@ -29,8 +29,9 @@ import ( "github.com/prometheus/alertmanager/types" ) -// An Inhibitor determines whether a given label set is muted -// based on the currently active alerts and a set of inhibition rules. +// An Inhibitor determines whether a given label set is muted based on the +// currently active alerts and a set of inhibition rules. It implements the +// Muter interface. type Inhibitor struct { alerts provider.Alerts rules []*InhibitRule @@ -121,7 +122,8 @@ func (ih *Inhibitor) Stop() { } } -// Mutes returns true iff the given label set is muted. +// Mutes returns true iff the given label set is muted. It implements the Muter +// interface. func (ih *Inhibitor) Mutes(lset model.LabelSet) bool { fp := lset.Fingerprint() @@ -197,8 +199,9 @@ func NewInhibitRule(cr *config.InhibitRule) *InhibitRule { } // hasEqual checks whether the source cache contains alerts matching the equal -// labels for the given label set. If excludeTwoSidedMatch is true, alerts that -// match both the source and the target side of the rule are disregarded. +// labels for the given label set. If so, the fingerprint of one of those alerts +// is returned. If excludeTwoSidedMatch is true, alerts that match both the +// source and the target side of the rule are disregarded. func (r *InhibitRule) hasEqual(lset model.LabelSet, excludeTwoSidedMatch bool) (model.Fingerprint, bool) { Outer: for a := range r.scache.List() { diff --git a/types/types.go b/types/types.go index 223f96ea..3c1e7a0d 100644 --- a/types/types.go +++ b/types/types.go @@ -22,15 +22,22 @@ import ( "github.com/prometheus/common/model" ) +// AlertState is used as part of AlertStatus. type AlertState string +// Possible values for AlertState. const ( AlertStateUnprocessed AlertState = "unprocessed" AlertStateActive AlertState = "active" AlertStateSuppressed AlertState = "suppressed" ) -// AlertStatus stores the state and values associated with an Alert. +// AlertStatus stores the state of an alert and, as applicable, the IDs of +// silences silencing the alert and of other alerts inhibiting the alert. Note +// that currently, SilencedBy is supposed to be the complete set of the relevant +// silences while InhibitedBy may contain only a subset of the inhibiting alerts +// – in practice exactly one ID. (This somewhat confusing semantics might change +// in the future.) type AlertStatus struct { State AlertState `json:"state"` SilencedBy []string `json:"silencedBy"` @@ -40,15 +47,36 @@ type AlertStatus struct { // Marker helps to mark alerts as silenced and/or inhibited. // All methods are goroutine-safe. type Marker interface { + // SetActive sets the provided alert to AlertStateActive and deletes all + // SilencedBy and InhibitedBy entries. SetActive(alert model.Fingerprint) - SetInhibited(alert model.Fingerprint, ids ...string) - SetSilenced(alert model.Fingerprint, ids ...string) + // SetSilenced replaces the previous SilencedBy by the provided IDs of + // silences. The set of provided IDs is supposed to represent the + // complete set of relevant silences. If no ID is provided and + // InhibitedBy is already empty, this call is equivalent + // SetActive. Otherwise, it sets AlertStateSuppressed. + SetSilenced(alert model.Fingerprint, silenceIDs ...string) + // SetInhibited replaces the previous InhibitedBy by the provided IDs of + // alerts. In contrast to SetSilenced, the set of provided IDs is not + // expected to represent the complete set of inhibiting alerts. (In + // practice, this method is only called with one or zero IDs. However, + // this expectation might change in the future.) If no ID is provided and + // SilencedBy is already empty, this call is equivalent to + // SetActive. Otherwise, it sets AlertStateSuppressed. + SetInhibited(alert model.Fingerprint, alertIDs ...string) + // Count alerts of the given state(s). With no state provided, count all + // alerts. Count(...AlertState) int + // Status of the given alert. Status(model.Fingerprint) AlertStatus + // Delete the given alert. Delete(model.Fingerprint) + // Various methods to inquire if the given alert is in a certain + // AlertState. Silenced also returns all the silencing silences, while + // Inhibited may return only a subset of inhibiting alerts. Unprocessed(model.Fingerprint) bool Active(model.Fingerprint) bool Silenced(model.Fingerprint) ([]string, bool) @@ -93,7 +121,7 @@ func (m *memMarker) registerMetrics(r prometheus.Registerer) { r.MustRegister(alertsSuppressed) } -// Count alerts of a given state. +// Count implements Marker. func (m *memMarker) Count(states ...AlertState) int { count := 0 @@ -114,7 +142,7 @@ func (m *memMarker) Count(states ...AlertState) int { return count } -// SetSilenced sets the AlertStatus to suppressed and stores the associated silence IDs. +// SetSilenced implements Marker. func (m *memMarker) SetSilenced(alert model.Fingerprint, ids ...string) { m.mtx.Lock() @@ -139,7 +167,7 @@ func (m *memMarker) SetSilenced(alert model.Fingerprint, ids ...string) { m.mtx.Unlock() } -// SetInhibited sets the AlertStatus to suppressed and stores the associated alert IDs. +// SetInhibited implements Marker. func (m *memMarker) SetInhibited(alert model.Fingerprint, ids ...string) { m.mtx.Lock() @@ -164,6 +192,7 @@ func (m *memMarker) SetInhibited(alert model.Fingerprint, ids ...string) { m.mtx.Unlock() } +// SetActive implements Marker. func (m *memMarker) SetActive(alert model.Fingerprint) { m.mtx.Lock() defer m.mtx.Unlock() @@ -182,7 +211,7 @@ func (m *memMarker) SetActive(alert model.Fingerprint) { s.InhibitedBy = []string{} } -// Status returns the AlertStatus for the given Fingerprint. +// Status implements Marker. func (m *memMarker) Status(alert model.Fingerprint) AlertStatus { m.mtx.RLock() defer m.mtx.RUnlock() @@ -198,7 +227,7 @@ func (m *memMarker) Status(alert model.Fingerprint) AlertStatus { return *s } -// Delete deletes the given Fingerprint from the internal cache. +// Delete implements Marker. func (m *memMarker) Delete(alert model.Fingerprint) { m.mtx.Lock() defer m.mtx.Unlock() @@ -206,20 +235,17 @@ func (m *memMarker) Delete(alert model.Fingerprint) { delete(m.m, alert) } -// Unprocessed returns whether the alert for the given Fingerprint is in the -// Unprocessed state. +// Unprocessed implements Marker. func (m *memMarker) Unprocessed(alert model.Fingerprint) bool { return m.Status(alert).State == AlertStateUnprocessed } -// Active returns whether the alert for the given Fingerprint is in the Active -// state. +// Active implements Marker. func (m *memMarker) Active(alert model.Fingerprint) bool { return m.Status(alert).State == AlertStateActive } -// Inhibited returns whether the alert for the given Fingerprint is in the -// Inhibited state and any associated alert IDs. +// Inhibited implements Marker. func (m *memMarker) Inhibited(alert model.Fingerprint) ([]string, bool) { s := m.Status(alert) return s.InhibitedBy, @@ -361,7 +387,9 @@ func (a *Alert) Merge(o *Alert) *Alert { return &res } -// A Muter determines whether a given label set is muted. +// A Muter determines whether a given label set is muted. Implementers that +// maintain an underlying Marker are expected to update it during a call of +// Mutes. type Muter interface { Mutes(model.LabelSet) bool } @@ -408,18 +436,23 @@ func (s *Silence) Expired() bool { return s.StartsAt.Equal(s.EndsAt) } +// SilenceStatus stores the state of a silence. type SilenceStatus struct { State SilenceState `json:"state"` } +// SilenceState is used as part of SilenceStatus. type SilenceState string +// Possible values for SilenceState. const ( SilenceStateExpired SilenceState = "expired" SilenceStateActive SilenceState = "active" SilenceStatePending SilenceState = "pending" ) +// CalcSilenceState returns the SilenceState that a silence with the given start +// and end time would have right now. func CalcSilenceState(start, end time.Time) SilenceState { current := time.Now() if current.Before(start) {