mirror of
https://github.com/prometheus/node_exporter.git
synced 2024-12-20 23:46:09 +01:00
14a4f0028e
* vendor: Update prometheus/procfs Signed-off-by: Hannes Körber <hannes.koerber@haktec.de> * mountstats: Use new NFS protocol field In https://github.com/prometheus/procfs/pull/100, the NFSTransportStats struct was expanded by a field called protocol that specifies the NFS protocol in use, either "tcp" or "udp". This commit adds the protocol as a label to all NFS metrics exported via the mountstats collector. Signed-off-by: Hannes Körber <hannes.koerber@haktec.de> * Update fixtures for UDP mount Signed-off-by: Hannes Körber <hannes.koerber@haktec.de>
381 lines
11 KiB
Go
381 lines
11 KiB
Go
// Copyright 2018 The Prometheus Authors
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package procfs
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestMountStats(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
s string
|
|
mounts []*Mount
|
|
invalid bool
|
|
}{
|
|
{
|
|
name: "no devices",
|
|
s: `hello`,
|
|
},
|
|
{
|
|
name: "device has too few fields",
|
|
s: `device foo`,
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "device incorrect format",
|
|
s: `device rootfs BAD on / with fstype rootfs`,
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "device incorrect format",
|
|
s: `device rootfs mounted BAD / with fstype rootfs`,
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "device incorrect format",
|
|
s: `device rootfs mounted on / BAD fstype rootfs`,
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "device incorrect format",
|
|
s: `device rootfs mounted on / with BAD rootfs`,
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "device rootfs cannot have stats",
|
|
s: `device rootfs mounted on / with fstype rootfs stats`,
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "NFSv4 device with too little info",
|
|
s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nhello",
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "NFSv4 device with bad bytes",
|
|
s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nbytes: 0",
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "NFSv4 device with bad events",
|
|
s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nevents: 0",
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "NFSv4 device with bad per-op stats",
|
|
s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nper-op statistics\nFOO 0",
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "NFSv4 device with bad transport stats",
|
|
s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nxprt: tcp",
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "NFSv4 device with bad transport version",
|
|
s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=foo\nxprt: tcp 0",
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "NFSv4 device with bad transport stats version 1.0",
|
|
s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.0\nxprt: tcp 0 0 0 0 0 0 0 0 0 0 0 0 0",
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "NFSv4 device with bad transport stats version 1.1",
|
|
s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nxprt: tcp 0 0 0 0 0 0 0 0 0 0",
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "NFSv3 device with bad transport protocol",
|
|
s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nxprt: tcpx 0 0 0 0 0 0 0 0 0 0",
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "NFSv3 device using TCP with transport stats version 1.0 OK",
|
|
s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs statvers=1.0\nxprt: tcp 1 2 3 4 5 6 7 8 9 10",
|
|
mounts: []*Mount{{
|
|
Device: "192.168.1.1:/srv",
|
|
Mount: "/mnt/nfs",
|
|
Type: "nfs",
|
|
Stats: &MountStatsNFS{
|
|
StatVersion: "1.0",
|
|
Transport: NFSTransportStats{
|
|
Protocol: "tcp",
|
|
Port: 1,
|
|
Bind: 2,
|
|
Connect: 3,
|
|
ConnectIdleTime: 4,
|
|
IdleTime: 5 * time.Second,
|
|
Sends: 6,
|
|
Receives: 7,
|
|
BadTransactionIDs: 8,
|
|
CumulativeActiveRequests: 9,
|
|
CumulativeBacklog: 10,
|
|
MaximumRPCSlotsUsed: 0, // these three are not
|
|
CumulativeSendingQueue: 0, // present in statvers=1.0
|
|
CumulativePendingQueue: 0, //
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
{
|
|
name: "NFSv3 device using UDP with transport stats version 1.0 OK",
|
|
s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs statvers=1.0\nxprt: udp 1 2 3 4 5 6 7",
|
|
mounts: []*Mount{{
|
|
Device: "192.168.1.1:/srv",
|
|
Mount: "/mnt/nfs",
|
|
Type: "nfs",
|
|
Stats: &MountStatsNFS{
|
|
StatVersion: "1.0",
|
|
Transport: NFSTransportStats{
|
|
Protocol: "udp",
|
|
Port: 1,
|
|
Bind: 2,
|
|
Connect: 0,
|
|
ConnectIdleTime: 0,
|
|
IdleTime: 0,
|
|
Sends: 3,
|
|
Receives: 4,
|
|
BadTransactionIDs: 5,
|
|
CumulativeActiveRequests: 6,
|
|
CumulativeBacklog: 7,
|
|
MaximumRPCSlotsUsed: 0, // these three are not
|
|
CumulativeSendingQueue: 0, // present in statvers=1.0
|
|
CumulativePendingQueue: 0, //
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
{
|
|
name: "NFSv3 device using TCP with transport stats version 1.1 OK",
|
|
s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs statvers=1.1\nxprt: tcp 1 2 3 4 5 6 7 8 9 10 11 12 13",
|
|
mounts: []*Mount{{
|
|
Device: "192.168.1.1:/srv",
|
|
Mount: "/mnt/nfs",
|
|
Type: "nfs",
|
|
Stats: &MountStatsNFS{
|
|
StatVersion: "1.1",
|
|
Transport: NFSTransportStats{
|
|
Protocol: "tcp",
|
|
Port: 1,
|
|
Bind: 2,
|
|
Connect: 3,
|
|
ConnectIdleTime: 4,
|
|
IdleTime: 5 * time.Second,
|
|
Sends: 6,
|
|
Receives: 7,
|
|
BadTransactionIDs: 8,
|
|
CumulativeActiveRequests: 9,
|
|
CumulativeBacklog: 10,
|
|
MaximumRPCSlotsUsed: 11,
|
|
CumulativeSendingQueue: 12,
|
|
CumulativePendingQueue: 13,
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
{
|
|
name: "NFSv3 device using UDP with transport stats version 1.1 OK",
|
|
s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs statvers=1.1\nxprt: udp 1 2 3 4 5 6 7 8 9 10",
|
|
mounts: []*Mount{{
|
|
Device: "192.168.1.1:/srv",
|
|
Mount: "/mnt/nfs",
|
|
Type: "nfs",
|
|
Stats: &MountStatsNFS{
|
|
StatVersion: "1.1",
|
|
Transport: NFSTransportStats{
|
|
Protocol: "udp",
|
|
Port: 1,
|
|
Bind: 2,
|
|
Connect: 0, // these three are not
|
|
ConnectIdleTime: 0, // present for UDP
|
|
IdleTime: 0, //
|
|
Sends: 3,
|
|
Receives: 4,
|
|
BadTransactionIDs: 5,
|
|
CumulativeActiveRequests: 6,
|
|
CumulativeBacklog: 7,
|
|
MaximumRPCSlotsUsed: 8,
|
|
CumulativeSendingQueue: 9,
|
|
CumulativePendingQueue: 10,
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
{
|
|
name: "device rootfs OK",
|
|
s: `device rootfs mounted on / with fstype rootfs`,
|
|
mounts: []*Mount{{
|
|
Device: "rootfs",
|
|
Mount: "/",
|
|
Type: "rootfs",
|
|
}},
|
|
},
|
|
{
|
|
name: "NFSv3 device with minimal stats OK",
|
|
s: `device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs statvers=1.1`,
|
|
mounts: []*Mount{{
|
|
Device: "192.168.1.1:/srv",
|
|
Mount: "/mnt/nfs",
|
|
Type: "nfs",
|
|
Stats: &MountStatsNFS{
|
|
StatVersion: "1.1",
|
|
},
|
|
}},
|
|
},
|
|
{
|
|
name: "fixtures OK",
|
|
mounts: []*Mount{
|
|
{
|
|
Device: "rootfs",
|
|
Mount: "/",
|
|
Type: "rootfs",
|
|
},
|
|
{
|
|
Device: "sysfs",
|
|
Mount: "/sys",
|
|
Type: "sysfs",
|
|
},
|
|
{
|
|
Device: "proc",
|
|
Mount: "/proc",
|
|
Type: "proc",
|
|
},
|
|
{
|
|
Device: "/dev/sda1",
|
|
Mount: "/",
|
|
Type: "ext4",
|
|
},
|
|
{
|
|
Device: "192.168.1.1:/srv/test",
|
|
Mount: "/mnt/nfs/test",
|
|
Type: "nfs4",
|
|
Stats: &MountStatsNFS{
|
|
StatVersion: "1.1",
|
|
Age: 13968 * time.Second,
|
|
Bytes: NFSBytesStats{
|
|
Read: 1207640230,
|
|
ReadTotal: 1210214218,
|
|
ReadPages: 295483,
|
|
},
|
|
Events: NFSEventsStats{
|
|
InodeRevalidate: 52,
|
|
DnodeRevalidate: 226,
|
|
VFSOpen: 1,
|
|
VFSLookup: 13,
|
|
VFSAccess: 398,
|
|
VFSReadPages: 331,
|
|
VFSWritePages: 47,
|
|
VFSFlush: 77,
|
|
VFSFileRelease: 77,
|
|
},
|
|
Operations: []NFSOperationStats{
|
|
{
|
|
Operation: "NULL",
|
|
},
|
|
{
|
|
Operation: "READ",
|
|
Requests: 1298,
|
|
Transmissions: 1298,
|
|
BytesSent: 207680,
|
|
BytesReceived: 1210292152,
|
|
CumulativeQueueTime: 6 * time.Millisecond,
|
|
CumulativeTotalResponseTime: 79386 * time.Millisecond,
|
|
CumulativeTotalRequestTime: 79407 * time.Millisecond,
|
|
},
|
|
{
|
|
Operation: "WRITE",
|
|
},
|
|
},
|
|
Transport: NFSTransportStats{
|
|
Protocol: "tcp",
|
|
Port: 832,
|
|
Connect: 1,
|
|
IdleTime: 11 * time.Second,
|
|
Sends: 6428,
|
|
Receives: 6428,
|
|
CumulativeActiveRequests: 12154,
|
|
MaximumRPCSlotsUsed: 24,
|
|
CumulativeSendingQueue: 26,
|
|
CumulativePendingQueue: 5726,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for i, tt := range tests {
|
|
t.Logf("[%02d] test %q", i, tt.name)
|
|
|
|
var mounts []*Mount
|
|
var err error
|
|
|
|
if tt.s != "" {
|
|
mounts, err = parseMountStats(strings.NewReader(tt.s))
|
|
} else {
|
|
proc, e := FS("fixtures").NewProc(26231)
|
|
if e != nil {
|
|
t.Fatalf("failed to create proc: %v", err)
|
|
}
|
|
|
|
mounts, err = proc.MountStats()
|
|
}
|
|
|
|
if tt.invalid && err == nil {
|
|
t.Error("expected an error, but none occurred")
|
|
}
|
|
if !tt.invalid && err != nil {
|
|
t.Errorf("unexpected error: %v", err)
|
|
}
|
|
|
|
if want, have := tt.mounts, mounts; !reflect.DeepEqual(want, have) {
|
|
t.Errorf("mounts:\nwant:\n%v\nhave:\n%v", mountsStr(want), mountsStr(have))
|
|
}
|
|
}
|
|
}
|
|
|
|
func mountsStr(mounts []*Mount) string {
|
|
var out string
|
|
for i, m := range mounts {
|
|
out += fmt.Sprintf("[%d] %q on %q (%q)", i, m.Device, m.Mount, m.Type)
|
|
|
|
stats, ok := m.Stats.(*MountStatsNFS)
|
|
if !ok {
|
|
out += "\n"
|
|
continue
|
|
}
|
|
|
|
out += fmt.Sprintf("\n\t- v%s, age: %s", stats.StatVersion, stats.Age)
|
|
out += fmt.Sprintf("\n\t- bytes: %v", stats.Bytes)
|
|
out += fmt.Sprintf("\n\t- events: %v", stats.Events)
|
|
out += fmt.Sprintf("\n\t- transport: %v", stats.Transport)
|
|
out += fmt.Sprintf("\n\t- per-operation stats:")
|
|
|
|
for _, o := range stats.Operations {
|
|
out += fmt.Sprintf("\n\t\t- %v", o)
|
|
}
|
|
|
|
out += "\n"
|
|
}
|
|
|
|
return out
|
|
}
|