netstat: Use procfs parsers for netstat, snmp and snmp6 - #3796
Conversation
Replace the hand-written parsers for /proc/net/netstat, /proc/net/snmp and /proc/net/snmp6 with the parsers from prometheus/procfs (Proc.Netstat, Proc.Snmp and Proc.Snmp6). The statistics are read via /proc/self/net, which is equivalent to /proc/net (both are network-namespace local views of the current process), so the collected data is unchanged. Metrics are exposed by iterating the procfs statistics structs, the same approach the NFS collector uses: fields are *float64 and only the ones present on the system are exported, matching the previous behavior. The --collector.netstat.fields flag and the exported metric names are unchanged; the e2e golden output is identical. Signed-off-by: neoLsH <43921685+neoLsH@users.noreply.github.com>
| // emitStruct emits one metric per non-nil field of a procfs netstat/snmp | ||
| // statistics struct, using the struct's type name as the protocol name. | ||
| func (c *netStatCollector) emitStruct(ch chan<- prometheus.Metric, stats any) { |
There was a problem hiding this comment.
When we are converting these collectors we are migrating to explicitly defined metric package var descriptors rather than dynamically generated Descs.
This reduces runtime allocs as well as makes it easier for us to do AST-generated documentation.
|
Thanks — that makes sense on both counts (per-scrape allocs and the AST-based doc generation in #3585). I'll rework the exposure layer accordingly, and I found a precedent I'd like to confirm: Two things worth deciding before I write it, since they change the diff shape: 1. Scale / splitting. The procfs structs expose 301 fields (netstat: TcpExt 113 + IpExt 18; snmp: 79; snmp6: 91), of which the default 2. A metric-contract change I should flag explicitly. Diffing the old dynamic parser's output (using this repo's own fixtures) against the procfs struct fields, 10 metrics disappear: Also: should the help strings stay as today's |
|
For the missing metrics if we're missing fields in procfs, we should update the parser there. I wonder if it would help to do some refactoring of the procfs code to add some helper functions. For example, the We could make this a custom type like This would allow us to embed the original filename string so that we can more easily use it with the regexp matcher. |
What
Replace the hand-written parsers for
/proc/net/netstat,/proc/net/snmpand/proc/net/snmp6with the parsers fromprometheus/procfs(
Proc.Netstat(),Proc.Snmp(),Proc.Snmp6()), as requested in #2336.This is a follow-up to #2360, which was closed as stale. Instead of declaring
one
prometheus.Descper field (~3000 lines), the metrics are exposed byiterating the procfs statistics structs via reflection, the same approach the
NFS collector (
collector/nfs_linux.go) already uses.Details
/proc/net/*is network-namespace local; the procfs parsers operate on/proc/<pid>/net/*, so the collector now reads/proc/self/net/*. On Linux/proc/netis an alias of/proc/self/net, so the collected data andnamespace semantics are unchanged.
*float64(Replace float64 with *float64 for proc_netstat, proc_snmp and proc_snmp6 procfs#464): fields thatare not present on the system are
niland skipped, so — like before — onlystatistics the kernel actually provides are exported.
--collector.netstat.fieldsflag and its default are unchanged, as arethe metric names, types and help strings.
proc.Snmp6()already tolerates amissing
snmp6file on systems with IPv6 disabled.(
collector/fixtures/e2e-output.txt) required no changes.Test fixtures
procfs.FS.Self()resolves theproc/selfsymlink in the fixtures (pid 10),so
collector/fixtures/proc/10/netwas added as a symlink to../net,mirroring the kernel layout where
/proc/<pid>/netis a per-netns symlink.Verification
go test ./collector/(includes a newTestNetStatscomparing the fullexposition against the expected 41 metrics via
testutil.CollectAndCompare)./end-to-end-test.sh(golden output unchanged)Fixes #2336