PMM-15362 Disable default-on node_exporter collectors - #5839
Conversation
Disabling a node_exporter collector that node_exporter enables by default had no effect: PMM removed its own --collector.<name> flag but never added --no-collector.<name>, so the collector kept running and exporting. Non-default collectors were unaffected, because dropping their enable flag falls back to node_exporter's default of off. Emit --no-collector.<name> for the default-on collectors PMM enables, following the pattern already used for the postgres and mongodb exporters. The list is a whitelist of collectors PMM already passes --collector.<name> for, so a name the bundled node_exporter does not know can never reach the command line - an unknown flag stops the exporter from starting. Collapse repeated names in DisableDefaultEnabledCollectors, since a flag repeated on the command line is rejected by the exporters' flag parser, and trim the values passed by "inventory change agent node-exporter" the way the add path already does. Signed-off-by: theTibi <tkorocz@gmail.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5839 +/- ##
==========================================
+ Coverage 43.59% 44.01% +0.41%
==========================================
Files 415 302 -113
Lines 43134 32883 -10251
==========================================
- Hits 18804 14473 -4331
+ Misses 22454 16896 -5558
+ Partials 1876 1514 -362 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
🔗 Linked repositories identifiedCodeRabbit considers these linked repositories for cross-repo context during reviews:
Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review. WalkthroughArrr, the change normalizes disabled collector input, removes duplicate disable flags, and applies default collector disabling on non-macOS Node Exporter configurations. ChangesNode Exporter collector configuration
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
pmm-admin inventory change agent node-exporter <id> --disable-collectors=<name>reports success and stores the value, but for any collector node_exporter enables by default (cpu,diskstats,meminfo,filesystem,netdev,stat, …) the metrics keep being exported. Disabling a non-default collector (processes,buddyinfo,meminfo_numa) already worked.nodeExporterConfigonly calledcollectors.FilterOutCollectors("--collector.", …), which strips the redundant enable flag PMM adds. For a collector node_exporter turns on by itself that is a no-op, so it kept running. The sibling exporters already solve this —postgresql.goandmongodb.goboth followFilterOutCollectorswithcollectors.DisableDefaultEnabledCollectors;node.gowas simply missing that second call.--no-collector.<name>for the default-on collectors PMM enables, via the same helper.Why the list is a whitelist, and deliberately not "every default-on collector"
An unknown
--no-collector.<name>makes node_exporter exit at startup, which would take all metrics for that host — far worse than the bug. SodefaultNodeExporterCollectorscontains only collectorsnodeExporterConfigalready passes--collector.<name>for. That is self-proving: if the positive flag is already accepted by every agent we drive today, the negation is too. No version gate is needed, unlikepostgresql.go, whose collectors are not passed positively.oswas considered and excluded: it is default-on and does appear in PMM's LRcollect[]list, but the collector only exists from node_exporter 1.3.0 (CHANGELOG.md, 2021-10-20) while this code still builds configs for agentVersion 2.15.1 — an unprovable risk with total-metric-loss failure mode, for ~2 series VictoriaMetrics already stops ingesting.Two related fixes in the same blast radius
DisableDefaultEnabledCollectorsnow collapses repeated names. Without it,--disable-collectors=cpu,cpuproduces two--no-collector.cpuargs and node_exporter refuses to start (flag 'collector.cpu' cannot be repeated) — verified live, see below. This also protects the mongodb and postgres call sites.inventory change agent node-exporternow runs--disable-collectorsthroughcommands.ParseDisableCollectors, as theaddpath already does. Previously--disable-collectors="cpu, meminfo"stored" meminfo"untrimmed, matching nothing — the ticket's "accepted but does nothing" symptom via the ticket's own command. The reported change now shows the parsed value instead of the raw one.Ticket
Test plan
Unit:
go test ./managed/services/agents/ -run TestNodeExporterConfig—LinuxDisabledCollectorsfails on the base commit with exactly the 5 missing--no-collector.*flags, passes here. New subtests:LinuxDisabledCollectorsNotDefaultEnabled,LinuxAllDefaultCollectorsDisabled(also pins that every entry has a matching--collector.<name>, and that none collides with the static--no-collector.*block),MacOSDisabledCollectors.go test ./managed/utils/collectors/...— new duplicate-input case.go test ./admin/commands/...— newDisableCollectorsAreTrimmedcase; fails against the pre-fix file.make init+bin/golangci-lint run --new-from-rev=origin/main→ 0 issues;gofumpt/goimports/gciclean;go-sumtypeclean;check-license0 invalid;go build ./...clean.Live, on an isolated PMM 3.10.0 server whose stock
pmm-managedis built from this PR's base commit, with a registered pmm-agent (node_exporter 1.8.2) — only thepmm-managed/pmm-adminbinaries swapped:node_disk_= 324; run the ticket's command; API stores["diskstats"];--collector.diskstatsgone, no--no-collector.diskstats;node_disk_= 324. Bug reproduced end to end.--no-collector.diskstatspresent on the real exporter cmdline;node_disk_= 0;node_cpu_seconds_total= 88 unchanged.--disable-collectors=diskstats,diskstats,cpu,diskstats— exactly one flag each, exporterRunning, both families 0.Done, agent log repeatingnode_exporter: error: flag 'collector.diskstats' cannot be repeated, listen port walking 42000→42025. The dedupe is load-bearing.--disable-collectors="cpu, meminfo"stores['cpu','meminfo'], both--no-collector.*flags present, both families 0.node_disk_back to 324.--disable-collectors=processes: enable flag removed, no--no-collector.processesadded,node_processes_= 0,node_disk_still 324.percona/pmm-client:2) and 1.8.2 (percona/pmm-client:3); a bogus name is correctly rejected on both, confirming the check discriminates.Not covered: darwin (no macOS node — unit + mutation test only); VictoriaMetrics/Grafana ingestion; a live matrix of older agents (1.4.0 exercised as a standalone binary only).
Known residuals, deliberately out of scope
pressure,schedstat,softnet,os,dmi,udp_queues,nvme,btrfs,cpufreq,selinux,thermal_zone,watchdog,rapl,fibrechannel,powersupplyclass,tapestats,textfile) remain silent no-ops for--disable-collectors. Onlyosis scraped by PMM; the rest never reach VictoriaMetrics, so the cost is host-side CPU. Handling them safely needs per-collector version gating.collect[]=<name>makes node_exporter answer HTTP 400 for the whole scrape job (~1–2 HR scrapes; none in push mode). This is pre-existing, not introduced here: verified live that on the base commit--disable-collectors=processesproduces the identical400 disabled collector: processes, becauseFilterOutCollectorsdisables the collector while the scrape config still names it. Worth knowing so the 400 in an exporter log is not mistaken for a new bug.change agentcommands (mysqld, mongodb, postgres, proxysql, valkey) still pass--disable-collectorsuntrimmed — PMM-14919's scope.Note for the release note
Because
collect[]is an exclusive filter and the scrape config already drops a disabled collector, the metrics had already stopped reaching Grafana before this fix. The real gains are that the collector stops executing on the monitored host, a direct/metricsscrape no longer exposes it, and the empty-collect[]fallback no longer resurrects it.🤖 Generated with Claude Code