From 8430129413de83d15cea5745c26795f7b22a4753 Mon Sep 17 00:00:00 2001 From: Dean Chen <862469039@qq.com> Date: Wed, 22 Jul 2026 15:42:50 +0500 Subject: [PATCH] nfsd: ignore unknown metric lines instead of failing New kernel versions can add lines to /proc/net/rpc/nfsd (for example wdeleg_getattr on Linux 6.6+). Treating an unknown key as a hard error makes ParseServerRPCStats return nothing, so consumers such as node_exporter drop all NFSd metrics for one new field. Skip unknown keys and keep returning the metrics we already understand. Known keys (including wdeleg_getattr) are still parsed as before. Related to prometheus/node_exporter#2799 Signed-off-by: Dean Chen <862469039@qq.com> --- nfs/parse_nfsd.go | 5 ++++- nfs/parse_nfsd_test.go | 51 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/nfs/parse_nfsd.go b/nfs/parse_nfsd.go index 34125a06..dce25901 100644 --- a/nfs/parse_nfsd.go +++ b/nfs/parse_nfsd.go @@ -76,7 +76,10 @@ func ParseServerRPCStats(r io.Reader) (*ServerRPCStats, error) { case "wdeleg_getattr": stats.WdelegGetattr = values[0] default: - return nil, fmt.Errorf("unknown NFSd metric line %q", metricLine) + // Ignore unknown metric lines. New kernel versions may add stats + // (e.g. wdeleg_getattr on Linux 6.6+); failing the whole parse + // would drop all NFSd metrics from consumers such as node_exporter. + continue } if err != nil { return nil, fmt.Errorf("errors parsing NFSd metric line: %w", err) diff --git a/nfs/parse_nfsd_test.go b/nfs/parse_nfsd_test.go index 2dc9e37f..218e125f 100644 --- a/nfs/parse_nfsd_test.go +++ b/nfs/parse_nfsd_test.go @@ -616,6 +616,57 @@ wdeleg_getattr 765432`, }, WdelegGetattr: 765432, }, + }, { + name: "unknown metric line is ignored", + content: `rc 1 2 3 +fh 0 0 0 0 0 +io 10 20 +th 8 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 +ra 32 0 0 0 0 0 0 0 0 0 0 0 +net 1 0 1 0 +rpc 1 0 0 0 0 +proc2 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +proc3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +proc4 2 0 0 +proc4ops 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +wdeleg_getattr 7 +future_kernel_stat 42 +`, + stats: &nfs.ServerRPCStats{ + ReplyCache: nfs.ReplyCache{ + Hits: 1, + Misses: 2, + NoCache: 3, + }, + FileHandles: nfs.FileHandles{}, + InputOutput: nfs.InputOutput{ + Read: 10, + Write: 20, + }, + Threads: nfs.Threads{ + Threads: 8, + FullCnt: 0, + }, + ReadAheadCache: nfs.ReadAheadCache{ + CacheSize: 32, + CacheHistogram: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + NotFound: 0, + }, + Network: nfs.Network{ + NetCount: 1, + UDPCount: 0, + TCPCount: 1, + TCPConnect: 0, + }, + ServerRPC: nfs.ServerRPC{ + RPCCount: 1, + }, + V2Stats: nfs.V2Stats{}, + V3Stats: nfs.V3Stats{}, + ServerV4Stats: nfs.ServerV4Stats{}, + V4Ops: nfs.V4Ops{}, + WdelegGetattr: 7, + }, }, }