Repository: prometheus/alertmanager
File: types/types.go (Go)

Code before:
	// result is based on.
	Unprocessed(model.Fingerprint) bool
	Active(model.Fingerprint) bool
	Silenced(model.Fingerprint) (activeIDs, pendingIDs []string, version int, silenced bool)
	Inhibited(model.Fingerprint) ([]string, bool)
}

// NewMarker returns an instance of a Marker implementation.
func NewMarker(r prometheus.Registerer) Marker {
	m := &memMarker{
		m: map[model.Fingerprint]*AlertStatus{},
	}

	m.registerMetrics(r)

	return m
}

type memMarker struct {
	m map[model.Fingerprint]*AlertStatus

	mtx sync.RWMutex
}

func (m *memMarker) registerMetrics(r prometheus.Registerer) {
	newMarkedAlertMetricByState := func(st AlertState) prometheus.GaugeFunc {
		return prometheus.NewGaugeFunc(
			prometheus.GaugeOpts{
				Name:        "alertmanager_marked_alerts",
				Help:        "How many alerts by state are currently marked in the Alertmanager regardless of their expiry.",
				ConstLabels: prometheus.Labels{"state": string(st)},
			},
			func() float64 {
				return float64(m.Count(st))
			},
		)
	}

	alertsActive := newMarkedAlertMetricByState(AlertStateActive)
	alertsSuppressed := newMarkedAlertMetricByState(AlertStateSuppressed)
	alertStateUnprocessed := newMarkedAlertMetricByState(AlertStateUnprocessed)

	r.MustRegister(alertsActive)
	r.MustRegister(alertsSuppressed)
	r.MustRegister(alertStateUnprocessed)
}

// Count implements Marker.
func (m *memMarker) Count(states ...AlertState) int {
	m.mtx.RLock()
	defer m.mtx.RUnlock()

Review comment (bug):
I added `routeID` to avoid the issue of non unique group keys from causing groups to be incorrectly marked as muted. See https://github.com/prometheus/alertmanager/issues/3817 for more information.

Code after:
	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 active and pending
	// silences, while Inhibited may return only a subset of inhibiting
	// alerts. Silenced also returns the version of the silences state the
	// result is based on.
	Unprocessed(model.Fingerprint) bool
	Active(model.Fingerprint) bool
	Silenced(model.Fingerprint) (activeIDs, pendingIDs []string, version int, silenced bool)
	Inhibited(model.Fingerprint) ([]string, bool)
}

// GroupMarker helps to mark groups as active or muted.
// All methods are goroutine-safe.
//
// TODO(grobinson): routeID is used in Muted and SetMuted because groupKey
// is not unique (see #3817). Once groupKey uniqueness is fixed routeID can
// be removed from the GroupMarker interface.
type GroupMarker interface {
	// Muted returns true if the group is muted, otherwise false. If the group
	// is muted then it also returns the names of the time intervals that muted
	// it.
	Muted(routeID, groupKey string) ([]string, bool)

	// SetMuted marks the group as muted, and sets the names of the time
	// intervals that mute it. If the list of names is nil or the empty slice
	// then the muted marker is removed.
	SetMuted(routeID, groupKey string, timeIntervalNames []string)
}

// NewMarker returns an instance of a AlertMarker implementation.
func NewMarker(r prometheus.Registerer) *MemMarker {
	m := &MemMarker{
		alerts: map[model.Fingerprint]*AlertStatus{},
		groups: map[string]*groupStatus{},
	}
	m.registerMetrics(r)
	return m
}

type MemMarker struct {
	alerts map[model.Fingerprint]*AlertStatus
	groups map[string]*groupStatus

	mtx sync.RWMutex
}

// Muted implements GroupMarker.