alertmanager/provider/mem.go

312 lines
6.3 KiB
Go
Raw Normal View History

2015-09-25 12:38:07 +00:00
// Copyright 2015 Prometheus Team
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package provider
import (
"sync"
"github.com/prometheus/common/model"
"github.com/prometheus/alertmanager/types"
)
// MemData contains the data backing MemAlerts and MemNotifies.
type MemData struct {
mtx sync.RWMutex
alerts map[model.Fingerprint]*types.Alert
notifies map[string]map[model.Fingerprint]*types.NotifyInfo
}
// NewMemData contains an empty but initialized MemData instance.
func NewMemData() *MemData {
return &MemData{
alerts: map[model.Fingerprint]*types.Alert{},
notifies: map[string]map[model.Fingerprint]*types.NotifyInfo{},
}
}
2015-09-25 12:38:07 +00:00
// MemAlerts implements an Alerts provider based on in-memory data.
type MemAlerts struct {
data *MemData
2015-09-25 12:38:07 +00:00
mtx sync.RWMutex
listeners map[int]chan *types.Alert
next int
2015-09-25 12:38:07 +00:00
}
// NewMemAlerts returns a new MemAlerts based on the provided data.
func NewMemAlerts(data *MemData) *MemAlerts {
2015-09-25 12:38:07 +00:00
return &MemAlerts{
data: data,
listeners: map[int]chan *types.Alert{},
2015-09-25 12:38:07 +00:00
}
}
// Subscribe implements the Alerts interface.
func (a *MemAlerts) Subscribe() AlertIterator {
2015-09-25 12:38:07 +00:00
a.mtx.Lock()
defer a.mtx.Unlock()
a.data.mtx.Lock()
defer a.data.mtx.Unlock()
2015-09-25 12:38:07 +00:00
2015-09-29 08:45:58 +00:00
var (
alerts = a.getPending()
ch = make(chan *types.Alert, 200)
done = make(chan struct{})
)
i := a.next
a.next++
a.listeners[i] = ch
2015-09-29 08:45:58 +00:00
go func() {
defer func() {
a.mtx.Lock()
delete(a.listeners, i)
2015-09-29 08:45:58 +00:00
close(ch)
a.mtx.Unlock()
}()
for _, a := range alerts {
select {
case ch <- a:
case <-done:
return
}
}
<-done
2015-09-29 08:45:58 +00:00
}()
return alertIterator{
2015-09-29 08:45:58 +00:00
ch: ch,
done: done,
2015-09-26 09:12:47 +00:00
}
2015-09-29 08:45:58 +00:00
}
2015-09-26 09:12:47 +00:00
// GetPending implements the Alerts interface.
2015-09-29 08:45:58 +00:00
func (a *MemAlerts) GetPending() AlertIterator {
a.mtx.Lock()
defer a.mtx.Unlock()
a.data.mtx.Lock()
defer a.data.mtx.Unlock()
var (
alerts = a.getPending()
ch = make(chan *types.Alert, 200)
done = make(chan struct{})
)
2015-09-25 12:38:07 +00:00
2015-09-26 09:12:47 +00:00
go func() {
2015-09-29 08:45:58 +00:00
defer close(ch)
2015-09-26 09:12:47 +00:00
for _, a := range alerts {
2015-09-29 08:45:58 +00:00
select {
case ch <- a:
case <-done:
return
}
2015-09-26 09:12:47 +00:00
}
}()
2015-09-25 12:38:07 +00:00
return alertIterator{
2015-09-29 08:45:58 +00:00
ch: ch,
done: done,
2015-09-26 09:12:47 +00:00
}
}
2015-09-29 08:45:58 +00:00
func (a *MemAlerts) getPending() []*types.Alert {
// Get fingerprints for all alerts that have pending notifications.
over := map[model.Fingerprint]struct{}{}
2015-09-29 08:45:58 +00:00
for _, ns := range a.data.notifies {
for fp, notify := range ns {
if notify.Resolved {
over[fp] = struct{}{}
2015-09-29 08:45:58 +00:00
}
}
}
2015-09-29 08:45:58 +00:00
// All alerts that have pending notifications are part of the
// new scubscription.
2015-09-26 09:12:47 +00:00
var alerts []*types.Alert
for _, a := range a.data.alerts {
if _, ok := over[a.Fingerprint()]; !ok {
2015-09-29 08:45:58 +00:00
alerts = append(alerts, a)
}
2015-09-26 09:12:47 +00:00
}
2015-09-29 08:45:58 +00:00
return alerts
2015-09-25 12:38:07 +00:00
}
// Put implements the Alerts interface.
2015-09-26 09:12:47 +00:00
func (a *MemAlerts) Put(alerts ...*types.Alert) error {
a.mtx.Lock()
defer a.mtx.Unlock()
a.data.mtx.Lock()
defer a.data.mtx.Unlock()
2015-09-25 12:38:07 +00:00
2015-09-26 09:12:47 +00:00
for _, alert := range alerts {
2015-10-02 14:52:04 +00:00
fp := alert.Fingerprint()
2015-09-25 12:38:07 +00:00
2015-10-02 14:52:04 +00:00
// Merge the alert with the existant one.
if old, ok := a.data.alerts[fp]; ok {
alert = old.Merge(alert)
2015-09-26 09:12:47 +00:00
}
2015-09-25 12:38:07 +00:00
2015-10-02 14:52:04 +00:00
a.data.alerts[fp] = alert
2015-09-29 08:45:58 +00:00
2015-10-02 14:52:04 +00:00
for _, ch := range a.listeners {
ch <- alert
2015-09-29 08:45:58 +00:00
}
2015-10-02 14:52:04 +00:00
}
2015-09-29 08:45:58 +00:00
2015-09-25 12:38:07 +00:00
return nil
}
// Get implements the Alerts interface.
2015-09-25 12:38:07 +00:00
func (a *MemAlerts) Get(fp model.Fingerprint) (*types.Alert, error) {
a.data.mtx.RLock()
defer a.data.mtx.RUnlock()
2015-09-25 12:38:07 +00:00
if a, ok := a.data.alerts[fp]; ok {
2015-09-25 12:38:07 +00:00
return a, nil
}
return nil, ErrNotFound
}
2015-09-27 11:18:13 +00:00
// MemNotifies implements a Notifies provider based on in-memory data.
2015-09-27 18:16:42 +00:00
type MemNotifies struct {
data *MemData
}
// NewMemNotifies returns a new MemNotifies based on the provided data.
2015-09-27 18:16:42 +00:00
func NewMemNotifies(data *MemData) *MemNotifies {
return &MemNotifies{data: data}
}
// Set implements the Notifies interface.
func (n *MemNotifies) Set(ns ...*types.NotifyInfo) error {
2015-09-27 18:16:42 +00:00
n.data.mtx.Lock()
defer n.data.mtx.Unlock()
2015-09-27 18:16:42 +00:00
for _, notify := range ns {
2015-09-28 19:43:28 +00:00
if notify == nil {
continue
}
2015-11-10 12:47:04 +00:00
am, ok := n.data.notifies[notify.Receiver]
2015-09-27 18:16:42 +00:00
if !ok {
am = map[model.Fingerprint]*types.NotifyInfo{}
2015-11-10 12:47:04 +00:00
n.data.notifies[notify.Receiver] = am
2015-09-27 18:16:42 +00:00
}
am[notify.Alert] = notify
}
return nil
}
// Get implements the Notifies interface.
func (n *MemNotifies) Get(dest string, fps ...model.Fingerprint) ([]*types.NotifyInfo, error) {
2015-09-27 18:16:42 +00:00
n.data.mtx.RLock()
defer n.data.mtx.RUnlock()
res := make([]*types.NotifyInfo, len(fps))
2015-09-27 19:51:54 +00:00
2015-09-27 18:16:42 +00:00
ns, ok := n.data.notifies[dest]
if !ok {
2015-09-27 19:51:54 +00:00
return res, nil
2015-09-27 18:16:42 +00:00
}
2015-09-27 19:51:54 +00:00
for i, fp := range fps {
res[i] = ns[fp]
2015-09-27 18:16:42 +00:00
}
return res, nil
}
// MemSilences implements a Silences provider based on in-memory data.
2015-09-27 11:18:13 +00:00
type MemSilences struct {
mtx sync.RWMutex
silences map[uint64]*model.Silence
2015-09-27 11:18:13 +00:00
}
// NewMemSilences returns a new MemSilences.
2015-09-27 11:18:13 +00:00
func NewMemSilences() *MemSilences {
return &MemSilences{
silences: map[uint64]*model.Silence{},
2015-09-27 11:18:13 +00:00
}
}
// Mutes implements the Muter interface.
2015-09-27 11:18:13 +00:00
func (s *MemSilences) Mutes(lset model.LabelSet) bool {
s.mtx.RLock()
defer s.mtx.RUnlock()
for _, sil := range s.silences {
if types.NewSilence(sil).Mutes(lset) {
2015-09-27 11:18:13 +00:00
return true
}
}
return false
}
// All implements the Silences interface.
2015-09-27 11:18:13 +00:00
func (s *MemSilences) All() ([]*types.Silence, error) {
2015-09-27 12:07:04 +00:00
s.mtx.RLock()
defer s.mtx.RUnlock()
var sils []*types.Silence
for _, sil := range s.silences {
sils = append(sils, types.NewSilence(sil))
2015-09-27 12:07:04 +00:00
}
return sils, nil
2015-09-27 11:18:13 +00:00
}
// Set impelements the Silences interface.
func (s *MemSilences) Set(sil *types.Silence) (uint64, error) {
2015-09-27 11:18:13 +00:00
s.mtx.Lock()
defer s.mtx.Unlock()
2015-09-27 12:07:04 +00:00
if sil.ID == 0 {
2015-10-01 15:50:15 +00:00
sil.ID = uint64(len(s.silences) + 1)
} else {
if _, ok := s.silences[sil.ID]; !ok {
return 0, ErrNotFound
}
2015-09-27 12:07:04 +00:00
}
s.silences[sil.ID] = &sil.Silence
return sil.ID, nil
2015-09-27 11:18:13 +00:00
}
// Del implements the Silences interface.
2015-10-01 15:50:15 +00:00
func (s *MemSilences) Del(id uint64) error {
2015-09-27 11:18:13 +00:00
s.mtx.Lock()
defer s.mtx.Unlock()
delete(s.silences, id)
return nil
}
// Get implements the Silences interface.
2015-10-01 15:50:15 +00:00
func (s *MemSilences) Get(id uint64) (*types.Silence, error) {
2015-09-27 11:18:13 +00:00
s.mtx.RLock()
defer s.mtx.RUnlock()
sil, ok := s.silences[id]
if !ok {
return nil, ErrNotFound
}
return types.NewSilence(sil), nil
2015-09-27 11:18:13 +00:00
}