From 331ad3140148e053da87441c1bb006aa9a81f68c Mon Sep 17 00:00:00 2001 From: Fabian Reinartz Date: Tue, 29 Sep 2015 12:22:13 +0200 Subject: [PATCH] Implement configuration reloading --- dispatch.go | 4 +++- inhibit.go | 4 +++- main.go | 42 +++++++++++++++++++++++++++++++++--------- notify.go | 4 +++- provider/provider.go | 9 +-------- types/types.go | 8 ++++++++ 6 files changed, 51 insertions(+), 20 deletions(-) diff --git a/dispatch.go b/dispatch.go index ea9aec03..27fb358f 100644 --- a/dispatch.go +++ b/dispatch.go @@ -43,7 +43,7 @@ func NewDispatcher(ap provider.Alerts, n Notifier) *Dispatcher { } // ApplyConfig updates the dispatcher to match the new configuration. -func (d *Dispatcher) ApplyConfig(conf *config.Config) { +func (d *Dispatcher) ApplyConfig(conf *config.Config) bool { d.mtx.Lock() defer d.mtx.Unlock() @@ -54,6 +54,8 @@ func (d *Dispatcher) ApplyConfig(conf *config.Config) { } d.routes = NewRoutes(conf.Routes) + + return true } // Run starts dispatching alerts incoming via the updates channel. diff --git a/inhibit.go b/inhibit.go index 4d30449b..bbf8add9 100644 --- a/inhibit.go +++ b/inhibit.go @@ -42,7 +42,7 @@ func (ih *Inhibitor) Mutes(lset model.LabelSet) bool { return false } -func (ih *Inhibitor) ApplyConfig(conf *config.Config) { +func (ih *Inhibitor) ApplyConfig(conf *config.Config) bool { ih.mtx.Lock() defer ih.mtx.Unlock() @@ -50,6 +50,8 @@ func (ih *Inhibitor) ApplyConfig(conf *config.Config) { for _, cr := range conf.InhibitRules { ih.rules = append(ih.rules, NewInhibitRule(cr)) } + + return true } // An InhibitRule specifies that a class of (source) alerts should inhibit diff --git a/main.go b/main.go index c198349f..7ef943f6 100644 --- a/main.go +++ b/main.go @@ -25,6 +25,7 @@ import ( "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/provider" + "github.com/prometheus/alertmanager/types" ) var ( @@ -34,11 +35,6 @@ var ( func main() { flag.Parse() - conf, err := config.LoadFile(*configFile) - if err != nil { - log.Fatal(err) - } - data := provider.NewMemData() alerts := provider.NewMemAlerts(data) @@ -46,7 +42,6 @@ func main() { silences := provider.NewMemSilences() inhibitor := &Inhibitor{alerts: alerts} - inhibitor.ApplyConfig(conf) routedNotifier := newRoutedNotifier(func(conf *config.Config) map[string]Notifier { res := map[string]Notifier{} @@ -55,7 +50,6 @@ func main() { } return res }) - routedNotifier.ApplyConfig(conf) var notifier Notifier notifier = routedNotifier @@ -70,7 +64,10 @@ func main() { disp := NewDispatcher(alerts, notifier) - disp.ApplyConfig(conf) + if !reloadConfig(*configFile, disp, routedNotifier, inhibitor) { + os.Exit(1) + } + go disp.Run() defer disp.Stop() @@ -80,10 +77,37 @@ func main() { go http.ListenAndServe(":9091", router) - term := make(chan os.Signal) + var ( + hup = make(chan os.Signal) + term = make(chan os.Signal) + ) + signal.Notify(hup, syscall.SIGHUP) signal.Notify(term, os.Interrupt, syscall.SIGTERM) + + go func() { + for range hup { + reloadConfig(*configFile, disp, routedNotifier, inhibitor) + } + }() + <-term log.Infoln("Received SIGTERM, exiting gracefully...") os.Exit(0) } + +func reloadConfig(filename string, rls ...types.Reloadable) (success bool) { + log.Infof("Loading configuration file %s", filename) + + conf, err := config.LoadFile(filename) + if err != nil { + log.Errorf("Couldn't load configuration (-config.file=%s): %v", filename, err) + return false + } + success = true + + for _, rl := range rls { + success = success && rl.ApplyConfig(conf) + } + return success +} diff --git a/notify.go b/notify.go index 4c249923..dce8e7fe 100644 --- a/notify.go +++ b/notify.go @@ -150,7 +150,7 @@ func (n *routedNotifier) Notify(ctx context.Context, alerts ...*types.Alert) err return notifier.Notify(ctx, alerts...) } -func (n *routedNotifier) ApplyConfig(conf *config.Config) { +func (n *routedNotifier) ApplyConfig(conf *config.Config) bool { n.mtx.Lock() defer n.mtx.Unlock() @@ -160,6 +160,8 @@ func (n *routedNotifier) ApplyConfig(conf *config.Config) { for _, opts := range conf.NotificationConfigs { n.notifierOpts[opts.Name] = opts } + + return true } // mutingNotifier wraps a notifier and applies a Silencer diff --git a/provider/provider.go b/provider/provider.go index 4f0b836f..ef9324a4 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -16,7 +16,6 @@ package provider import ( "github.com/prometheus/common/model" - "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/types" ) @@ -70,13 +69,7 @@ type Notifies interface { Set(dest string, ns ...*types.Notify) error } -// Reloadable is a component that can change its state based -// on a new configuration. -type Reloadable interface { - ApplyConfig(*config.Config) -} - type Config interface { // Reload initiates a configuration reload. - Reload(...Reloadable) error + Reload(...types.Reloadable) error } diff --git a/types/types.go b/types/types.go index fe3b9def..b556a6d7 100644 --- a/types/types.go +++ b/types/types.go @@ -7,8 +7,16 @@ import ( "time" "github.com/prometheus/common/model" + + "github.com/prometheus/alertmanager/config" ) +// Reloadable is a component that can change its state based +// on a new configuration. +type Reloadable interface { + ApplyConfig(*config.Config) bool +} + type Annotations map[model.LabelName]string type Alert struct {