-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace --collectors.enabled with per-collector flags #640
Changes from 12 commits
760da42
4bb0f09
a237740
b771eb4
f6a3147
ef41b18
b78eba7
a5d7a14
0dada5b
dea9a7b
f8dc13a
7147b30
a55f065
ec50ff5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,20 +15,120 @@ | |
package collector | ||
|
||
import ( | ||
"fmt" | ||
"sync" | ||
"time" | ||
|
||
"github.com/prometheus/client_golang/prometheus" | ||
"github.com/prometheus/common/log" | ||
"gopkg.in/alecthomas/kingpin.v2" | ||
) | ||
|
||
// Namespace defines the common namespace to be used by all metrics. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be lowercase |
||
const Namespace = "node" | ||
const namespace = "node" | ||
|
||
// Factories contains the list of all available collectors. | ||
var Factories = make(map[string]func() (Collector, error)) | ||
|
||
var ( | ||
scrapeDurationDesc = prometheus.NewDesc( | ||
prometheus.BuildFQName(namespace, "scrape", "collector_duration_seconds"), | ||
"node_exporter: Duration of a collector scrape.", | ||
[]string{"collector"}, | ||
nil, | ||
) | ||
scrapeSuccessDesc = prometheus.NewDesc( | ||
prometheus.BuildFQName(namespace, "scrape", "collector_success"), | ||
"node_exporter: Whether a collector succeeded.", | ||
[]string{"collector"}, | ||
nil, | ||
) | ||
) | ||
|
||
func warnDeprecated(collector string) { | ||
log.Warnf("The %s collector is deprecated and will be removed in the future!", collector) | ||
} | ||
|
||
const ( | ||
defaultEnabled = true | ||
defaultDisabled = false | ||
) | ||
|
||
var collectorState = make(map[string]*bool) | ||
|
||
func registerCollector(collector string, isDefaultEnabled bool, factory func() (Collector, error)) { | ||
var helpDefaultState string | ||
if isDefaultEnabled { | ||
helpDefaultState = "enabled" | ||
} else { | ||
helpDefaultState = "disabled" | ||
} | ||
|
||
flagName := fmt.Sprintf("collector.%s", collector) | ||
flagHelp := fmt.Sprintf("Enable the %s collector (default: %s).", collector, helpDefaultState) | ||
defaultValue := fmt.Sprintf("%v", isDefaultEnabled) | ||
|
||
flag := kingpin.Flag(flagName, flagHelp).Default(defaultValue).Bool() | ||
collectorState[collector] = flag | ||
|
||
Factories[collector] = factory | ||
} | ||
|
||
// NodeCollector implements the prometheus.Collector interface. | ||
type NodeCollector struct { | ||
Collectors map[string]Collector | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NewNodeCollector should have a docstring as it's exported. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, perhaps it shouldn't be exported? Not much point to it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Eh, I meant that the |
||
func NewNodeCollector() (*NodeCollector, error) { | ||
collectors := make(map[string]Collector) | ||
for key, enabled := range collectorState { | ||
if *enabled { | ||
collector, err := Factories[key]() | ||
if err != nil { | ||
return nil, err | ||
} | ||
collectors[key] = collector | ||
} | ||
} | ||
return &NodeCollector{Collectors: collectors}, nil | ||
} | ||
|
||
// Describe implements the prometheus.Collector interface. | ||
func (n NodeCollector) Describe(ch chan<- *prometheus.Desc) { | ||
ch <- scrapeDurationDesc | ||
ch <- scrapeSuccessDesc | ||
} | ||
|
||
// Collect implements the prometheus.Collector interface. | ||
func (n NodeCollector) Collect(ch chan<- prometheus.Metric) { | ||
wg := sync.WaitGroup{} | ||
wg.Add(len(n.Collectors)) | ||
for name, c := range n.Collectors { | ||
go func(name string, c Collector) { | ||
execute(name, c, ch) | ||
wg.Done() | ||
}(name, c) | ||
} | ||
wg.Wait() | ||
} | ||
|
||
func execute(name string, c Collector, ch chan<- prometheus.Metric) { | ||
begin := time.Now() | ||
err := c.Update(ch) | ||
duration := time.Since(begin) | ||
var success float64 | ||
|
||
if err != nil { | ||
log.Errorf("ERROR: %s collector failed after %fs: %s", name, duration.Seconds(), err) | ||
success = 0 | ||
} else { | ||
log.Debugf("OK: %s collector succeeded after %fs.", name, duration.Seconds()) | ||
success = 1 | ||
} | ||
ch <- prometheus.MustNewConstMetric(scrapeDurationDesc, prometheus.GaugeValue, duration.Seconds(), name) | ||
ch <- prometheus.MustNewConstMetric(scrapeSuccessDesc, prometheus.GaugeValue, success, name) | ||
} | ||
|
||
// Collector is the interface a collector has to implement. | ||
type Collector interface { | ||
// Get new metrics and expose them via prometheus registry. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency, this should be
<name>