2015-07-01 15:56:53 +00:00
|
|
|
package manager
|
2015-06-30 12:29:30 +00:00
|
|
|
|
|
|
|
import (
|
2015-07-01 11:17:08 +00:00
|
|
|
"fmt"
|
|
|
|
"sync"
|
|
|
|
|
2015-06-30 12:29:30 +00:00
|
|
|
"github.com/prometheus/common/model"
|
2015-07-02 16:38:05 +00:00
|
|
|
// "github.com/prometheus/log"
|
2015-06-30 12:29:30 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// A State serves the Alertmanager's internal state about active silences.
|
|
|
|
type State interface {
|
2015-07-01 11:17:08 +00:00
|
|
|
Silence() SilenceState
|
2015-07-02 16:38:05 +00:00
|
|
|
Config() ConfigState
|
2015-07-01 11:17:08 +00:00
|
|
|
// Notify() NotifyState
|
2015-07-01 16:36:37 +00:00
|
|
|
Alert() AlertState
|
2015-06-30 12:29:30 +00:00
|
|
|
}
|
|
|
|
|
2015-07-01 16:36:37 +00:00
|
|
|
type AlertState interface {
|
|
|
|
Add(...*Alert) error
|
2015-07-04 10:52:53 +00:00
|
|
|
Get(model.Fingerprint) (*Alert, error)
|
2015-07-01 16:36:37 +00:00
|
|
|
GetAll() ([]*Alert, error)
|
2015-07-02 16:38:05 +00:00
|
|
|
|
|
|
|
Next() *Alert
|
2015-07-01 16:36:37 +00:00
|
|
|
}
|
2015-06-30 12:29:30 +00:00
|
|
|
|
2015-07-02 16:38:05 +00:00
|
|
|
type ConfigState interface {
|
|
|
|
Set(*Config) error
|
|
|
|
Get() (*Config, error)
|
|
|
|
}
|
2015-06-30 12:29:30 +00:00
|
|
|
|
|
|
|
type NotifyState interface{}
|
|
|
|
|
|
|
|
type SilenceState interface {
|
|
|
|
// Silences returns a list of all silences.
|
2015-07-01 11:17:08 +00:00
|
|
|
GetAll() ([]*Silence, error)
|
2015-06-30 12:29:30 +00:00
|
|
|
|
|
|
|
// SetSilence sets the given silence.
|
2015-07-01 11:17:08 +00:00
|
|
|
Set(*Silence) error
|
|
|
|
Del(sid string) error
|
|
|
|
Get(sid string) (*Silence, error)
|
2015-06-30 12:29:30 +00:00
|
|
|
}
|
|
|
|
|
2015-07-02 16:38:05 +00:00
|
|
|
// simpleState implements the State interface based on in-memory storage.
|
|
|
|
type simpleState struct {
|
2015-07-01 11:17:08 +00:00
|
|
|
silences *memSilences
|
2015-07-01 16:36:37 +00:00
|
|
|
alerts *memAlerts
|
2015-07-02 16:38:05 +00:00
|
|
|
config *memConfig
|
2015-06-30 12:29:30 +00:00
|
|
|
}
|
|
|
|
|
2015-07-02 16:38:05 +00:00
|
|
|
func NewSimpleState() State {
|
|
|
|
return &simpleState{
|
2015-07-01 11:17:08 +00:00
|
|
|
silences: &memSilences{
|
2015-07-04 10:52:53 +00:00
|
|
|
sils: map[string]*Silence{},
|
2015-07-01 11:17:08 +00:00
|
|
|
nextID: 1,
|
|
|
|
},
|
2015-07-02 16:38:05 +00:00
|
|
|
alerts: &memAlerts{
|
2015-07-04 10:52:53 +00:00
|
|
|
alerts: map[model.Fingerprint]*Alert{},
|
|
|
|
ch: make(chan *Alert, 100),
|
2015-07-02 16:38:05 +00:00
|
|
|
},
|
|
|
|
config: &memConfig{},
|
2015-06-30 12:29:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-02 16:38:05 +00:00
|
|
|
func (s *simpleState) Alert() AlertState {
|
2015-07-01 16:36:37 +00:00
|
|
|
return s.alerts
|
|
|
|
}
|
|
|
|
|
2015-07-02 16:38:05 +00:00
|
|
|
func (s *simpleState) Silence() SilenceState {
|
2015-07-01 11:17:08 +00:00
|
|
|
return s.silences
|
|
|
|
}
|
|
|
|
|
2015-07-02 16:38:05 +00:00
|
|
|
func (s *simpleState) Config() ConfigState {
|
|
|
|
return s.config
|
|
|
|
}
|
|
|
|
|
|
|
|
type memConfig struct {
|
|
|
|
config *Config
|
|
|
|
mtx sync.RWMutex
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *memConfig) Set(conf *Config) error {
|
|
|
|
c.mtx.Lock()
|
|
|
|
defer c.mtx.Unlock()
|
|
|
|
|
|
|
|
c.config = conf
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *memConfig) Get() (*Config, error) {
|
|
|
|
c.mtx.RLock()
|
|
|
|
defer c.mtx.RUnlock()
|
|
|
|
|
|
|
|
return c.config, nil
|
|
|
|
}
|
|
|
|
|
2015-07-01 16:36:37 +00:00
|
|
|
type memAlerts struct {
|
2015-07-04 10:52:53 +00:00
|
|
|
alerts map[model.Fingerprint]*Alert
|
2015-07-02 16:38:05 +00:00
|
|
|
ch chan *Alert
|
2015-07-01 16:36:37 +00:00
|
|
|
mtx sync.RWMutex
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *memAlerts) GetAll() ([]*Alert, error) {
|
|
|
|
s.mtx.RLock()
|
|
|
|
defer s.mtx.RUnlock()
|
|
|
|
|
|
|
|
alerts := make([]*Alert, len(s.alerts))
|
2015-07-04 10:52:53 +00:00
|
|
|
for i, a := range s.alerts {
|
|
|
|
alerts[i] = a
|
|
|
|
}
|
2015-07-01 16:36:37 +00:00
|
|
|
|
|
|
|
return alerts, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *memAlerts) Add(alerts ...*Alert) error {
|
|
|
|
s.mtx.Lock()
|
|
|
|
defer s.mtx.Unlock()
|
|
|
|
|
2015-07-02 16:38:05 +00:00
|
|
|
for _, alert := range alerts {
|
2015-07-04 10:52:53 +00:00
|
|
|
fp := alert.Fingerprint()
|
|
|
|
|
|
|
|
// Last write wins.
|
|
|
|
if prev, ok := s.alerts[fp]; !ok || alert.Timestamp.After(prev.Timestamp) {
|
|
|
|
s.alerts[fp] = alert
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO(fabxc): remove this as it blocks if the channel is full.
|
2015-07-02 16:38:05 +00:00
|
|
|
s.ch <- alert
|
|
|
|
}
|
2015-07-04 10:52:53 +00:00
|
|
|
|
2015-07-01 16:36:37 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-07-04 10:52:53 +00:00
|
|
|
func (s *memAlerts) Get(fp model.Fingerprint) (*Alert, error) {
|
|
|
|
s.mtx.Lock()
|
|
|
|
defer s.mtx.Unlock()
|
|
|
|
|
|
|
|
if a, ok := s.alerts[fp]; ok {
|
|
|
|
return a, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("alert with fingerprint %s does not exist", fp)
|
|
|
|
}
|
|
|
|
|
2015-07-02 16:38:05 +00:00
|
|
|
func (s *memAlerts) Next() *Alert {
|
|
|
|
return <-s.ch
|
|
|
|
}
|
|
|
|
|
2015-07-01 11:17:08 +00:00
|
|
|
type memSilences struct {
|
2015-07-04 10:52:53 +00:00
|
|
|
sils map[string]*Silence
|
2015-07-01 11:17:08 +00:00
|
|
|
|
2015-07-04 10:52:53 +00:00
|
|
|
mtx sync.RWMutex
|
2015-07-01 11:17:08 +00:00
|
|
|
nextID uint64
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *memSilences) genID() string {
|
|
|
|
sid := fmt.Sprintf("%x", s.nextID)
|
|
|
|
s.nextID++
|
|
|
|
return sid
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *memSilences) Get(sid string) (*Silence, error) {
|
2015-07-04 10:52:53 +00:00
|
|
|
s.mtx.RLock()
|
|
|
|
defer s.mtx.RUnlock()
|
|
|
|
|
|
|
|
if sil, ok := s.sils[sid]; ok {
|
|
|
|
return sil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("silence with ID %s does not exist", sid)
|
2015-07-01 11:17:08 +00:00
|
|
|
}
|
2015-07-04 10:52:53 +00:00
|
|
|
|
2015-07-01 11:17:08 +00:00
|
|
|
func (s *memSilences) Del(sid string) error {
|
2015-07-04 10:52:53 +00:00
|
|
|
if _, ok := s.sils[sid]; !ok {
|
2015-07-01 11:17:08 +00:00
|
|
|
return fmt.Errorf("silence with ID %s does not exist", sid)
|
|
|
|
}
|
2015-07-04 10:52:53 +00:00
|
|
|
|
|
|
|
delete(s.sils, sid)
|
2015-07-01 11:17:08 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *memSilences) GetAll() ([]*Silence, error) {
|
|
|
|
s.mtx.Lock()
|
|
|
|
defer s.mtx.Unlock()
|
|
|
|
|
2015-07-04 10:52:53 +00:00
|
|
|
sils := make([]*Silence, 0, len(s.sils))
|
|
|
|
for _, sil := range s.sils {
|
2015-06-30 12:29:30 +00:00
|
|
|
sils = append(sils, sil)
|
|
|
|
}
|
|
|
|
return sils, nil
|
|
|
|
}
|
|
|
|
|
2015-07-01 11:17:08 +00:00
|
|
|
func (s *memSilences) Set(sil *Silence) error {
|
|
|
|
s.mtx.RLock()
|
|
|
|
defer s.mtx.RUnlock()
|
|
|
|
|
|
|
|
if sil.ID == "" {
|
|
|
|
sil.ID = s.genID()
|
|
|
|
}
|
|
|
|
|
2015-07-04 10:52:53 +00:00
|
|
|
s.sils[sil.ID] = sil
|
2015-06-30 12:29:30 +00:00
|
|
|
return nil
|
|
|
|
}
|