Consolidate collector selection

Remove special tags necessary for gmond and runit collectors. All
collectors get built. Selection of which collectors to use continues to
happen via parameter.
This commit is contained in:
Tobias Schmidt 2014-11-24 17:15:13 -05:00
parent 600a529e09
commit 211ddf33f1
6 changed files with 64 additions and 87 deletions

View file

@ -2,33 +2,7 @@
Prometheus exporter with pluggable metric collectors. Prometheus exporter with pluggable metric collectors.
## collectors
Which collectors are used is controlled by the --enabledCollectors flag. To see
## Available collectors all available collectors, use `--printCollectors`.
By default the build will only include the native collectors
that expose information from /proc.
To include other collectors, specify the build tags lile this:
go build -tags 'ganglia runit' node_exporter.go
Which collectors are used is controlled by the --enabledCollectors flag.
### NativeCollector
Provides metrics for load, seconds since last login and a list of tags
read from `node_exporter.conf`.
### GmondCollector (tag: ganglia)
Talks to a local gmond and provide it's metrics.
### RunitCollector (tag: runit)
Provides metrics for each runit services like state and how long it
has been in that state.

View file

@ -1,4 +1,4 @@
// +build ganglia // +build !nogmond
package collector package collector
@ -24,7 +24,7 @@ const (
) )
type gmondCollector struct { type gmondCollector struct {
Metrics map[string]*prometheus.GaugeVec metrics map[string]*prometheus.GaugeVec
config Config config Config
} }
@ -38,41 +38,12 @@ var illegalCharsRE = regexp.MustCompile(`[^a-zA-Z0-9_]`)
func NewGmondCollector(config Config) (Collector, error) { func NewGmondCollector(config Config) (Collector, error) {
c := gmondCollector{ c := gmondCollector{
config: config, config: config,
Metrics: map[string]*prometheus.GaugeVec{}, metrics: map[string]*prometheus.GaugeVec{},
} }
return &c, nil return &c, nil
} }
func (c *gmondCollector) setMetric(name, cluster string, metric ganglia.Metric) {
if _, ok := c.Metrics[name]; !ok {
var desc string
var title string
for _, element := range metric.ExtraData.ExtraElements {
switch element.Name {
case "DESC":
desc = element.Val
case "TITLE":
title = element.Val
}
if title != "" && desc != "" {
break
}
}
glog.V(1).Infof("Register %s: %s", name, desc)
gv := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: gangliaMetricsPrefix,
Name: name,
Help: desc,
},
[]string{"cluster"},
)
}
glog.V(1).Infof("Set %s{cluster=%q}: %f", name, cluster, metric.Value)
c.Metrics[name].WithLabelValues(cluster).Set(metric.Value)
}
func (c *gmondCollector) Update(ch chan<- prometheus.Metric) (err error) { func (c *gmondCollector) Update(ch chan<- prometheus.Metric) (err error) {
conn, err := net.Dial(gangliaProto, gangliaAddress) conn, err := net.Dial(gangliaProto, gangliaAddress)
glog.V(1).Infof("gmondCollector Update") glog.V(1).Infof("gmondCollector Update")
@ -100,12 +71,41 @@ func (c *gmondCollector) Update(ch chan<- prometheus.Metric) (err error) {
} }
} }
} }
for _, m := range c.Metrics { for _, m := range c.metrics {
m.Collect(ch) m.Collect(ch)
} }
return err return err
} }
func (c *gmondCollector) setMetric(name, cluster string, metric ganglia.Metric) {
if _, ok := c.metrics[name]; !ok {
var desc string
var title string
for _, element := range metric.ExtraData.ExtraElements {
switch element.Name {
case "DESC":
desc = element.Val
case "TITLE":
title = element.Val
}
if title != "" && desc != "" {
break
}
}
glog.V(1).Infof("Register %s: %s", name, desc)
c.metrics[name] = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: gangliaMetricsPrefix,
Name: name,
Help: desc,
},
[]string{"cluster"},
)
}
glog.V(1).Infof("Set %s{cluster=%q}: %f", name, cluster, metric.Value)
c.metrics[name].WithLabelValues(cluster).Set(metric.Value)
}
func toUtf8(charset string, input io.Reader) (io.Reader, error) { func toUtf8(charset string, input io.Reader) (io.Reader, error) {
return input, nil //FIXME return input, nil //FIXME
} }

View file

@ -1,4 +1,4 @@
// +build megacli // +build !nomegacli
package collector package collector

View file

@ -1,4 +1,4 @@
// +build megacli // +build !nomegacli
package collector package collector

View file

@ -1,4 +1,4 @@
// +build runit // +build !norunit
package collector package collector
@ -8,10 +8,6 @@ import (
"github.com/soundcloud/go-runit/runit" "github.com/soundcloud/go-runit/runit"
) )
const (
runitSubsystem = "runit"
)
type runitCollector struct { type runitCollector struct {
config Config config Config
@ -23,36 +19,43 @@ func init() {
} }
func NewRunitCollector(config Config) (Collector, error) { func NewRunitCollector(config Config) (Collector, error) {
var labels = []string{"service"} var (
subsystem = "service"
constLabels = prometheus.Labels{"supervisor": "runit"}
labelNames = []string{"service"}
)
return &runitCollector{ return &runitCollector{
config: config, config: config,
state: prometheus.NewGaugeVec( state: prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Namespace: Namespace, Namespace: Namespace,
Subsystem: runitSubsystem, Subsystem: subsystem,
Name: "state", Name: "state",
Help: "state of runit service.", Help: "state of runit service.",
ConstLabels: constLabels,
}, },
labels, labelNames,
), ),
stateDesired: prometheus.NewGaugeVec( stateDesired: prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Namespace: Namespace, Namespace: Namespace,
Subsystem: runitSubsystem, Subsystem: subsystem,
Name: "desired_state", Name: "desired_state",
Help: "desired state of runit service.", Help: "desired state of runit service.",
ConstLabels: constLabels,
}, },
labels, labelNames,
), ),
stateNormal: prometheus.NewGaugeVec( stateNormal: prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Namespace: Namespace, Namespace: Namespace,
Subsystem: runitSubsystem, Subsystem: subsystem,
Name: "normal_state", Name: "normal_state",
Help: "normal state of runit service.", Help: "normal state of runit service.",
ConstLabels: constLabels,
}, },
labels, labelNames,
), ),
}, nil }, nil
} }

View file

@ -96,12 +96,12 @@ func loadCollectors(file string) (map[string]collector.Collector, error) {
collectors := map[string]collector.Collector{} collectors := map[string]collector.Collector{}
config, err := getConfig(file) config, err := getConfig(file)
if err != nil { if err != nil {
log.Fatalf("Couldn't read config %s: %s", file, err) return nil, fmt.Errorf("couldn't read config %s: %s", file, err)
} }
for _, name := range strings.Split(*enabledCollectors, ",") { for _, name := range strings.Split(*enabledCollectors, ",") {
fn, ok := collector.Factories[name] fn, ok := collector.Factories[name]
if !ok { if !ok {
log.Fatalf("Collector '%s' not available", name) return nil, fmt.Errorf("collector '%s' not available", name)
} }
c, err := fn(*config) c, err := fn(*config)
if err != nil { if err != nil {