From 04380ae60a0067d87029a7974ecffab64bececd1 Mon Sep 17 00:00:00 2001 From: Johannes 'fish' Ziemke Date: Fri, 7 Feb 2014 17:09:39 +0100 Subject: [PATCH] Add support for selecting collectors at buildtime This works by using a global array with references to NewXCollector functions. Each collector appends to that array in it's init() function. Which file gets build depends on the build tags: To build only the ganglia exporter, you can do: go build -tags nonative,ganglia By default it will build only the native collector. --- README.md | 33 ++++++++++++++++++++++++++++++--- exporter/exporter.go | 32 +++++++++++--------------------- exporter/gmond_collector.go | 12 +++++++++--- exporter/native_collector.go | 18 ++++++++++++------ exporter/runit_collector.go | 10 ++++++++-- node_exporter.conf | 5 ----- node_exporter.go | 7 ++++++- 7 files changed, 76 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 26080a30..3a6abc62 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,31 @@ -node_exporter -============= +# node_exporter + +Prometheus exporter with plugable metric collectors. + + + +## Available collectors + +By default it will only include the NativeCollector. + +To include other collectors, specify the build tags accordently. + + +### NativeCollector + +Provides metrics for load, seconds since last login and a list of tags +read from `node_exporter.conf`. + +To disable the native collector, use build tag `nonative`. + + +### GmondCollector + +Talks to a local gmond and provide it's metrics. + + +### RunitCollector + +Provides metrics for each runit services like state and how long it +has been in that state. -Simple exporter, exposing load, seconds since last login and a list of tags for the node it's running on. \ No newline at end of file diff --git a/exporter/exporter.go b/exporter/exporter.go index 7c347461..2e0c4756 100644 --- a/exporter/exporter.go +++ b/exporter/exporter.go @@ -1,4 +1,4 @@ -// Exporter is a prometheus exporter using multiple collectors to collect and export system metrics. +// Exporter is a prometheus exporter using multiple collectorFactories to collect and export system metrics. package exporter import ( @@ -19,6 +19,7 @@ import ( ) var verbose = flag.Bool("verbose", false, "Verbose output.") +var collectorFactories []func(config, prometheus.Registry) (Collector, error) // Interface a collector has to implement. type Collector interface { @@ -33,7 +34,6 @@ type config struct { Attributes map[string]string `json:"attributes"` ListeningAddress string `json:"listeningAddress"` ScrapeInterval int `json:"scrapeInterval"` - Collectors []string `json:"collectors"` } func (e *exporter) loadConfig() (err error) { @@ -54,7 +54,7 @@ type exporter struct { metricsUpdated prometheus.Gauge config config registry prometheus.Registry - collectors []Collector + Collectors []Collector MemProfile string } @@ -74,24 +74,14 @@ func New(configFile string) (e exporter, err error) { if err != nil { return e, fmt.Errorf("Couldn't read config: %s", err) } - - cn, err := NewNativeCollector(e.config, e.registry) - if err != nil { - log.Fatalf("Couldn't attach collector: %s", err) - } - - cr, err := NewRunitCollector(e.config, e.registry) - if err != nil { - log.Fatalf("Couldn't attach collector: %s", err) - } - - cg, err := NewGmondCollector(e.config, e.registry) - if err != nil { - log.Fatalf("Couldn't attach collector: %s", err) + for _, fn := range collectorFactories { + c, err := fn(e.config, e.registry) + if err != nil { + return e, err + } + e.Collectors = append(e.Collectors, c) } - e.collectors = []Collector{&cn, &cr, &cg} - if e.config.ListeningAddress != "" { e.listeningAddress = e.config.ListeningAddress } @@ -152,8 +142,8 @@ func (e *exporter) Loop() { case <-tick: log.Printf("Starting new scrape interval") wg := sync.WaitGroup{} - wg.Add(len(e.collectors)) - for _, c := range e.collectors { + wg.Add(len(e.Collectors)) + for _, c := range e.Collectors { go func(c Collector) { e.Execute(c) wg.Done() diff --git a/exporter/gmond_collector.go b/exporter/gmond_collector.go index e6c1fe4b..eef5a377 100644 --- a/exporter/gmond_collector.go +++ b/exporter/gmond_collector.go @@ -1,3 +1,5 @@ +// +build ganglia + package exporter import ( @@ -25,18 +27,22 @@ type gmondCollector struct { registry prometheus.Registry } +func init() { + collectors = append(collectors, NewGmondCollector) +} + var illegalCharsRE = regexp.MustCompile(`[^a-zA-Z0-9_]`) // Takes a config struct and prometheus registry and returns a new Collector scraping ganglia. -func NewGmondCollector(config config, registry prometheus.Registry) (collector gmondCollector, err error) { - collector = gmondCollector{ +func NewGmondCollector(config config, registry prometheus.Registry) (Collector, error) { + c := gmondCollector{ name: "gmond_collector", config: config, Metrics: make(map[string]prometheus.Gauge), registry: registry, } - return collector, nil + return &c, nil } func (c *gmondCollector) Name() string { return c.name } diff --git a/exporter/native_collector.go b/exporter/native_collector.go index cc545ae0..809b0d09 100644 --- a/exporter/native_collector.go +++ b/exporter/native_collector.go @@ -1,3 +1,5 @@ +// +build !nonative + package exporter import ( @@ -24,10 +26,14 @@ type nativeCollector struct { config config } +func init() { + collectorFactories = append(collectorFactories, NewNativeCollector) +} + // Takes a config struct and prometheus registry and returns a new Collector exposing // load, seconds since last login and a list of tags as specified by config. -func NewNativeCollector(config config, registry prometheus.Registry) (collector nativeCollector, err error) { - collector = nativeCollector{ +func NewNativeCollector(config config, registry prometheus.Registry) (Collector, error) { + c := nativeCollector{ name: "native_collector", config: config, loadAvg: prometheus.NewGauge(), @@ -39,24 +45,24 @@ func NewNativeCollector(config config, registry prometheus.Registry) (collector "node_load", "node_exporter: system load.", prometheus.NilLabels, - collector.loadAvg, + c.loadAvg, ) registry.Register( "node_last_login_seconds", "node_exporter: seconds since last login.", prometheus.NilLabels, - collector.lastSeen, + c.lastSeen, ) registry.Register( "node_attributes", "node_exporter: system attributes.", prometheus.NilLabels, - collector.attributes, + c.attributes, ) - return collector, nil + return &c, nil } func (c *nativeCollector) Name() string { return c.name } diff --git a/exporter/runit_collector.go b/exporter/runit_collector.go index c4276514..b0ccea59 100644 --- a/exporter/runit_collector.go +++ b/exporter/runit_collector.go @@ -1,3 +1,5 @@ +// +build runit + package exporter import ( @@ -13,7 +15,11 @@ type runitCollector struct { stateNormal prometheus.Gauge } -func NewRunitCollector(config config, registry prometheus.Registry) (runitCollector, error) { +func init() { + collectors = append(collectors, NewRunitCollector) +} + +func NewRunitCollector(config config, registry prometheus.Registry) (Collector, error) { c := runitCollector{ name: "runit_collector", config: config, @@ -43,7 +49,7 @@ func NewRunitCollector(config config, registry prometheus.Registry) (runitCollec c.stateNormal, ) - return c, nil + return &c, nil } func (c *runitCollector) Name() string { return c.name } diff --git a/node_exporter.conf b/node_exporter.conf index 405712e1..261d76b4 100644 --- a/node_exporter.conf +++ b/node_exporter.conf @@ -1,10 +1,5 @@ { "scrapeInterval": 10, - "collectors": [ - "NativeCollector", - "GmondCollector", - "MuninCollector" - ], "attributes" : { "web-server" : "1", "zone" : "a", diff --git a/node_exporter.go b/node_exporter.go index 20d4fdd1..3d14e703 100644 --- a/node_exporter.go +++ b/node_exporter.go @@ -2,8 +2,9 @@ package main import ( "flag" - "github.com/prometheus/node_exporter/exporter" "log" + + "github.com/prometheus/node_exporter/exporter" ) var ( @@ -18,5 +19,9 @@ func main() { if err != nil { log.Fatalf("Couldn't instantiate exporter: %s", err) } + log.Printf("Registered collectors:") + for _, c := range exporter.Collectors { + log.Print(" - ", c.Name()) + } exporter.Loop() }