From cbd350a3814a3d8cfe7c3fe2a627add90b8a7cee Mon Sep 17 00:00:00 2001 From: Johannes 'fish' Ziemke Date: Wed, 24 Jul 2013 14:15:40 +0200 Subject: [PATCH] Remove munin exporter The exporter was never fully working and it turns out the protocol is much harder to support than thought. Since we're not depending on munin anyway, I've dropped it. --- exporter/exporter.go | 7 +- exporter/munin_collector.go | 236 ------------------------------------ 2 files changed, 1 insertion(+), 242 deletions(-) delete mode 100644 exporter/munin_collector.go diff --git a/exporter/exporter.go b/exporter/exporter.go index 72de61ef..6c3f4292 100644 --- a/exporter/exporter.go +++ b/exporter/exporter.go @@ -85,12 +85,7 @@ func New(configFile string) (e exporter, err error) { log.Fatalf("Couldn't attach collector: %s", err) } - cm, err := NewMuninCollector(e.config, e.registry) - if err != nil { - log.Fatalf("Couldn't attach collector: %s", err) - } - - e.collectors = []Collector{&cn, &cg, &cm} + e.collectors = []Collector{&cn, &cg} if e.config.ListeningAddress != "" { e.listeningAddress = e.config.ListeningAddress diff --git a/exporter/munin_collector.go b/exporter/munin_collector.go deleted file mode 100644 index c3ea1edf..00000000 --- a/exporter/munin_collector.go +++ /dev/null @@ -1,236 +0,0 @@ -package exporter - -import ( - "bufio" - "fmt" - "github.com/prometheus/client_golang/prometheus" - "io" - "net" - "regexp" - "strconv" - "strings" -) - -const ( - muninAddress = "127.0.0.1:4949" - muninProto = "tcp" -) - -var muninBanner = regexp.MustCompile(`# munin node at (.*)`) - -type muninCollector struct { - name string - hostname string - graphs []string - gaugePerMetric map[string]prometheus.Gauge - config config - registry prometheus.Registry - connection net.Conn -} - -// Takes a config struct and prometheus registry and returns a new Collector scraping munin. -func NewMuninCollector(config config, registry prometheus.Registry) (c muninCollector, err error) { - c = muninCollector{ - name: "munin_collector", - config: config, - registry: registry, - gaugePerMetric: make(map[string]prometheus.Gauge), - } - - return c, err -} - -func (c *muninCollector) Name() string { return c.name } - -func (c *muninCollector) connect() (err error) { - c.connection, err = net.Dial(muninProto, muninAddress) - if err != nil { - return err - } - debug(c.Name(), "Connected.") - - reader := bufio.NewReader(c.connection) - head, err := reader.ReadString('\n') - if err != nil { - return err - } - - matches := muninBanner.FindStringSubmatch(head) - if len(matches) != 2 { // expect: # munin node at - return fmt.Errorf("Unexpected line: %s", head) - } - c.hostname = matches[1] - debug(c.Name(), "Found hostname: %s", c.hostname) - return err -} - -func (c *muninCollector) muninCommand(cmd string) (reader *bufio.Reader, err error) { - if c.connection == nil { - err := c.connect() - if err != nil { - return reader, fmt.Errorf("Couldn't connect to munin: %s", err) - } - } - reader = bufio.NewReader(c.connection) - - fmt.Fprintf(c.connection, cmd+"\n") - - _, err = reader.Peek(1) - switch err { - case io.EOF: - debug(c.Name(), "not connected anymore, closing connection and reconnect.") - c.connection.Close() - err = c.connect() - if err != nil { - return reader, fmt.Errorf("Couldn't connect to %s: %s", muninAddress) - } - return c.muninCommand(cmd) - case nil: //no error - break - default: - return reader, fmt.Errorf("Unexpected error: %s", err) - } - - return reader, err -} - -func (c *muninCollector) muninList() (items []string, err error) { - munin, err := c.muninCommand("list") - if err != nil { - return items, fmt.Errorf("Couldn't get list: %s", err) - } - - response, err := munin.ReadString('\n') // we are only interested in the first line - if err != nil { - return items, fmt.Errorf("Couldn't read response: %s", err) - } - - if response[0] == '#' { // # not expected here - return items, fmt.Errorf("Error getting items: %s", response) - } - items = strings.Fields(strings.TrimRight(response, "\n")) - return items, err -} - -func (c *muninCollector) muninConfig(name string) (config map[string]map[string]string, graphConfig map[string]string, err error) { - graphConfig = make(map[string]string) - config = make(map[string]map[string]string) - - resp, err := c.muninCommand("config " + name) - if err != nil { - return config, graphConfig, fmt.Errorf("Couldn't get config for %s: %s", name, err) - } - - for { - line, err := resp.ReadString('\n') - if err == io.EOF { - debug(c.Name(), "EOF, retrying") - return c.muninConfig(name) - } - if err != nil { - return nil, nil, err - } - if line == ".\n" { // munin end marker - break - } - if line[0] == '#' { // here it's just a comment, so ignore it - continue - } - parts := strings.Fields(line) - if len(parts) < 2 { - return nil, nil, fmt.Errorf("Line unexpected: %s", line) - } - key, value := parts[0], strings.TrimRight(strings.Join(parts[1:], " "), "\n") - - key_parts := strings.Split(key, ".") - if len(key_parts) > 1 { // it's a metric config (metric.label etc) - if _, ok := config[key_parts[0]]; !ok { - config[key_parts[0]] = make(map[string]string) - } - config[key_parts[0]][key_parts[1]] = value - } else { - graphConfig[key_parts[0]] = value - } - } - return config, graphConfig, err -} - - -func (c *muninCollector) registerMetric(name string) (err error) { - configs, graphConfig, err := c.muninConfig(name) - if err != nil { - return fmt.Errorf("Couldn't get config for graph %s: %s", name, err) - } - - for metric, config := range configs { - metricName := strings.Replace(name+"-"+metric, ".", "_", -1) - desc := graphConfig["graph_title"] + ": " + config["label"] - if config["info"] != "" { - desc = desc + ", " + config["info"] - } - gauge := prometheus.NewGauge() - debug(c.Name(), "Register %s: %s", metricName, desc) - c.gaugePerMetric[metricName] = gauge - c.registry.Register(metricName, desc, prometheus.NilLabels, gauge) - } - return nil -} - - -func (c *muninCollector) Update() (updates int, err error) { - items, err := c.muninList() - if err != nil { - return updates, fmt.Errorf("Couldn't get graph list: %s", err) - } - - for _, name := range items { - c.graphs = append(c.graphs, name) - } - - for _, graph := range c.graphs { - munin, err := c.muninCommand("fetch " + graph) - if err != nil { - return updates, err - } - - for { - line, err := munin.ReadString('\n') - line = strings.TrimRight(line, "\n") - if err == io.EOF { - debug(c.Name(), "unexpected EOF, retrying") - return c.Update() - } - if err != nil { - return updates, err - } - if len(line) == 1 && line[0] == '.' { - break // end of list - } - - parts := strings.Fields(line) - if len(parts) != 2 { - debug(c.Name(), "unexpected line: %s", line) - continue - } - key, value_s := strings.Split(parts[0], ".")[0], parts[1] - name := graph + "-" + key - if _, ok := c.gaugePerMetric[name]; !ok { - if err := c.registerMetric(name); err != nil { - return updates, err - } - } - value, err := strconv.ParseFloat(value_s, 64) - if err != nil { - debug(c.Name(), "Couldn't parse value in line %s, malformed?", line) - continue - } - labels := map[string]string{ - "hostname": c.hostname, - } - debug(c.Name(), "Set %s{%s}: %f\n", name, labels, value) - c.gaugePerMetric[name].Set(labels, value) - updates++ - } - } - return updates, err -}