Skip to content

Commit

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

Signed-off-by: Siavash Safi <git@hosted.run>
  • Loading branch information
siavashs committed Sep 13, 2024
1 parent 0909576 commit 82aa649
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 `exclude[]` 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 exclude `netdev`:
```
params:
exclude[]:
- 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/promslog"
Expand All @@ -37,6 +38,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 @@ -73,16 +77,39 @@ func newHandler(includeExporterMetrics bool, maxRequests int, logger *slog.Logge

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

if len(filters) == 0 {
excludes := r.URL.Query()["exclude[]"]
h.logger.Debug("exclude query:", "excludes", excludes)

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

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

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

// To serve filtered metrics, we create a filtering handler on the fly.
filteredHandler, err := h.innerHandler(filters...)
filteredHandler, err := h.innerHandler(*filters...)
if err != nil {
h.logger.Warn("Couldn't create filtered metrics handler:", "err", err)
w.WriteHeader(http.StatusBadRequest)
Expand All @@ -107,12 +134,11 @@ func (h *handler) innerHandler(filters ...string) (http.Handler, error) {
// only once upon startup.
if len(filters) == 0 {
h.logger.Info("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 {
h.logger.Info(c)
}
}
Expand Down

0 comments on commit 82aa649

Please sign in to comment.