Skip to content

Commit 625ce84

Browse files
committed
collector/mountstats: add mountpoint label for NFS metrics
Signed-off-by: Vedant-Mhatre <vedantmh@gmail.com>
1 parent b5966ca commit 625ce84

File tree

2 files changed

+81
-9
lines changed

2 files changed

+81
-9
lines changed

collector/mountstats_linux.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ type nfsDeviceIdentifier struct {
103103
Device string
104104
Protocol string
105105
MountAddress string
106+
MountPoint string
106107
}
107108

108109
func init() {
@@ -127,9 +128,9 @@ func NewMountStatsCollector(logger *slog.Logger) (Collector, error) {
127128
)
128129

129130
var (
130-
labels = []string{"export", "protocol", "mountaddr"}
131-
opLabels = []string{"export", "protocol", "mountaddr", "operation"}
132-
translabels = []string{"export", "protocol", "mountaddr", "transport"}
131+
labels = []string{"export", "protocol", "mountaddr", "mountpoint"}
132+
opLabels = []string{"export", "protocol", "mountaddr", "mountpoint", "operation"}
133+
translabels = []string{"export", "protocol", "mountaddr", "mountpoint", "transport"}
133134
)
134135

135136
return &mountStatsCollector{
@@ -531,6 +532,7 @@ func (c *mountStatsCollector) Update(ch chan<- prometheus.Metric) error {
531532
continue
532533
}
533534

535+
mountPoint := m.Mount
534536
var mountAddress string
535537
if idx < len(mountsInfo) {
536538
// The mount entry order in the /proc/self/mountstats and /proc/self/mountinfo is the same.
@@ -539,22 +541,22 @@ func (c *mountStatsCollector) Update(ch chan<- prometheus.Metric) error {
539541
}
540542

541543
for k := range stats.Transport {
542-
deviceIdentifier := nfsDeviceIdentifier{m.Device, stats.Transport[k].Protocol, mountAddress}
544+
deviceIdentifier := nfsDeviceIdentifier{m.Device, stats.Transport[k].Protocol, mountAddress, mountPoint}
543545
i := deviceList[deviceIdentifier]
544546
if i {
545547
c.logger.Debug("Skipping duplicate device entry", "device", deviceIdentifier)
546548
break
547549
}
548550
deviceList[deviceIdentifier] = true
549-
c.updateNFSStats(ch, stats, m.Device, stats.Transport[k].Protocol, mountAddress)
551+
c.updateNFSStats(ch, stats, m.Device, stats.Transport[k].Protocol, mountAddress, mountPoint)
550552
}
551553
}
552554

553555
return nil
554556
}
555557

556-
func (c *mountStatsCollector) updateNFSStats(ch chan<- prometheus.Metric, s *procfs.MountStatsNFS, export, protocol, mountAddress string) {
557-
labelValues := []string{export, protocol, mountAddress}
558+
func (c *mountStatsCollector) updateNFSStats(ch chan<- prometheus.Metric, s *procfs.MountStatsNFS, export, protocol, mountAddress, mountPoint string) {
559+
labelValues := []string{export, protocol, mountAddress, mountPoint}
558560
ch <- prometheus.MustNewConstMetric(
559561
c.NFSAgeSecondsTotal,
560562
prometheus.CounterValue,
@@ -619,7 +621,7 @@ func (c *mountStatsCollector) updateNFSStats(ch chan<- prometheus.Metric, s *pro
619621
)
620622

621623
for i := range s.Transport {
622-
translabelValues := []string{export, protocol, mountAddress, strconv.Itoa(i)}
624+
translabelValues := []string{export, protocol, mountAddress, mountPoint, strconv.Itoa(i)}
623625

624626
ch <- prometheus.MustNewConstMetric(
625627
c.NFSTransportBindTotal,
@@ -693,7 +695,7 @@ func (c *mountStatsCollector) updateNFSStats(ch chan<- prometheus.Metric, s *pro
693695
}
694696

695697
for _, op := range s.Operations {
696-
opLabelValues := []string{export, protocol, mountAddress, op.Operation}
698+
opLabelValues := []string{export, protocol, mountAddress, mountPoint, op.Operation}
697699

698700
ch <- prometheus.MustNewConstMetric(
699701
c.NFSOperationsRequestsTotal,

collector/mountstats_linux_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright 2026 The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
//go:build !nomountstats
15+
16+
package collector
17+
18+
import (
19+
"io"
20+
"log/slog"
21+
"strings"
22+
"testing"
23+
24+
"github.com/prometheus/client_golang/prometheus"
25+
"github.com/prometheus/client_golang/prometheus/testutil"
26+
)
27+
28+
type testMountStatsCollector struct {
29+
c Collector
30+
}
31+
32+
func (c testMountStatsCollector) Collect(ch chan<- prometheus.Metric) {
33+
c.c.Update(ch)
34+
}
35+
36+
func (c testMountStatsCollector) Describe(ch chan<- *prometheus.Desc) {
37+
prometheus.DescribeByCollect(c, ch)
38+
}
39+
40+
func NewTestMountStatsCollector(logger *slog.Logger) (prometheus.Collector, error) {
41+
c, err := NewMountStatsCollector(logger)
42+
if err != nil {
43+
return testMountStatsCollector{}, err
44+
}
45+
return testMountStatsCollector{c: c}, nil
46+
}
47+
48+
func TestMountStatsMountPointLabel(t *testing.T) {
49+
*procPath = "fixtures/proc"
50+
51+
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
52+
c, err := NewTestMountStatsCollector(logger)
53+
if err != nil {
54+
t.Fatal(err)
55+
}
56+
57+
reg := prometheus.NewPedanticRegistry()
58+
reg.MustRegister(c)
59+
60+
expected := `# HELP node_mountstats_nfs_age_seconds_total The age of the NFS mount in seconds.
61+
# TYPE node_mountstats_nfs_age_seconds_total counter
62+
node_mountstats_nfs_age_seconds_total{export="192.168.1.1:/srv/test",mountaddr="192.168.1.1",mountpoint="/mnt/nfs/test",protocol="tcp"} 13968
63+
node_mountstats_nfs_age_seconds_total{export="192.168.1.1:/srv/test",mountaddr="192.168.1.1",mountpoint="/mnt/nfs/test-dupe",protocol="tcp"} 13968
64+
node_mountstats_nfs_age_seconds_total{export="192.168.1.1:/srv/test",mountaddr="192.168.1.1",mountpoint="/mnt/nfs/test-dupe",protocol="udp"} 13968
65+
`
66+
67+
if err := testutil.GatherAndCompare(reg, strings.NewReader(expected), "node_mountstats_nfs_age_seconds_total"); err != nil {
68+
t.Fatal(err)
69+
}
70+
}

0 commit comments

Comments
 (0)