func main() { flag.Parse() if *showVersion { fmt.Fprintln(os.Stdout, version.Print("alertmanager")) os.Exit(0) } log.Infoln("Starting alertmanager", version.Info()) log.Infoln("Build context", version.BuildContext()) err := os.MkdirAll(*dataDir, 0777) if err != nil { log.Fatal(err) } marker := types.NewMarker() alerts, err := boltmem.NewAlerts(*dataDir) if err != nil { log.Fatal(err) } defer alerts.Close() notifies, err := boltmem.NewNotificationInfo(*dataDir) if err != nil { log.Fatal(err) } defer notifies.Close() silences, err := boltmem.NewSilences(*dataDir, marker) if err != nil { log.Fatal(err) } defer silences.Close() var ( inhibitor *Inhibitor tmpl *template.Template disp *Dispatcher ) defer disp.Stop() api := NewAPI(alerts, silences, func() AlertOverview { return disp.Groups() }) build := func(rcvs []*config.Receiver) notify.Notifier { var ( router = notify.Router{} fanouts = notify.Build(rcvs, tmpl) ) for name, fo := range fanouts { for i, n := range fo { n = notify.Retry(n) n = notify.Log(n, log.With("step", "retry")) n = notify.Dedup(notifies, n) n = notify.Log(n, log.With("step", "dedup")) fo[i] = n } router[name] = fo } n := notify.Notifier(router) n = notify.Log(n, log.With("step", "route")) n = notify.Silence(silences, n, marker) n = notify.Log(n, log.With("step", "silence")) n = notify.Inhibit(inhibitor, n, marker) n = notify.Log(n, log.With("step", "inhibit")) return n } amURL, err := extURL(*externalURL) if err != nil { log.Fatal(err) } reload := func() (err error) { log.With("file", *configFile).Infof("Loading configuration file") defer func() { if err != nil { log.With("file", *configFile).Errorf("Loading configuration file failed: %s", err) configSuccess.Set(0) } else { configSuccess.Set(1) configSuccessTime.Set(float64(time.Now().Unix())) } }() conf, err := config.LoadFile(*configFile) if err != nil { return err } api.Update(conf.String(), time.Duration(conf.Global.ResolveTimeout)) tmpl, err = template.FromGlobs(conf.Templates...) if err != nil { return err } tmpl.ExternalURL = amURL inhibitor.Stop() disp.Stop() inhibitor = NewInhibitor(alerts, conf.InhibitRules, marker) disp = NewDispatcher(alerts, NewRoute(conf.Route, nil), build(conf.Receivers), marker) go disp.Run() go inhibitor.Run() return nil } if err := reload(); err != nil { os.Exit(1) } router := route.New() webReload := make(chan struct{}) RegisterWeb(router.WithPrefix(amURL.Path), webReload) api.Register(router.WithPrefix(path.Join(amURL.Path, "/api"))) log.Infoln("Listening on", *listenAddress) go listen(router) var ( hup = make(chan os.Signal) hupReady = make(chan bool) term = make(chan os.Signal) ) signal.Notify(hup, syscall.SIGHUP) signal.Notify(term, os.Interrupt, syscall.SIGTERM) go func() { <-hupReady for { select { case <-hup: case <-webReload: } reload() } }() // Wait for reload or termination signals. close(hupReady) // Unblock SIGHUP handler. <-term log.Infoln("Received SIGTERM, exiting gracefully...") }
func main() { flag.Parse() printVersion() if *showVersion { os.Exit(0) } err := os.MkdirAll(*dataDir, 0777) if err != nil { log.Fatal(err) } db, err := sql.Open("sqlite3", filepath.Join(*dataDir, "am.db")) if err != nil { log.Fatal(err) } defer db.Close() marker := types.NewMarker() alerts, err := sqlite.NewAlerts(db) if err != nil { log.Fatal(err) } notifies, err := sqlite.NewNotifies(db) if err != nil { log.Fatal(err) } silences, err := sqlite.NewSilences(db, marker) if err != nil { log.Fatal(err) } var ( inhibitor *Inhibitor tmpl *template.Template disp *Dispatcher ) defer disp.Stop() api := NewAPI(alerts, silences, func() AlertOverview { return disp.Groups() }) build := func(rcvs []*config.Receiver) notify.Notifier { var ( router = notify.Router{} fanouts = notify.Build(rcvs, tmpl) ) for name, fo := range fanouts { for i, n := range fo { n = notify.Retry(n) n = notify.Log(n, log.With("step", "retry")) n = notify.Dedup(notifies, n) n = notify.Log(n, log.With("step", "dedup")) fo[i] = n } router[name] = fo } n := notify.Notifier(router) n = notify.Log(n, log.With("step", "route")) n = notify.Silence(silences, n, marker) n = notify.Log(n, log.With("step", "silence")) n = notify.Inhibit(inhibitor, n, marker) n = notify.Log(n, log.With("step", "inhibit")) return n } reload := func() (err error) { log.With("file", *configFile).Infof("Loading configuration file") defer func() { if err != nil { log.With("file", *configFile).Errorf("Loading configuration file failed: %s", err) } }() conf, err := config.LoadFile(*configFile) if err != nil { return err } api.Update(conf.String(), time.Duration(conf.Global.ResolveTimeout)) tmpl, err = template.FromGlobs(conf.Templates...) if err != nil { return err } if tmpl.ExternalURL, err = extURL(*externalURL); err != nil { return err } disp.Stop() inhibitor = NewInhibitor(alerts, conf.InhibitRules, marker) disp = NewDispatcher(alerts, NewRoute(conf.Route, nil), build(conf.Receivers), marker) go disp.Run() return nil } if err := reload(); err != nil { os.Exit(1) } router := route.New() RegisterWeb(router) api.Register(router.WithPrefix("/api")) go http.ListenAndServe(*listenAddress, router) 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 { reload() } }() <-term log.Infoln("Received SIGTERM, exiting gracefully...") }