Skip to content

Commit

Permalink
Add discard[] parameter
Browse files Browse the repository at this point in the history
This PR adds a `discard[]` URL parameter to discard specific enabled collectors.
Compared to `collect[]` parameter, the `discard[]` parameter results in a filtered list which equals enabled collectors minus discarded ones.

A small fix is applied to filtering related debug logs to print the actual slices instead of `unsupported value type`.

Signed-off-by: Siavash Safi <git@hosted.run>
  • Loading branch information
siavashs committed Sep 9, 2024
1 parent b9d0932 commit 7fc81ff
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 11 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,13 +339,21 @@ mv /path/to/directory/role.prom.$$ /path/to/directory/role.prom

The `node_exporter` will expose all metrics from enabled collectors by default. This is the recommended way to collect metrics to avoid errors when comparing metrics of different families.

For advanced use the `node_exporter` can be passed an optional list of collectors to filter metrics. The `collect[]` parameter may be used multiple times. In Prometheus configuration you can use this syntax under the [scrape config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#<scrape_config>).
For advanced use the `node_exporter` can be passed an optional list of collectors to filter metrics. The parameters `collect[]` and `discard[]` can be used multiple times (but cannot be combined). In Prometheus configuration you can use this syntax under the [scrape config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#<scrape_config>).

Collect only `cpu` and `meminfo` collector metrics:
```
params:
collect[]:
- foo
- bar
- cpu
- meminfo
```

Collect all enabled collector metrics but discard `netdev`:
```
params:
discard[]:
- netdev
```

This can be useful for having different Prometheus servers collect specific metrics from nodes.
Expand Down
42 changes: 34 additions & 8 deletions node_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"os"
"os/user"
"runtime"
"slices"
"sort"

"github.com/prometheus/common/promlog"
Expand All @@ -39,6 +40,9 @@ import (
"github.com/prometheus/node_exporter/collector"
)

// list of enabled collectors used for logging and filtering.
var enabledCollectors []string

// handler wraps an unfiltered http.Handler but uses a filtered handler,
// created on the fly, if filtering is requested. Create instances with
// newHandler.
Expand Down Expand Up @@ -75,16 +79,39 @@ func newHandler(includeExporterMetrics bool, maxRequests int, logger log.Logger)

// ServeHTTP implements http.Handler.
func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
filters := r.URL.Query()["collect[]"]
level.Debug(h.logger).Log("msg", "collect query:", "filters", filters)
collects := r.URL.Query()["collect[]"]
level.Debug(h.logger).Log("msg", "collect query:", "collects", fmt.Sprintf("%v", collects))

if len(filters) == 0 {
discards := r.URL.Query()["discard[]"]
level.Debug(h.logger).Log("msg", "discard query:", "discards", fmt.Sprintf("%v", discards))

if len(collects) == 0 && len(discards) == 0 {
// No filters, use the prepared unfiltered handler.
h.unfilteredHandler.ServeHTTP(w, r)
return
}

if len(collects) > 0 && len(discards) > 0 {
level.Debug(h.logger).Log("msg", "rejecting combined collect and discard queries")
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Combined collect and discard queries are not allowed."))
return
}

fileters := &collects
if len(discards) > 0 {
// In discard mode, filtered collectors = enabled - discarded.
f := []string{}
for _, c := range enabledCollectors {
if (slices.Index(discards, c)) == -1 {
f = append(f, c)
}
}
fileters = &f
}

// To serve filtered metrics, we create a filtering handler on the fly.
filteredHandler, err := h.innerHandler(filters...)
filteredHandler, err := h.innerHandler(*fileters...)
if err != nil {
level.Warn(h.logger).Log("msg", "Couldn't create filtered metrics handler:", "err", err)
w.WriteHeader(http.StatusBadRequest)
Expand All @@ -109,12 +136,11 @@ func (h *handler) innerHandler(filters ...string) (http.Handler, error) {
// only once upon startup.
if len(filters) == 0 {
level.Info(h.logger).Log("msg", "Enabled collectors")
collectors := []string{}
for n := range nc.Collectors {
collectors = append(collectors, n)
enabledCollectors = append(enabledCollectors, n)
}
sort.Strings(collectors)
for _, c := range collectors {
sort.Strings(enabledCollectors)
for _, c := range enabledCollectors {
level.Info(h.logger).Log("collector", c)
}
}
Expand Down

0 comments on commit 7fc81ff

Please sign in to comment.