func fetchMetricFamilies(url string, ch chan<- *dto.MetricFamily) { defer close(ch) req, err := http.NewRequest("GET", url, nil) if err != nil { log.Fatalf("creating GET request for URL %q failed: %s", url, err) } req.Header.Add("Accept", acceptHeader) resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatalf("executing GET request for URL %q failed: %s", url, err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { log.Fatalf("GET request for URL %q returned HTTP status %s", url, resp.Status) } mediatype, params, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) if err == nil && mediatype == "application/vnd.google.protobuf" && params["encoding"] == "delimited" && params["proto"] == "io.prometheus.client.MetricFamily" { for { mf := &dto.MetricFamily{} if _, err = pbutil.ReadDelimited(resp.Body, mf); err != nil { if err == io.EOF { break } log.Fatalln("reading metric family protocol buffer failed:", err) } ch <- mf } } else { // We could do further content-type checks here, but the // fallback for now will anyway be the text format // version 0.0.4, so just go for it and see if it works. var parser expfmt.TextParser metricFamilies, err := parser.TextToMetricFamilies(resp.Body) if err != nil { log.Fatalln("reading text format failed:", err) } for _, mf := range metricFamilies { ch <- mf } } }
func main() { flag.Parse() yamlFile, err := ioutil.ReadFile(*configFile) if err != nil { log.Fatalf("Error reading config file: %s", err) } config := Config{} err = yaml.Unmarshal(yamlFile, &config) if err != nil { log.Fatalf("Error parsing config file: %s", err) } http.Handle("/metrics", prometheus.Handler()) http.HandleFunc("/probe", func(w http.ResponseWriter, r *http.Request) { probeHandler(w, r, &config) }) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<html> <head><title>Blackbox Exporter</title></head> <body> <h1>Blackbox Exporter</h1> <p><a href="/probe?target=prometheus.io&module=http_2xx">Probe prometheus.io for http_2xx</a></p> <p><a href="/metrics">Metrics</a></p> </body> </html>`)) }) if err := http.ListenAndServe(*addr, nil); err != nil { log.Fatalf("Error starting HTTP server: %s", err) } }
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 parseMasterURL(masterURL string) *url.URL { parsedMasterURL, err := url.Parse(masterURL) if err != nil { log.Fatalf("unable to parse master URL '%s': ", masterURL, err) } if strings.HasPrefix(parsedMasterURL.Scheme, "http") == false { log.Fatalf("invalid scheme '%s' in master url - use 'http' or 'https'", parsedMasterURL.Scheme) } return parsedMasterURL }
func startCollectdServer(w api.Writer) { if *collectdAddress == "" { return } srv := network.Server{ Addr: *collectdAddress, Writer: w, } if *collectdAuth != "" { srv.PasswordLookup = network.NewAuthFile(*collectdAuth) } 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) } go func() { log.Fatal(srv.ListenAndWrite()) }() }
func MustLoadFromFile(fileName string) Config { conf, err := LoadFromFile(fileName) if err != nil { log.Fatalf("Error loading configuration from %s: %s", fileName, err) } return conf }
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() { flag.Parse() yamlFile, err := ioutil.ReadFile(*configFile) if err != nil { log.Fatalf("Error reading config file: %s", err) } config := Config{} err = yaml.Unmarshal(yamlFile, &config) if err != nil { log.Fatalf("Error parsing config file: %s", err) } http.Handle("/metrics", prometheus.Handler()) http.HandleFunc("/probe", func(w http.ResponseWriter, r *http.Request) { probeHandler(w, r, &config) }) http.ListenAndServe(*addr, nil) }
func (c *GaugeContainer) Get(metricName string, labels prometheus.Labels) prometheus.Gauge { hash := hashNameAndLabels(metricName, labels) gauge, ok := c.Elements[hash] if !ok { gauge = prometheus.NewGauge(prometheus.GaugeOpts{ Name: metricName, Help: defaultHelp, ConstLabels: labels, }) c.Elements[hash] = gauge if err := prometheus.Register(gauge); err != nil { log.Fatalf(regErrF, metricName, err) } } return gauge }
func (c *CounterContainer) Get(metricName string, labels prometheus.Labels) prometheus.Counter { hash := hashNameAndLabels(metricName, labels) counter, ok := c.Elements[hash] if !ok { counter = prometheus.NewCounter(prometheus.CounterOpts{ Name: metricName, Help: defaultHelp, ConstLabels: labels, }) c.Elements[hash] = counter if err := prometheus.Register(counter); err != nil { log.Fatalf(regErrF, metricName, err) } } return counter }
func (c *SummaryContainer) Get(metricName string, labels prometheus.Labels) prometheus.Summary { hash := hashNameAndLabels(metricName, labels) summary, ok := c.Elements[hash] if !ok { summary = prometheus.NewSummary( prometheus.SummaryOpts{ Name: metricName, Help: defaultHelp, ConstLabels: labels, }) c.Elements[hash] = summary if err := prometheus.Register(summary); err != nil { log.Fatalf(regErrF, metricName, err) } } return summary }
func newMesosExporter(opts *exporterOpts) *periodicExporter { e := &periodicExporter{ errors: prometheus.NewCounterVec( prometheus.CounterOpts{ Namespace: "mesos_exporter", Name: "slave_scrape_errors_total", Help: "Current total scrape errors", }, []string{"slave"}, ), opts: opts, } if opts.queryURL == "" { log.Fatal("Flag '-exporter.url' not set") } switch opts.mode { case "discover": log.Info("starting mesos_exporter in scrape mode 'discover'") e.queryURL = parseMasterURL(opts.queryURL) // Update nr. of mesos slaves. e.updateSlaves() go runEvery(e.updateSlaves, e.opts.autoDiscoverInterval) // Fetch slave metrics every interval. go runEvery(e.scrapeSlaves, e.opts.interval) case "master": log.Info("starting mesos_exporter in scrape mode 'master'") e.queryURL = parseMasterURL(opts.queryURL) case "slave": log.Info("starting mesos_exporter in scrape mode 'slave'") e.slaves.urls = []string{opts.queryURL} default: log.Fatalf("Invalid value '%s' of flag '-exporter.mode' - must be one of 'discover', 'master' or 'slave'", opts.mode) } return e }
func main() { flag.Parse() client := etcd.NewClient([]string{etcdServer}) srvs := &services{ m: map[string]*service{}, } updates := make(chan *etcd.Response) // Perform an initial read of all services. res, err := client.Get(servicesPrefix, false, true) if err != nil { log.Fatalf("Error on initial retrieval: %s", err) } srvs.update(res.Node) srvs.persist() // Start watching for updates. go func() { res, err := client.Watch(servicesPrefix, 0, true, updates, nil) if err != nil { log.Errorln(err) } log.Infoln(res) }() // Apply updates sent on the channel. for res := range updates { if res.Action == "delete" { log.Debugf("delete: %s", res.Node.Key) srvs.delete(res.Node) } else { log.Debugf("%s: %s = %s", res.Action, res.Node.Key, res.Node.Value) srvs.update(res.Node) } srvs.persist() } }
func main() { runtime.GOMAXPROCS(2) if len(os.Args) != 2 { log.Fatalf("Usage: %s METRICS_URL", os.Args[0]) } mfChan := make(chan *dto.MetricFamily, 1024) go fetchMetricFamilies(os.Args[1], mfChan) result := []*metricFamily{} for mf := range mfChan { result = append(result, newMetricFamily(mf)) } json, err := json.Marshal(result) if err != nil { log.Fatalln("error marshaling JSON:", err) } if _, err := os.Stdout.Write(json); err != nil { log.Fatalln("error writing to stdout:", err) } fmt.Println() }
func main() { flag.Parse() var ( client = etcd.NewClient([]string{*etcdServer}) srvs = services{} updates = make(chan *etcd.Response) ) // Perform an initial read of all services. res, err := client.Get(servicesPrefix, false, true) if err != nil { log.Fatalf("Error on initial retrieval: %s", err) } srvs.handle(res.Node, srvs.update) srvs.persist() // Start watching for updates. go func() { _, err := client.Watch(servicesPrefix, 0, true, updates, nil) if err != nil { log.Errorln(err) } }() // Apply updates sent on the channel. for res := range updates { log.Infoln(res.Action, res.Node.Key, res.Node.Value) h := srvs.update if res.Action == "delete" { h = srvs.delete } srvs.handle(res.Node, h) srvs.persist() } }
// NewExporter returns an initialized Exporter. func NewExporter(uri string, haProxyServerMetricFields string, timeout time.Duration) *Exporter { serverMetrics := map[int]*prometheus.GaugeVec{} serverMetricFields := make(map[int]bool) if haProxyServerMetricFields != "" { for _, f := range strings.Split(haProxyServerMetricFields, ",") { field, err := strconv.Atoi(f) if err != nil { log.Fatalf("Invalid field number: %v", f) } serverMetricFields[field] = true } } for index, metric := range map[int]*prometheus.GaugeVec{ 4: newServerMetric("current_sessions", "Current number of active sessions.", nil), 5: newServerMetric("max_sessions", "Maximum number of active sessions.", nil), 7: newServerMetric("connections_total", "Total number of connections.", nil), 8: newServerMetric("bytes_in_total", "Current total of incoming bytes.", nil), 9: newServerMetric("bytes_out_total", "Current total of outgoing bytes.", nil), 13: newServerMetric("connection_errors_total", "Total of connection errors.", nil), 14: newServerMetric("response_errors_total", "Total of response errors.", nil), 15: newServerMetric("retry_warnings_total", "Total of retry warnings.", nil), 16: newServerMetric("redispatch_warnings_total", "Total of redispatch warnings.", nil), 17: newServerMetric("up", "Current health status of the server (1 = UP, 0 = DOWN).", nil), 18: newServerMetric("weight", "Current weight of the server.", nil), 33: newServerMetric("current_session_rate", "Current number of sessions per second over last elapsed second.", nil), 35: newServerMetric("max_session_rate", "Maximum number of sessions per second.", nil), 39: newServerMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "1xx"}), 40: newServerMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "2xx"}), 41: newServerMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "3xx"}), 42: newServerMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "4xx"}), 43: newServerMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "5xx"}), 44: newServerMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "other"}), } { if len(serverMetricFields) == 0 || serverMetricFields[index] { serverMetrics[index] = metric } } return &Exporter{ URI: uri, up: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, Name: "up", Help: "Was the last scrape of haproxy successful.", }), totalScrapes: prometheus.NewCounter(prometheus.CounterOpts{ Namespace: namespace, Name: "exporter_total_scrapes", Help: "Current total HAProxy scrapes.", }), csvParseFailures: prometheus.NewCounter(prometheus.CounterOpts{ Namespace: namespace, Name: "exporter_csv_parse_failures", Help: "Number of errors while parsing CSV.", }), frontendMetrics: map[int]*prometheus.GaugeVec{ 4: newFrontendMetric("current_sessions", "Current number of active sessions.", nil), 5: newFrontendMetric("max_sessions", "Maximum number of active sessions.", nil), 7: newFrontendMetric("connections_total", "Total number of connections.", nil), 8: newFrontendMetric("bytes_in_total", "Current total of incoming bytes.", nil), 9: newFrontendMetric("bytes_out_total", "Current total of outgoing bytes.", nil), 10: newFrontendMetric("requests_denied_total", "Total of requests denied for security.", nil), 12: newFrontendMetric("request_errors_total", "Total of request errors.", nil), 33: newFrontendMetric("current_session_rate", "Current number of sessions per second over last elapsed second.", nil), 35: newFrontendMetric("max_session_rate", "Maximum number of sessions per second.", nil), 39: newFrontendMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "1xx"}), 40: newFrontendMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "2xx"}), 41: newFrontendMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "3xx"}), 42: newFrontendMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "4xx"}), 43: newFrontendMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "5xx"}), 44: newFrontendMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "other"}), 48: newFrontendMetric("http_requests_total", "Total HTTP requests.", nil), }, backendMetrics: map[int]*prometheus.GaugeVec{ 2: newBackendMetric("current_queue", "Current server queue length.", nil), 3: newBackendMetric("max_queue", "Maximum server queue length.", nil), 4: newBackendMetric("current_sessions", "Current number of active sessions.", nil), 5: newBackendMetric("max_sessions", "Maximum number of active sessions.", nil), 7: newBackendMetric("connections_total", "Total number of connections.", nil), 8: newBackendMetric("bytes_in_total", "Current total of incoming bytes.", nil), 9: newBackendMetric("bytes_out_total", "Current total of outgoing bytes.", nil), 13: newBackendMetric("connection_errors_total", "Total of connection errors.", nil), 14: newBackendMetric("response_errors_total", "Total of response errors.", nil), 15: newBackendMetric("retry_warnings_total", "Total of retry warnings.", nil), 16: newBackendMetric("redispatch_warnings_total", "Total of redispatch warnings.", nil), 17: newBackendMetric("up", "Current health status of the backend (1 = UP, 0 = DOWN).", nil), 18: newBackendMetric("weight", "Total weight of the servers in the backend.", nil), 33: newBackendMetric("current_session_rate", "Current number of sessions per second over last elapsed second.", nil), 35: newBackendMetric("max_session_rate", "Maximum number of sessions per second.", nil), 39: newBackendMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "1xx"}), 40: newBackendMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "2xx"}), 41: newBackendMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "3xx"}), 42: newBackendMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "4xx"}), 43: newBackendMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "5xx"}), 44: newBackendMetric("http_responses_total", "Total of HTTP responses.", prometheus.Labels{"code": "other"}), }, serverMetrics: serverMetrics, client: &http.Client{ Transport: &http.Transport{ Dial: func(netw, addr string) (net.Conn, error) { c, err := net.DialTimeout(netw, addr, timeout) if err != nil { return nil, err } if err := c.SetDeadline(time.Now().Add(timeout)); err != nil { return nil, err } return c, nil }, }, }, } }
func main() { flag.Parse() http.Handle(*metricsPath, prometheus.Handler()) c := newGraphiteCollector() prometheus.MustRegister(c) c.mapper = &metricMapper{} if *mappingConfig != "" { err := c.mapper.initFromFile(*mappingConfig) if err != nil { log.Fatalf("Error loading metric mapping config: %s", err) } } tcpSock, err := net.Listen("tcp", *graphiteAddress) if err != nil { log.Fatalf("Error binding to TCP socket: %s", err) } go func() { for { conn, err := tcpSock.Accept() if err != nil { log.Errorf("Error accepting TCP connection: %s", err) continue } go func() { defer conn.Close() c.processReader(conn) }() } }() udpAddress, err := net.ResolveUDPAddr("udp", *graphiteAddress) if err != nil { log.Fatalf("Error resolving UDP address: %s", err) } udpSock, err := net.ListenUDP("udp", udpAddress) if err != nil { log.Fatalf("Error listening to UDP address: %s", err) } go func() { defer udpSock.Close() for { buf := make([]byte, 65536) chars, srcAddress, err := udpSock.ReadFromUDP(buf) if err != nil { log.Errorf("Error reading UDP packet from %s: %s", srcAddress, err) continue } go c.processReader(bytes.NewReader(buf[0:chars])) } }() http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<html> <head><title>Graphite Exporter</title></head> <body> <h1>Graphite Exporter</h1> <p>Accepting plaintext Graphite samples over TCP and UDP on ` + *graphiteAddress + `</p> <p><a href="` + *metricsPath + `">Metrics</a></p> </body> </html>`)) }) http.ListenAndServe(*listeningAddress, nil) }