func main() { flag.Parse() if *showVersion { fmt.Fprintln(os.Stdout, version.Print("mysqld_exporter")) os.Exit(0) } log.Infoln("Starting mysqld_exporter", version.Info()) log.Infoln("Build context", version.BuildContext()) dsn := os.Getenv("DATA_SOURCE_NAME") if len(dsn) == 0 { var err error if dsn, err = parseMycnf(*configMycnf); err != nil { log.Fatal(err) } } exporter := NewExporter(dsn) prometheus.MustRegister(exporter) http.Handle(*metricPath, prometheus.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write(landingPage) }) log.Infoln("Listening on", *listenAddress) log.Fatal(http.ListenAndServe(*listenAddress, nil)) }
func watchConfig(fileName string, mapper *metricMapper) { watcher, err := fsnotify.NewWatcher() if err != nil { log.Fatal(err) } err = watcher.WatchFlags(fileName, fsnotify.FSN_MODIFY) if err != nil { log.Fatal(err) } for { select { case ev := <-watcher.Event: log.Infof("Config file changed (%s), attempting reload", ev) err = mapper.initFromFile(fileName) if err != nil { log.Errorln("Error reloading config:", err) configLoads.WithLabelValues("failure").Inc() } else { log.Infoln("Config reloaded successfully") configLoads.WithLabelValues("success").Inc() } // Re-add the file watcher since it can get lost on some changes. E.g. // saving a file with vim results in a RENAME-MODIFY-DELETE event // sequence, after which the newly written file is no longer watched. err = watcher.WatchFlags(fileName, fsnotify.FSN_MODIFY) case err := <-watcher.Error: log.Errorln("Error watching config:", err) } } }
func main() { flag.Parse() if *printCollectors { collectorNames := make(sort.StringSlice, 0, len(collector.Factories)) for n := range collector.Factories { collectorNames = append(collectorNames, n) } collectorNames.Sort() fmt.Printf("Available collectors:\n") for _, n := range collectorNames { fmt.Printf(" - %s\n", n) } return } collectors, err := loadCollectors() if err != nil { log.Fatalf("Couldn't load collectors: %s", err) } log.Infof("Enabled collectors:") for n := range collectors { log.Infof(" - %s", n) } nodeCollector := NodeCollector{collectors: collectors} prometheus.MustRegister(nodeCollector) sigUsr1 := make(chan os.Signal) signal.Notify(sigUsr1, syscall.SIGUSR1) handler := prometheus.Handler() if *authUser != "" || *authPass != "" { if *authUser == "" || *authPass == "" { log.Fatal("You need to specify -auth.user and -auth.pass to enable basic auth") } handler = &basicAuthHandler{ handler: prometheus.Handler().ServeHTTP, user: *authUser, password: *authPass, } } http.Handle(*metricsPath, handler) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<html> <head><title>Node Exporter</title></head> <body> <h1>Node Exporter</h1> <p><a href="` + *metricsPath + `">Metrics</a></p> </body> </html>`)) }) log.Infof("Starting node_exporter v%s at %s", Version, *listenAddress) err = http.ListenAndServe(*listenAddress, nil) if err != nil { log.Fatal(err) } }
func main() { var ( listenAddress = flag.String("web.listen-address", ":9101", "Address to listen on for web interface and telemetry.") metricsPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.") haProxyScrapeURI = flag.String("haproxy.scrape-uri", "http://localhost/;csv", "URI on which to scrape HAProxy.") haProxyServerMetricFields = flag.String("haproxy.server-metric-fields", serverMetrics.String(), "Comma-seperated list of exported server metrics. See http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#9.1") haProxyTimeout = flag.Duration("haproxy.timeout", 5*time.Second, "Timeout for trying to get stats from HAProxy.") haProxyPidFile = flag.String("haproxy.pid-file", "", "Path to haproxy's pid file.") ) flag.Parse() selectedServerMetrics, err := filterServerMetrics(*haProxyServerMetricFields) if err != nil { log.Fatal(err) } exporter := NewExporter(*haProxyScrapeURI, selectedServerMetrics, *haProxyTimeout) prometheus.MustRegister(exporter) if *haProxyPidFile != "" { procExporter := prometheus.NewProcessCollectorPIDFn( func() (int, error) { content, err := ioutil.ReadFile(*haProxyPidFile) if err != nil { return 0, fmt.Errorf("Can't read pid file: %s", err) } value, err := strconv.Atoi(strings.TrimSpace(string(content))) if err != nil { return 0, fmt.Errorf("Can't parse pid file: %s", err) } return value, nil }, namespace) prometheus.MustRegister(procExporter) } log.Infof("Starting Server: %s", *listenAddress) http.Handle(*metricsPath, prometheus.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<html> <head><title>Haproxy Exporter</title></head> <body> <h1>Haproxy Exporter</h1> <p><a href='` + *metricsPath + `'>Metrics</a></p> </body> </html>`)) }) log.Fatal(http.ListenAndServe(*listenAddress, nil)) }
func main() { flag.Parse() if *showVersion { fmt.Fprintln(os.Stdout, version.Print("statsd_exporter")) os.Exit(0) } if *addSuffix { log.Warnln("Warning: Using -statsd.add-suffix is discouraged. We recommend explicitly naming metrics appropriately in the mapping configuration.") } log.Infoln("Starting StatsD -> Prometheus Exporter", version.Info()) log.Infoln("Build context", version.BuildContext()) log.Infoln("Accepting StatsD Traffic on", *statsdListenAddress) log.Infoln("Accepting Prometheus Requests on", *listenAddress) go serveHTTP() events := make(chan Events, 1024) defer close(events) listenAddr := udpAddrFromString(*statsdListenAddress) conn, err := net.ListenUDP("udp", listenAddr) if err != nil { log.Fatal(err) } if *readBuffer != 0 { err = conn.SetReadBuffer(*readBuffer) if err != nil { log.Fatal("Error setting UDP read buffer:", err) } } l := &StatsDListener{conn: conn} go l.Listen(events) mapper := &metricMapper{} if *mappingConfig != "" { err := mapper.initFromFile(*mappingConfig) if err != nil { log.Fatal("Error loading config:", err) } go watchConfig(*mappingConfig, mapper) } exporter := NewExporter(mapper, *addSuffix) exporter.Listen(events) }
func main() { config := createConfig() log.Info("Create provisioner...") provisioner, err := provisioner.NewProvisioner(config.Token) if err != nil { log.Fatal(err) } go backgroundRunner(provisioner) log.Info("Create server...") server := web.CreateServer(provisioner) log.Infof("Listen on %s", config.Port) log.Fatal(http.ListenAndServe(":"+config.Port, server)) }
func udpAddrFromString(addr string) *net.UDPAddr { host, portStr, err := net.SplitHostPort(addr) if err != nil { log.Fatal("Bad StatsD listening address", addr) } if host == "" { host = "0.0.0.0" } ip, err := net.ResolveIPAddr("ip", host) if err != nil { log.Fatalf("Unable to resolve %s: %s", host, err) } port, err := strconv.Atoi(portStr) if err != nil || port < 0 || port > 65535 { log.Fatalf("Bad port %s: %s", portStr, err) } return &net.UDPAddr{ IP: ip.IP, Port: port, Zone: ip.Zone, } }
func main() { var ( listenAddress = flag.String("listen-address", ":9120", "Address to listen on for web interface and telemetry.") metricsPath = flag.String("metric-path", "/metrics", "Path under which to expose metrics.") apiURL = flag.String("api-url", "http://localhost:8001/", "Base-URL of PowerDNS authoritative server/recursor API.") apiKey = flag.String("api-key", "", "PowerDNS API Key") ) flag.Parse() hostURL, err := url.Parse(*apiURL) if err != nil { log.Fatalf("Error parsing api-url: %v", err) } server, err := getServerInfo(hostURL, *apiKey) if err != nil { log.Fatalf("Could not fetch PowerDNS server info: %v", err) } exporter := NewExporter(*apiKey, server.DaemonType, hostURL) prometheus.MustRegister(exporter) log.Infof("Starting Server: %s", *listenAddress) http.Handle(*metricsPath, prometheus.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<html> <head><title>PowerDNS Exporter</title></head> <body> <h1>PowerDNS Exporter</h1> <p><a href='` + *metricsPath + `'>Metrics</a></p> </body> </html>`)) }) log.Fatal(http.ListenAndServe(*listenAddress, nil)) }
func main() { flag.Parse() if *showVersion { fmt.Fprintln(os.Stdout, version.Print("collectd_exporter")) os.Exit(0) } log.Infoln("Starting collectd_exporter", version.Info()) log.Infoln("Build context", version.BuildContext()) c := newCollectdCollector() prometheus.MustRegister(c) startCollectdServer(context.Background(), c) if *collectdPostPath != "" { http.HandleFunc(*collectdPostPath, c.collectdPost) } http.Handle(*metricsPath, prometheus.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<html> <head><title>Collectd Exporter</title></head> <body> <h1>Collectd Exporter</h1> <p><a href='` + *metricsPath + `'>Metrics</a></p> </body> </html>`)) }) log.Infoln("Listening on", *listenAddress) log.Fatal(http.ListenAndServe(*listenAddress, nil)) }
func main() { flag.Parse() exporter := NewExporter(*scrapeURI) prometheus.MustRegister(exporter) log.Infof("Starting Server: %s", *listeningAddress) http.Handle(*metricsEndpoint, prometheus.Handler()) log.Fatal(http.ListenAndServe(*listeningAddress, nil)) }
func (l *StatsDListener) Listen(e chan<- Events) { buf := make([]byte, 65535) for { n, _, err := l.conn.ReadFromUDP(buf) if err != nil { log.Fatal(err) } l.handlePacket(buf[0:n], e) } }
func main() { r := httprouter.New() // r.GET("/overview", Overview) r.GET("/graph/*importpath", Grapher) r.ServeFiles("/static/*filepath", http.Dir("static/")) log.Infoln("launching tracegraph on :8080") log.Fatal(http.ListenAndServe(":8080", r)) }
func main() { var ( listenAddress = flag.String("web.listen-address", ":9100", "Address on which to expose metrics and web interface.") metricsPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.") enabledCollectors = flag.String("collectors.enabled", filterAvailableCollectors(defaultCollectors), "Comma-separated list of collectors to use.") printCollectors = flag.Bool("collectors.print", false, "If true, print available collectors and exit.") ) flag.Parse() if *printCollectors { collectorNames := make(sort.StringSlice, 0, len(collector.Factories)) for n := range collector.Factories { collectorNames = append(collectorNames, n) } collectorNames.Sort() fmt.Printf("Available collectors:\n") for _, n := range collectorNames { fmt.Printf(" - %s\n", n) } return } collectors, err := loadCollectors(*enabledCollectors) if err != nil { log.Fatalf("Couldn't load collectors: %s", err) } log.Infof("Enabled collectors:") for n := range collectors { log.Infof(" - %s", n) } nodeCollector := NodeCollector{collectors: collectors} prometheus.MustRegister(nodeCollector) handler := prometheus.Handler() http.Handle(*metricsPath, handler) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<html> <head><title>Node Exporter</title></head> <body> <h1>Node Exporter</h1> <p><a href="` + *metricsPath + `">Metrics</a></p> </body> </html>`)) }) log.Infof("Starting node_exporter v%s at %s", Version, *listenAddress) err = http.ListenAndServe(*listenAddress, nil) if err != nil { log.Fatal(err) } }
func main() { var ( bindURI = flag.String("bind.stats-url", "http://localhost:8053/", "HTTP XML API address of an Bind server.") bindTimeout = flag.Duration("bind.timeout", 10*time.Second, "Timeout for trying to get stats from Bind.") bindPidFile = flag.String("bind.pid-file", "", "Path to Bind's pid file to export process information.") bindVersion = flag.String("bind.stats-version", "auto", "BIND statistics version. Can be detected automatically. Available: [xml.v2, xml.v3, auto]") showVersion = flag.Bool("version", false, "Print version information.") listenAddress = flag.String("web.listen-address", ":9119", "Address to listen on for web interface and telemetry.") metricsPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.") groups = statisticGroups{bind.ServerStats, bind.ViewStats} ) flag.Var(&groups, "bind.stats-groups", "Comma-separated list of statistics to collect. Available: [server, view, tasks]") flag.Parse() if *showVersion { fmt.Fprintln(os.Stdout, version.Print("bind_exporter")) os.Exit(0) } log.Infoln("Starting bind_exporter", version.Info()) log.Infoln("Build context", version.BuildContext()) log.Infoln("Configured to collect statistics", groups.String()) prometheus.MustRegister(NewExporter(*bindVersion, *bindURI, *bindTimeout, groups)) if *bindPidFile != "" { procExporter := prometheus.NewProcessCollectorPIDFn( func() (int, error) { content, err := ioutil.ReadFile(*bindPidFile) if err != nil { return 0, fmt.Errorf("Can't read pid file: %s", err) } value, err := strconv.Atoi(strings.TrimSpace(string(content))) if err != nil { return 0, fmt.Errorf("Can't parse pid file: %s", err) } return value, nil }, namespace) prometheus.MustRegister(procExporter) } log.Info("Starting Server: ", *listenAddress) http.Handle(*metricsPath, prometheus.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<html> <head><title>Bind Exporter</title></head> <body> <h1>Bind Exporter</h1> <p><a href='` + *metricsPath + `'>Metrics</a></p> </body> </html>`)) }) log.Fatal(http.ListenAndServe(*listenAddress, nil)) }
func main() { flag.Parse() dsn := os.Getenv("DATA_SOURCE_NAME") if len(dsn) == 0 { var err error if dsn, err = parseMycnf(*configMycnf); err != nil { log.Fatal(err) } } exporter := NewExporter(dsn) prometheus.MustRegister(exporter) http.Handle(*metricPath, prometheus.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write(landingPage) }) log.Infof("Starting Server: %s", *listenAddress) log.Fatal(http.ListenAndServe(*listenAddress, nil)) }
func main() { flag.Parse() uri, err := url.Parse(*marathonUri) if err != nil { log.Fatal(err) } retryTimeout := time.Duration(10 * time.Second) for { err := marathonConnect(uri) if err == nil { break } log.Debugf("Problem connecting to Marathon: %v", err) log.Infof("Couldn't connect to Marathon! Trying again in %v", retryTimeout) time.Sleep(retryTimeout) } exporter := NewExporter(&scraper{uri}) prometheus.MustRegister(exporter) http.Handle(*metricsPath, prometheus.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<html> <head><title>Marathon Exporter</title></head> <body> <h1>Marathon Exporter</h1> <p><a href='` + *metricsPath + `'>Metrics</a></p> </body> </html>`)) }) log.Info("Starting Server: ", *listenAddress) log.Fatal(http.ListenAndServe(*listenAddress, nil)) }
func main() { flag.Parse() if *onlyDumpMaps { dumpMaps() return } dsn := os.Getenv("DATA_SOURCE_NAME") if len(dsn) == 0 { log.Fatal("couldn't find environment variable DATA_SOURCE_NAME") } exporter := NewExporter(dsn, *queriesPath) prometheus.MustRegister(exporter) http.Handle(*metricPath, prometheus.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write(landingPage) }) log.Infof("Starting Server: %s", *listenAddress) log.Fatal(http.ListenAndServe(*listenAddress, nil)) }
func main() { flag.Parse() if *printCollectors { collectorNames := make(sort.StringSlice, 0, len(collector.Factories)) for n := range collector.Factories { collectorNames = append(collectorNames, n) } collectorNames.Sort() fmt.Printf("Available collectors:\n") for _, n := range collectorNames { fmt.Printf(" - %s\n", n) } return } collectors, err := loadCollectors() if err != nil { log.Fatalf("Couldn't load collectors: %s", err) } log.Infof("Enabled collectors:") for n := range collectors { log.Infof(" - %s", n) } nodeCollector := NodeCollector{collectors: collectors} prometheus.MustRegister(nodeCollector) handler := prometheus.Handler() http.Handle(*metricsPath, handler) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<html> <head><title>Node Exporter</title></head> <body> <h1>Node Exporter</h1> <p><a href="` + *metricsPath + `">Metrics</a></p> </body> </html>`)) }) log.Infof("Starting node_exporter v%s at %s", Version, *listenAddress) err = http.ListenAndServe(*listenAddress, nil) if err != nil { log.Fatal(err) } }
// NewClient creates a new Client. func NewClient(conf influx.Config, db string, rp string) *Client { c, err := influx.NewClient(conf) // Currently influx.NewClient() *should* never return an error. if err != nil { log.Fatal(err) } return &Client{ client: c, database: db, retentionPolicy: rp, ignoredSamples: prometheus.NewCounter( prometheus.CounterOpts{ Name: "prometheus_influxdb_ignored_samples_total", Help: "The total number of samples not sent to InfluxDB due to unsupported float values (Inf, -Inf, NaN).", }, ), } }
func main() { flag.Parse() exporter := NewTinystatsExporter() prometheus.MustRegister(exporter) http.Handle(*metricsPath, prometheus.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<html> <head><title>Tinystats Exporter</title></head> <body> <h1>Tinystats Exporter</h1> <p><a href='` + *metricsPath + `'>Metrics</a></p> </body> </html> `)) }) log.Infof("Starting Server: %s", *listenAddress) log.Infof("ipv4tinystats file: %s", *ipv4TinystatsFile) log.Infof("ipv6tinystats file: %s", *ipv6TinystatsFile) log.Fatal(http.ListenAndServe(*listenAddress, nil)) }
func main() { flag.Parse() log.Infoln("Starting snmp exporter", version.Info()) log.Infoln("Build context", version.BuildContext()) // Bail early if the config is bad. c, err := LoadFile(*configFile) if err != nil { log.Fatalf("Error parsing config file: %s", err) } // Initilise metrics. for module, _ := range *c { snmpDuration.WithLabelValues(module) } http.Handle("/metrics", promhttp.Handler()) // Normal metrics endpoint for SNMP exporter itself. http.HandleFunc("/snmp", handler) // Endpoint to do SNMP scrapes. log.Infof("Listening on %s", *listenAddress) log.Fatal(http.ListenAndServe(*listenAddress, nil)) }
func main() { flag.Parse() exporter, err := NewPfExporter() if err != nil { log.Fatalf("Failed to create pf exporter: %v", err) } prometheus.MustRegister(exporter) log.Infof("Starting Server: %s", *listenAddress) http.Handle(*metricsPath, prometheus.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<html> <head><title>pf Exporter</title></head> <body> <h1>pf Exporter</h1> <p><a href='` + *metricsPath + `'>Metrics</a></p> </body> </html>`)) }) log.Fatal(http.ListenAndServe(*listenAddress, nil)) }
func main() { var ( listenAddress = flag.String("web.listen-address", ":9101", "Address to listen on for web interface and telemetry.") metricsPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.") actuatorScrapeURI = flag.String("actuator.scrape-uri", "http://localhost/metrics", "URI on which to scrape Spring Actuator.") timeout = flag.Duration("actuator.timeout", 5*time.Second, "Timeout for trying to get stats from Spring Actuator.") ) flag.Parse() exporter := NewExporter(*actuatorScrapeURI, *timeout) prometheus.MustRegister(exporter) log.Infof("Starting Server: %s", *listenAddress) http.Handle(*metricsPath, prometheus.Handler()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<html> <head><title>Spring Actuator Exporter</title></head> <body> <h1>Spring Actuator Exporter</h1> <p><a href='` + *metricsPath + `'>Metrics</a></p> </body> </html>`)) }) log.Fatal(http.ListenAndServe(*listenAddress, nil)) }
func listen(listen string, router *route.Router) { if err := http.ListenAndServe(listen, router); err != nil { log.Fatal(err) } }
func startCollectdServer(ctx context.Context, w api.Writer) { if *collectdAddress == "" { return } srv := network.Server{ Addr: *collectdAddress, Writer: w, } if *collectdAuth != "" { srv.PasswordLookup = network.NewAuthFile(*collectdAuth) } if *collectdTypesDB != "" { file, err := os.Open(*collectdTypesDB) if err != nil { log.Fatalf("Can't open types.db file %s", *collectdTypesDB) } defer file.Close() typesDB, err := api.NewTypesDB(file) if err != nil { log.Fatalf("Error in parsing types.db file %s", *collectdTypesDB) } srv.TypesDB = typesDB } switch strings.ToLower(*collectdSecurity) { case "", "none": srv.SecurityLevel = network.None case "sign": srv.SecurityLevel = network.Sign case "encrypt": srv.SecurityLevel = network.Encrypt default: log.Fatalf("Unknown security level %q. Must be one of \"None\", \"Sign\" and \"Encrypt\".", *collectdSecurity) } laddr, err := net.ResolveUDPAddr("udp", *collectdAddress) if err != nil { log.Fatalf("Failed to resolve binary protocol listening UDP address %q: %v", *collectdAddress, err) } if laddr.IP != nil && laddr.IP.IsMulticast() { srv.Conn, err = net.ListenMulticastUDP("udp", nil, laddr) } else { srv.Conn, err = net.ListenUDP("udp", laddr) } if err != nil { log.Fatalf("Failed to create a socket for a binary protocol server: %v", err) } if *collectdBuffer >= 0 { if err = srv.Conn.SetReadBuffer(*collectdBuffer); err != nil { log.Fatalf("Failed to adjust a read buffer of the socket: %v", err) } } go func() { log.Fatal(srv.ListenAndWrite(ctx)) }() }
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 listen(router *route.Router) { if err := http.ListenAndServe(*listenAddress, router); err != nil { log.Fatal(err) } }
func main() { rand.Seed(time.Now().Unix()) flag.Parse() // This is only used when we're running in -dev mode with bindata rootDir, _ = osext.ExecutableFolder() rootDir = path.Join(rootDir, "web") // Parse configuration cfg, err := config.LoadFromFile(*configFile) if err != nil { log.Fatalln("Error loading config", err) } // Templates amberTmpl, err := Asset("templates/index.amber") if err != nil { log.Fatalln("Could not load index template:", err) } tmpl := amber.MustCompile(string(amberTmpl), amber.Options{}) // Setup the web UI router := httprouter.New() router.Handler("GET", *metricsPath, prometheus.Handler()) // Prometheus // Static asset handling router.GET("/static/*filepath", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { reqpath := ps.ByName("filepath") realpath := path.Join("static", reqpath) b, err := Asset(realpath) if err != nil { log.Debugln("Could not find asset: ", err) return } else { w.Write(b) } }) var monitoredHosts []*pollers.Host router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { data := struct { Cfg *config.Config Hosts *[]*pollers.Host }{ Cfg: cfg, Hosts: &monitoredHosts, } err := tmpl.Execute(w, &data) if err != nil { log.Errorln("Error rendering template", err) } }) // Initialize the host pollers monitoredHosts = make([]*pollers.Host, len(cfg.Hosts)) // We don't allow duplicate hosts, but also don't want to panic just due // to a typo, so keep track and skip duplicates here. seenHosts := make(map[string]bool) realidx := 0 for _, hostCfg := range cfg.Hosts { log.Debugln("Setting up poller for: ", hostCfg.Hostname) if *skipPing { hostCfg.PingDisable = true } if _, ok := seenHosts[hostCfg.Hostname]; ok { log.Warnln("Discarding repeat configuration of same hostname", hostCfg.Hostname) continue } host := pollers.NewHost(hostCfg) monitoredHosts[realidx] = host prometheus.MustRegister(host) seenHosts[hostCfg.Hostname] = true realidx++ } // Trim monitoredHosts to the number we actually used monitoredHosts = monitoredHosts[0:realidx] // This is the dispatcher. It is responsible for invoking the doPoll method // of hosts. connectionLimiter := pollers.NewLimiter(*maxConnections) hostQueue := make(chan *pollers.Host) // Start the host dispatcher go func() { for host := range hostQueue { go host.Poll(connectionLimiter, hostQueue) } }() // Do the initial host dispatch go func() { for _, host := range monitoredHosts { log.Debugln("Starting polling for hosts") hostQueue <- host } }() var handler http.Handler // If basic auth is requested, enable it for the interface. if cfg.BasicAuthUsername != "" && cfg.BasicAuthPassword != "" { basicauth := httpauth.SimpleBasicAuth(cfg.BasicAuthUsername, cfg.BasicAuthPassword) handler = basicauth(router) } else { handler = router } // If TLS certificates are specificed, use TLS if cfg.TLSCertificatePath != "" && cfg.TLSKeyPath != "" { log.Infof("Listening on (TLS-enabled) %s", *listenAddress) err = http.ListenAndServeTLS(*listenAddress, cfg.TLSCertificatePath, cfg.TLSKeyPath, handler) } else { log.Infof("Listening on %s", *listenAddress) err = http.ListenAndServe(*listenAddress, handler) } if err != nil { log.Fatal(err) } }
func main() { peers := &stringset{} var ( showVersion = flag.Bool("version", false, "Print version information.") configFile = flag.String("config.file", "alertmanager.yml", "Alertmanager configuration file name.") dataDir = flag.String("storage.path", "data/", "Base path for data storage.") retention = flag.Duration("data.retention", 5*24*time.Hour, "How long to keep data for.") externalURL = flag.String("web.external-url", "", "The URL under which Alertmanager is externally reachable (for example, if Alertmanager is served via a reverse proxy). Used for generating relative and absolute links back to Alertmanager itself. If the URL has a path portion, it will be used to prefix all HTTP endpoints served by Alertmanager. If omitted, relevant URL components will be derived automatically.") listenAddress = flag.String("web.listen-address", ":9093", "Address to listen on for the web interface and API.") meshListen = flag.String("mesh.listen-address", net.JoinHostPort("0.0.0.0", strconv.Itoa(mesh.Port)), "mesh listen address") hwaddr = flag.String("mesh.hardware-address", mustHardwareAddr(), "MAC address, i.e. mesh peer ID") nickname = flag.String("mesh.nickname", mustHostname(), "peer nickname") ) flag.Var(peers, "mesh.peer", "initial peers (may be repeated)") flag.Parse() if len(flag.Args()) > 0 { log.Fatalln("Received unexpected and unparsed arguments: ", strings.Join(flag.Args(), ", ")) } 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) } logger := log.NewLogger(os.Stderr) mrouter := initMesh(*meshListen, *hwaddr, *nickname) stopc := make(chan struct{}) var wg sync.WaitGroup wg.Add(1) notificationLog, err := nflog.New( nflog.WithMesh(func(g mesh.Gossiper) mesh.Gossip { return mrouter.NewGossip("nflog", g) }), nflog.WithRetention(*retention), nflog.WithSnapshot(filepath.Join(*dataDir, "nflog")), nflog.WithMaintenance(15*time.Minute, stopc, wg.Done), nflog.WithLogger(logger.With("component", "nflog")), ) if err != nil { log.Fatal(err) } marker := types.NewMarker() silences, err := silence.New(silence.Options{ SnapshotFile: filepath.Join(*dataDir, "silences"), Retention: *retention, Logger: logger.With("component", "silences"), Gossip: func(g mesh.Gossiper) mesh.Gossip { return mrouter.NewGossip("silences", g) }, }) if err != nil { log.Fatal(err) } // Start providers before router potentially sends updates. wg.Add(1) go func() { silences.Maintenance(15*time.Minute, filepath.Join(*dataDir, "silences"), stopc) wg.Done() }() mrouter.Start() defer func() { close(stopc) // Stop receiving updates from router before shutting down. mrouter.Stop() wg.Wait() }() mrouter.ConnectionMaker.InitiateConnections(peers.slice(), true) alerts, err := mem.NewAlerts(*dataDir) if err != nil { log.Fatal(err) } defer alerts.Close() var ( inhibitor *inhibit.Inhibitor tmpl *template.Template pipeline notify.Stage disp *dispatch.Dispatcher ) defer disp.Stop() apiv := api.New(alerts, silences, func() dispatch.AlertOverview { return disp.Groups() }) amURL, err := extURL(*listenAddress, *externalURL) if err != nil { log.Fatal(err) } waitFunc := meshWait(mrouter, 5*time.Second) timeoutFunc := func(d time.Duration) time.Duration { if d < notify.MinTimeout { d = notify.MinTimeout } return d + waitFunc() } 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 } apiv.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 = inhibit.NewInhibitor(alerts, conf.InhibitRules, marker) pipeline = notify.BuildPipeline( conf.Receivers, tmpl, waitFunc, inhibitor, silences, notificationLog, marker, ) disp = dispatch.NewDispatcher(alerts, dispatch.NewRoute(conf.Route, nil), pipeline, marker, timeoutFunc) go disp.Run() go inhibitor.Run() return nil } if err := reload(); err != nil { os.Exit(1) } router := route.New() webReload := make(chan struct{}) ui.Register(router.WithPrefix(amURL.Path), webReload) apiv.Register(router.WithPrefix(path.Join(amURL.Path, "/api"))) log.Infoln("Listening on", *listenAddress) go listen(*listenAddress, 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...") }