diff --git a/cmd/alertmanager/main.go b/cmd/alertmanager/main.go index 814a3489..9d1f31c7 100644 --- a/cmd/alertmanager/main.go +++ b/cmd/alertmanager/main.go @@ -67,9 +67,7 @@ var ( Name: "alertmanager_config_last_reload_success_timestamp_seconds", Help: "Timestamp of the last successful configuration reload.", }) - alertsActive prometheus.GaugeFunc - alertsSuppressed prometheus.GaugeFunc - requestDuration = prometheus.NewHistogramVec( + requestDuration = prometheus.NewHistogramVec( prometheus.HistogramOpts{ Name: "alertmanager_http_request_duration_seconds", Help: "Histogram of latencies for HTTP requests.", @@ -107,27 +105,6 @@ func instrumentHandler(handlerName string, handler http.HandlerFunc) http.Handle ) } -func newAlertMetricByState(marker types.Marker, st types.AlertState) prometheus.GaugeFunc { - return prometheus.NewGaugeFunc( - prometheus.GaugeOpts{ - Name: "alertmanager_alerts", - Help: "How many alerts by state.", - ConstLabels: prometheus.Labels{"state": string(st)}, - }, - func() float64 { - return float64(marker.Count(st)) - }, - ) -} - -func newMarkerMetrics(marker types.Marker) { - alertsActive = newAlertMetricByState(marker, types.AlertStateActive) - alertsSuppressed = newAlertMetricByState(marker, types.AlertStateSuppressed) - - prometheus.MustRegister(alertsActive) - prometheus.MustRegister(alertsSuppressed) -} - const defaultClusterAddr = "0.0.0.0:9094" func main() { @@ -225,8 +202,7 @@ func run() int { notificationLog.SetBroadcast(c.Broadcast) } - marker := types.NewMarker() - newMarkerMetrics(marker) + marker := types.NewMarker(prometheus.DefaultRegisterer) silenceOpts := silence.Options{ SnapshotFile: filepath.Join(*dataDir, "silences"), diff --git a/inhibit/inhibit_test.go b/inhibit/inhibit_test.go index d5863c4f..7cb06a58 100644 --- a/inhibit/inhibit_test.go +++ b/inhibit/inhibit_test.go @@ -18,6 +18,7 @@ import ( "time" "github.com/go-kit/kit/log" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" "github.com/prometheus/alertmanager/config" @@ -145,7 +146,7 @@ func TestInhibitRuleMatches(t *testing.T) { TargetMatch: map[string]string{"t": "1"}, Equal: model.LabelNames{"e"}, } - m := types.NewMarker() + m := types.NewMarker(prometheus.NewRegistry()) ih := NewInhibitor(nil, []*config.InhibitRule{&cr}, m, nopLogger) ir := ih.rules[0] now := time.Now() @@ -320,7 +321,7 @@ func TestInhibit(t *testing.T) { }, } { ap := newFakeAlerts(tc.alerts) - mk := types.NewMarker() + mk := types.NewMarker(prometheus.NewRegistry()) inhibitor := NewInhibitor(ap, []*config.InhibitRule{inhibitRule()}, mk, nopLogger) go func() { diff --git a/notify/notify_test.go b/notify/notify_test.go index 2fe3bd9f..d15e7cdf 100644 --- a/notify/notify_test.go +++ b/notify/notify_test.go @@ -22,6 +22,7 @@ import ( "time" "github.com/go-kit/kit/log" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" "github.com/stretchr/testify/require" @@ -586,7 +587,7 @@ func TestSilenceStage(t *testing.T) { t.Fatal(err) } - marker := types.NewMarker() + marker := types.NewMarker(prometheus.NewRegistry()) silencer := NewSilenceStage(silences, marker) in := []model.LabelSet{ diff --git a/provider/mem/mem_test.go b/provider/mem/mem_test.go index 2414c49f..bece7e4c 100644 --- a/provider/mem/mem_test.go +++ b/provider/mem/mem_test.go @@ -27,6 +27,7 @@ import ( "github.com/kylelemons/godebug/pretty" "github.com/prometheus/alertmanager/store" "github.com/prometheus/alertmanager/types" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" "github.com/stretchr/testify/require" ) @@ -83,7 +84,7 @@ func init() { // If the channel of a listener is at its limit, `alerts.Lock` is blocked, whereby // a listener can not unsubscribe as the lock is hold by `alerts.Lock`. func TestAlertsSubscribePutStarvation(t *testing.T) { - marker := types.NewMarker() + marker := types.NewMarker(prometheus.NewRegistry()) alerts, err := NewAlerts(context.Background(), marker, 30*time.Minute, log.NewNopLogger()) if err != nil { t.Fatal(err) @@ -134,7 +135,7 @@ func TestAlertsSubscribePutStarvation(t *testing.T) { } func TestAlertsPut(t *testing.T) { - marker := types.NewMarker() + marker := types.NewMarker(prometheus.NewRegistry()) alerts, err := NewAlerts(context.Background(), marker, 30*time.Minute, log.NewNopLogger()) if err != nil { t.Fatal(err) @@ -159,7 +160,7 @@ func TestAlertsPut(t *testing.T) { } func TestAlertsSubscribe(t *testing.T) { - marker := types.NewMarker() + marker := types.NewMarker(prometheus.NewRegistry()) alerts, err := NewAlerts(context.Background(), marker, 30*time.Minute, log.NewNopLogger()) if err != nil { t.Fatal(err) @@ -248,7 +249,7 @@ func TestAlertsSubscribe(t *testing.T) { } func TestAlertsGetPending(t *testing.T) { - marker := types.NewMarker() + marker := types.NewMarker(prometheus.NewRegistry()) alerts, err := NewAlerts(context.Background(), marker, 30*time.Minute, log.NewNopLogger()) if err != nil { t.Fatal(err) @@ -291,7 +292,7 @@ func TestAlertsGetPending(t *testing.T) { } func TestAlertsGC(t *testing.T) { - marker := types.NewMarker() + marker := types.NewMarker(prometheus.NewRegistry()) alerts, err := NewAlerts(context.Background(), marker, 200*time.Millisecond, log.NewNopLogger()) if err != nil { t.Fatal(err) diff --git a/types/types.go b/types/types.go index 67713584..223f96ea 100644 --- a/types/types.go +++ b/types/types.go @@ -18,6 +18,7 @@ import ( "sync" "time" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" ) @@ -55,10 +56,14 @@ type Marker interface { } // NewMarker returns an instance of a Marker implementation. -func NewMarker() Marker { - return &memMarker{ +func NewMarker(r prometheus.Registerer) Marker { + m := &memMarker{ m: map[model.Fingerprint]*AlertStatus{}, } + + m.registerMetrics(r) + + return m } type memMarker struct { @@ -67,6 +72,27 @@ type memMarker struct { mtx sync.RWMutex } +func (m *memMarker) registerMetrics(r prometheus.Registerer) { + newAlertMetricByState := func(st AlertState) prometheus.GaugeFunc { + return prometheus.NewGaugeFunc( + prometheus.GaugeOpts{ + Name: "alertmanager_alerts", + Help: "How many alerts by state.", + ConstLabels: prometheus.Labels{"state": string(st)}, + }, + func() float64 { + return float64(m.Count(st)) + }, + ) + } + + alertsActive := newAlertMetricByState(AlertStateActive) + alertsSuppressed := newAlertMetricByState(AlertStateSuppressed) + + r.MustRegister(alertsActive) + r.MustRegister(alertsSuppressed) +} + // Count alerts of a given state. func (m *memMarker) Count(states ...AlertState) int { count := 0 diff --git a/types/types_test.go b/types/types_test.go index bb1970a7..d9ad8bdc 100644 --- a/types/types_test.go +++ b/types/types_test.go @@ -20,6 +20,7 @@ import ( "testing" "time" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" "github.com/stretchr/testify/require" ) @@ -366,3 +367,28 @@ func TestAlertSliceSort(t *testing.T) { } } } + +type fakeRegisterer struct { + registeredCollectors []prometheus.Collector +} + +func (r *fakeRegisterer) Register(prometheus.Collector) error { + return nil +} + +func (r *fakeRegisterer) MustRegister(c ...prometheus.Collector) { + r.registeredCollectors = append(r.registeredCollectors, c...) +} + +func (r *fakeRegisterer) Unregister(prometheus.Collector) bool { + return false +} + +func TestNewMarkerRegistersMetrics(t *testing.T) { + fr := fakeRegisterer{} + NewMarker(&fr) + + if len(fr.registeredCollectors) == 0 { + t.Error("expected NewMarker to register metrics on the given registerer") + } +}