telegraf/plugins/inputs/system/disk_test.go

456 lines
12 KiB
Go

package system
import (
"os"
"testing"
"github.com/influxdata/telegraf/testutil"
"github.com/shirou/gopsutil/disk"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
type MockFileInfo struct {
os.FileInfo
}
func TestDiskUsage(t *testing.T) {
mck := &mock.Mock{}
mps := MockPSDisk{&systemPS{&mockDiskUsage{mck}}, mck}
defer mps.AssertExpectations(t)
var acc testutil.Accumulator
var err error
psAll := []disk.PartitionStat{
{
Device: "/dev/sda",
Mountpoint: "/",
Fstype: "ext4",
Opts: "ro,noatime,nodiratime",
},
{
Device: "/dev/sdb",
Mountpoint: "/home",
Fstype: "ext4",
Opts: "rw,noatime,nodiratime,errors=remount-ro",
},
}
duAll := []disk.UsageStat{
{
Path: "/",
Fstype: "ext4",
Total: 128,
Free: 23,
Used: 100,
InodesTotal: 1234,
InodesFree: 234,
InodesUsed: 1000,
},
{
Path: "/home",
Fstype: "ext4",
Total: 256,
Free: 46,
Used: 200,
InodesTotal: 2468,
InodesFree: 468,
InodesUsed: 2000,
},
}
mps.On("Partitions", true).Return(psAll, nil)
mps.On("OSGetenv", "HOST_MOUNT_PREFIX").Return("")
mps.On("PSDiskUsage", "/").Return(&duAll[0], nil)
mps.On("PSDiskUsage", "/home").Return(&duAll[1], nil)
err = (&DiskStats{ps: mps}).Gather(&acc)
require.NoError(t, err)
numDiskMetrics := acc.NFields()
expectedAllDiskMetrics := 14
assert.Equal(t, expectedAllDiskMetrics, numDiskMetrics)
tags1 := map[string]string{
"path": "/",
"fstype": "ext4",
"device": "sda",
"mode": "ro",
}
tags2 := map[string]string{
"path": "/home",
"fstype": "ext4",
"device": "sdb",
"mode": "rw",
}
fields1 := map[string]interface{}{
"total": uint64(128),
"used": uint64(100),
"free": uint64(23),
"inodes_total": uint64(1234),
"inodes_free": uint64(234),
"inodes_used": uint64(1000),
"used_percent": float64(81.30081300813008),
}
fields2 := map[string]interface{}{
"total": uint64(256),
"used": uint64(200),
"free": uint64(46),
"inodes_total": uint64(2468),
"inodes_free": uint64(468),
"inodes_used": uint64(2000),
"used_percent": float64(81.30081300813008),
}
acc.AssertContainsTaggedFields(t, "disk", fields1, tags1)
acc.AssertContainsTaggedFields(t, "disk", fields2, tags2)
// We expect 6 more DiskMetrics to show up with an explicit match on "/"
// and /home not matching the /dev in MountPoints
err = (&DiskStats{ps: &mps, MountPoints: []string{"/", "/dev"}}).Gather(&acc)
assert.Equal(t, expectedAllDiskMetrics+7, acc.NFields())
// We should see all the diskpoints as MountPoints includes both
// / and /home
err = (&DiskStats{ps: &mps, MountPoints: []string{"/", "/home"}}).Gather(&acc)
assert.Equal(t, 2*expectedAllDiskMetrics+7, acc.NFields())
}
func TestDiskUsageHostMountPrefix(t *testing.T) {
tests := []struct {
name string
partitionStats []disk.PartitionStat
usageStats []*disk.UsageStat
hostMountPrefix string
expectedTags map[string]string
expectedFields map[string]interface{}
}{
{
name: "no host mount prefix",
partitionStats: []disk.PartitionStat{
{
Device: "/dev/sda",
Mountpoint: "/",
Fstype: "ext4",
Opts: "ro",
},
},
usageStats: []*disk.UsageStat{
&disk.UsageStat{
Path: "/",
Total: 42,
},
},
expectedTags: map[string]string{
"path": "/",
"device": "sda",
"fstype": "ext4",
"mode": "ro",
},
expectedFields: map[string]interface{}{
"total": uint64(42),
"used": uint64(0),
"free": uint64(0),
"inodes_total": uint64(0),
"inodes_free": uint64(0),
"inodes_used": uint64(0),
"used_percent": float64(0),
},
},
{
name: "host mount prefix",
partitionStats: []disk.PartitionStat{
{
Device: "/dev/sda",
Mountpoint: "/hostfs/var",
Fstype: "ext4",
Opts: "ro",
},
},
usageStats: []*disk.UsageStat{
&disk.UsageStat{
Path: "/hostfs/var",
Total: 42,
},
},
hostMountPrefix: "/hostfs",
expectedTags: map[string]string{
"path": "/var",
"device": "sda",
"fstype": "ext4",
"mode": "ro",
},
expectedFields: map[string]interface{}{
"total": uint64(42),
"used": uint64(0),
"free": uint64(0),
"inodes_total": uint64(0),
"inodes_free": uint64(0),
"inodes_used": uint64(0),
"used_percent": float64(0),
},
},
{
name: "host mount prefix exact match",
partitionStats: []disk.PartitionStat{
{
Device: "/dev/sda",
Mountpoint: "/hostfs",
Fstype: "ext4",
Opts: "ro",
},
},
usageStats: []*disk.UsageStat{
&disk.UsageStat{
Path: "/hostfs",
Total: 42,
},
},
hostMountPrefix: "/hostfs",
expectedTags: map[string]string{
"path": "/",
"device": "sda",
"fstype": "ext4",
"mode": "ro",
},
expectedFields: map[string]interface{}{
"total": uint64(42),
"used": uint64(0),
"free": uint64(0),
"inodes_total": uint64(0),
"inodes_free": uint64(0),
"inodes_used": uint64(0),
"used_percent": float64(0),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mck := &mock.Mock{}
mps := MockPSDisk{&systemPS{&mockDiskUsage{mck}}, mck}
defer mps.AssertExpectations(t)
var acc testutil.Accumulator
var err error
mps.On("Partitions", true).Return(tt.partitionStats, nil)
for _, v := range tt.usageStats {
mps.On("PSDiskUsage", v.Path).Return(v, nil)
}
mps.On("OSGetenv", "HOST_MOUNT_PREFIX").Return(tt.hostMountPrefix)
err = (&DiskStats{ps: mps}).Gather(&acc)
require.NoError(t, err)
acc.AssertContainsTaggedFields(t, "disk", tt.expectedFields, tt.expectedTags)
})
}
}
func TestDiskStats(t *testing.T) {
var mps MockPS
defer mps.AssertExpectations(t)
var acc testutil.Accumulator
var err error
duAll := []*disk.UsageStat{
{
Path: "/",
Fstype: "ext4",
Total: 128,
Free: 23,
Used: 100,
InodesTotal: 1234,
InodesFree: 234,
InodesUsed: 1000,
},
{
Path: "/home",
Fstype: "ext4",
Total: 256,
Free: 46,
Used: 200,
InodesTotal: 2468,
InodesFree: 468,
InodesUsed: 2000,
},
}
duFiltered := []*disk.UsageStat{
{
Path: "/",
Fstype: "ext4",
Total: 128,
Free: 23,
Used: 100,
InodesTotal: 1234,
InodesFree: 234,
InodesUsed: 1000,
},
}
psAll := []*disk.PartitionStat{
{
Device: "/dev/sda",
Mountpoint: "/",
Fstype: "ext4",
Opts: "ro,noatime,nodiratime",
},
{
Device: "/dev/sdb",
Mountpoint: "/home",
Fstype: "ext4",
Opts: "rw,noatime,nodiratime,errors=remount-ro",
},
}
psFiltered := []*disk.PartitionStat{
{
Device: "/dev/sda",
Mountpoint: "/",
Fstype: "ext4",
Opts: "ro,noatime,nodiratime",
},
}
mps.On("DiskUsage", []string(nil), []string(nil)).Return(duAll, psAll, nil)
mps.On("DiskUsage", []string{"/", "/dev"}, []string(nil)).Return(duFiltered, psFiltered, nil)
mps.On("DiskUsage", []string{"/", "/home"}, []string(nil)).Return(duAll, psAll, nil)
err = (&DiskStats{ps: &mps}).Gather(&acc)
require.NoError(t, err)
numDiskMetrics := acc.NFields()
expectedAllDiskMetrics := 14
assert.Equal(t, expectedAllDiskMetrics, numDiskMetrics)
tags1 := map[string]string{
"path": "/",
"fstype": "ext4",
"device": "sda",
"mode": "ro",
}
tags2 := map[string]string{
"path": "/home",
"fstype": "ext4",
"device": "sdb",
"mode": "rw",
}
fields1 := map[string]interface{}{
"total": uint64(128),
"used": uint64(100),
"free": uint64(23),
"inodes_total": uint64(1234),
"inodes_free": uint64(234),
"inodes_used": uint64(1000),
"used_percent": float64(81.30081300813008),
}
fields2 := map[string]interface{}{
"total": uint64(256),
"used": uint64(200),
"free": uint64(46),
"inodes_total": uint64(2468),
"inodes_free": uint64(468),
"inodes_used": uint64(2000),
"used_percent": float64(81.30081300813008),
}
acc.AssertContainsTaggedFields(t, "disk", fields1, tags1)
acc.AssertContainsTaggedFields(t, "disk", fields2, tags2)
// We expect 6 more DiskMetrics to show up with an explicit match on "/"
// and /home not matching the /dev in MountPoints
err = (&DiskStats{ps: &mps, MountPoints: []string{"/", "/dev"}}).Gather(&acc)
assert.Equal(t, expectedAllDiskMetrics+7, acc.NFields())
// We should see all the diskpoints as MountPoints includes both
// / and /home
err = (&DiskStats{ps: &mps, MountPoints: []string{"/", "/home"}}).Gather(&acc)
assert.Equal(t, 2*expectedAllDiskMetrics+7, acc.NFields())
}
// func TestDiskIOStats(t *testing.T) {
// var mps MockPS
// defer mps.AssertExpectations(t)
// var acc testutil.Accumulator
// var err error
// diskio1 := disk.IOCountersStat{
// ReadCount: 888,
// WriteCount: 5341,
// ReadBytes: 100000,
// WriteBytes: 200000,
// ReadTime: 7123,
// WriteTime: 9087,
// Name: "sda1",
// IoTime: 123552,
// SerialNumber: "ab-123-ad",
// }
// diskio2 := disk.IOCountersStat{
// ReadCount: 444,
// WriteCount: 2341,
// ReadBytes: 200000,
// WriteBytes: 400000,
// ReadTime: 3123,
// WriteTime: 6087,
// Name: "sdb1",
// IoTime: 246552,
// SerialNumber: "bb-123-ad",
// }
// mps.On("DiskIO").Return(
// map[string]disk.IOCountersStat{"sda1": diskio1, "sdb1": diskio2},
// nil)
// err = (&DiskIOStats{ps: &mps}).Gather(&acc)
// require.NoError(t, err)
// numDiskIOMetrics := acc.NFields()
// expectedAllDiskIOMetrics := 14
// assert.Equal(t, expectedAllDiskIOMetrics, numDiskIOMetrics)
// dtags1 := map[string]string{
// "name": "sda1",
// "serial": "ab-123-ad",
// }
// dtags2 := map[string]string{
// "name": "sdb1",
// "serial": "bb-123-ad",
// }
// assert.True(t, acc.CheckTaggedValue("reads", uint64(888), dtags1))
// assert.True(t, acc.CheckTaggedValue("writes", uint64(5341), dtags1))
// assert.True(t, acc.CheckTaggedValue("read_bytes", uint64(100000), dtags1))
// assert.True(t, acc.CheckTaggedValue("write_bytes", uint64(200000), dtags1))
// assert.True(t, acc.CheckTaggedValue("read_time", uint64(7123), dtags1))
// assert.True(t, acc.CheckTaggedValue("write_time", uint64(9087), dtags1))
// assert.True(t, acc.CheckTaggedValue("io_time", uint64(123552), dtags1))
// assert.True(t, acc.CheckTaggedValue("reads", uint64(444), dtags2))
// assert.True(t, acc.CheckTaggedValue("writes", uint64(2341), dtags2))
// assert.True(t, acc.CheckTaggedValue("read_bytes", uint64(200000), dtags2))
// assert.True(t, acc.CheckTaggedValue("write_bytes", uint64(400000), dtags2))
// assert.True(t, acc.CheckTaggedValue("read_time", uint64(3123), dtags2))
// assert.True(t, acc.CheckTaggedValue("write_time", uint64(6087), dtags2))
// assert.True(t, acc.CheckTaggedValue("io_time", uint64(246552), dtags2))
// // We expect 7 more DiskIOMetrics to show up with an explicit match on "sdb1"
// // and serial should be missing from the tags with SkipSerialNumber set
// err = (&DiskIOStats{ps: &mps, Devices: []string{"sdb1"}, SkipSerialNumber: true}).Gather(&acc)
// assert.Equal(t, expectedAllDiskIOMetrics+7, acc.NFields())
// dtags3 := map[string]string{
// "name": "sdb1",
// }
// assert.True(t, acc.CheckTaggedValue("reads", uint64(444), dtags3))
// assert.True(t, acc.CheckTaggedValue("writes", uint64(2341), dtags3))
// assert.True(t, acc.CheckTaggedValue("read_bytes", uint64(200000), dtags3))
// assert.True(t, acc.CheckTaggedValue("write_bytes", uint64(400000), dtags3))
// assert.True(t, acc.CheckTaggedValue("read_time", uint64(3123), dtags3))
// assert.True(t, acc.CheckTaggedValue("write_time", uint64(6087), dtags3))
// assert.True(t, acc.CheckTaggedValue("io_time", uint64(246552), dtags3))
// }