alertmanager/manager/state.go

204 lines
3.6 KiB
Go
Raw Normal View History

2015-07-01 15:56:53 +00:00
package manager
import (
2015-07-01 11:17:08 +00:00
"fmt"
"sync"
"github.com/prometheus/common/model"
// "github.com/prometheus/log"
)
// A State serves the Alertmanager's internal state about active silences.
type State interface {
2015-07-01 11:17:08 +00:00
Silence() SilenceState
Config() ConfigState
2015-07-01 11:17:08 +00:00
// Notify() NotifyState
Alert() AlertState
}
type AlertState interface {
Add(...*Alert) error
Get(model.Fingerprint) (*Alert, error)
GetAll() ([]*Alert, error)
Next() *Alert
}
type ConfigState interface {
Set(*Config) error
Get() (*Config, error)
}
type NotifyState interface{}
type SilenceState interface {
// Silences returns a list of all silences.
2015-07-01 11:17:08 +00:00
GetAll() ([]*Silence, error)
// 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)
}
// simpleState implements the State interface based on in-memory storage.
type simpleState struct {
2015-07-01 11:17:08 +00:00
silences *memSilences
alerts *memAlerts
config *memConfig
}
func NewSimpleState() State {
return &simpleState{
2015-07-01 11:17:08 +00:00
silences: &memSilences{
sils: map[string]*Silence{},
2015-07-01 11:17:08 +00:00
nextID: 1,
},
alerts: &memAlerts{
alerts: map[model.Fingerprint]*Alert{},
ch: make(chan *Alert, 100),
},
config: &memConfig{},
}
}
func (s *simpleState) Alert() AlertState {
return s.alerts
}
func (s *simpleState) Silence() SilenceState {
2015-07-01 11:17:08 +00:00
return s.silences
}
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
}
type memAlerts struct {
alerts map[model.Fingerprint]*Alert
ch chan *Alert
mtx sync.RWMutex
}
func (s *memAlerts) GetAll() ([]*Alert, error) {
s.mtx.RLock()
defer s.mtx.RUnlock()
alerts := make([]*Alert, len(s.alerts))
for i, a := range s.alerts {
alerts[i] = a
}
return alerts, nil
}
func (s *memAlerts) Add(alerts ...*Alert) error {
s.mtx.Lock()
defer s.mtx.Unlock()
for _, alert := range alerts {
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.
s.ch <- alert
}
return nil
}
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)
}
func (s *memAlerts) Next() *Alert {
return <-s.ch
}
2015-07-01 11:17:08 +00:00
type memSilences struct {
sils map[string]*Silence
2015-07-01 11:17:08 +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) {
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-01 11:17:08 +00:00
func (s *memSilences) Del(sid string) error {
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)
}
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()
sils := make([]*Silence, 0, len(s.sils))
for _, sil := range s.sils {
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()
}
s.sils[sil.ID] = sil
return nil
}