Add support for Linux discards and flushes in IOCounterStats.

These were added in kernels 4.18 and 5.5, respectively.

Flushes (i.e. fsyncs) are especially important for logging for database servers and
the like, as flushes can be a very limiting factor on IO throughput.
pull/1307/head
Joseph Malicki 3 years ago
parent c4a0f4689f
commit 6f716d14c8

@ -41,6 +41,13 @@ type IOCountersStat struct {
IopsInProgress uint64 `json:"iopsInProgress"`
IoTime uint64 `json:"ioTime"`
WeightedIO uint64 `json:"weightedIO"`
DiscardCount uint64 `json:"discardCount"`
MergedDiscardCount uint64 `json:"mergedDiscardCount"`
DiscardBytes uint64 `json:"discardBytes"`
DiscardTime uint64 `json:"discardTime"`
FlushCount uint64 `json:"flushCount"`
FlushTime uint64 `json:"flushTime"`
Name string `json:"name"`
SerialNumber string `json:"serialNumber"`
Label string `json:"label"`

@ -455,6 +455,40 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
if err != nil {
return ret, err
}
discards := uint64(0)
mergedDiscards := uint64(0)
dbytes := uint64(0)
dtime := uint64(0)
if len(fields) >= 18 {
discards, err = strconv.ParseUint((fields[14]), 10, 64)
if err != nil {
return ret, err
}
mergedDiscards, err = strconv.ParseUint((fields[15]), 10, 64)
if err != nil {
return ret, err
}
dbytes, err = strconv.ParseUint((fields[16]), 10, 64)
if err != nil {
return ret, err
}
dtime, err = strconv.ParseUint((fields[17]), 10, 64)
if err != nil {
return ret, err
}
}
flushes := uint64(0)
ftime := uint64(0)
if len(fields) >= 20 {
flushes, err = strconv.ParseUint((fields[18]), 10, 64)
if err != nil {
return ret, err
}
ftime, err = strconv.ParseUint((fields[19]), 10, 64)
if err != nil {
return ret, err
}
}
d := IOCountersStat{
ReadBytes: rbytes * sectorSize,
WriteBytes: wbytes * sectorSize,
@ -467,6 +501,12 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
IopsInProgress: iopsInProgress,
IoTime: iotime,
WeightedIO: weightedIO,
DiscardCount: discards,
MergedDiscardCount: mergedDiscards,
DiscardBytes: dbytes * sectorSize,
DiscardTime: dtime,
FlushCount: flushes,
FlushTime: ftime,
}
if d == empty {
continue

@ -0,0 +1,122 @@
//go:build linux
// +build linux
package disk
import (
"os"
"testing"
)
func TestDiskStatsPost55(t *testing.T) {
orig := os.Getenv("HOST_PROC")
defer os.Setenv("HOST_PROC", orig)
os.Setenv("HOST_PROC", "testdata/linux/diskstats-post5.5/proc")
ios, err := IOCounters("sda", "sdc")
if err != nil {
t.Error("IOCounters failed")
}
expected := IOCountersStat{
ReadCount: 256838102,
MergedReadCount: 620512,
ReadBytes: 5028599594 * sectorSize,
ReadTime: 226563271,
WriteCount: 418236058,
MergedWriteCount: 7573415,
WriteBytes: 8577305933 * sectorSize,
WriteTime: 171833267,
IopsInProgress: 0,
IoTime: 141604084,
WeightedIO: 402232601,
DiscardCount: 168817,
MergedDiscardCount: 110,
DiscardBytes: 4991981424 * sectorSize,
DiscardTime: 387582,
FlushCount: 983197,
FlushTime: 3448479,
Name: "sdc",
SerialNumber: "",
Label: "",
}
if ios["sdc"] != expected {
t.Logf("IOCounterStats gave wrong results: expected %v actual %v", expected, ios["sdc"])
t.Error("IOCounterStats gave wrong results")
}
}
func TestDiskStatsPre55(t *testing.T) {
orig := os.Getenv("HOST_PROC")
os.Setenv("HOST_PROC", "testdata/linux/diskstats-pre5.5/proc")
defer os.Setenv("HOST_PROC", orig)
ios, err := IOCounters("sda", "sdc")
if err != nil {
t.Error("IOCounters failed")
}
expected := IOCountersStat{
ReadCount: 256838102,
MergedReadCount: 620512,
ReadBytes: 5028599594 * sectorSize,
ReadTime: 226563271,
WriteCount: 418236058,
MergedWriteCount: 7573415,
WriteBytes: 8577305933 * sectorSize,
WriteTime: 171833267,
IopsInProgress: 0,
IoTime: 141604084,
WeightedIO: 402232601,
DiscardCount: 168817,
MergedDiscardCount: 110,
DiscardBytes: 4991981424 * sectorSize,
DiscardTime: 387582,
FlushCount: 0,
FlushTime: 0,
Name: "sdc",
SerialNumber: "",
Label: "",
}
if ios["sdc"] != expected {
t.Logf("IOCounterStats gave wrong results: expected %v actual %v", expected, ios)
t.Error("IOCounterStats gave wrong results")
}
}
func TestDiskStatsPre418(t *testing.T) {
orig := os.Getenv("HOST_PROC")
defer os.Setenv("HOST_PROC", orig)
os.Setenv("HOST_PROC", "testdata/linux/diskstats-pre4.18/proc")
ios, err := IOCounters("sda", "sdc")
if err != nil {
t.Error("IOCounters failed")
}
expected := IOCountersStat{
ReadCount: 256838102,
MergedReadCount: 620512,
ReadBytes: 5028599594 * sectorSize,
ReadTime: 226563271,
WriteCount: 418236058,
MergedWriteCount: 7573415,
WriteBytes: 8577305933 * sectorSize,
WriteTime: 171833267,
IopsInProgress: 0,
IoTime: 141604084,
WeightedIO: 402232601,
DiscardCount: 0,
MergedDiscardCount: 0,
DiscardBytes: 0,
DiscardTime: 0,
FlushCount: 0,
FlushTime: 0,
Name: "sdc",
SerialNumber: "",
Label: "",
}
if ios["sdc"] != expected {
t.Logf("IOCounterStats gave wrong results: expected %v actual %v", expected, ios["sdc"])
t.Error("IOCounterStats gave wrong results")
}
}

@ -123,9 +123,11 @@ func TestDiskIOCountersStat_String(t *testing.T) {
WriteCount: 200,
ReadBytes: 300,
WriteBytes: 400,
DiscardCount: 500,
FlushCount: 600,
SerialNumber: "SERIAL",
}
e := `{"readCount":100,"mergedReadCount":0,"writeCount":200,"mergedWriteCount":0,"readBytes":300,"writeBytes":400,"readTime":0,"writeTime":0,"iopsInProgress":0,"ioTime":0,"weightedIO":0,"name":"sd01","serialNumber":"SERIAL","label":""}`
e := `{"readCount":100,"mergedReadCount":0,"writeCount":200,"mergedWriteCount":0,"readBytes":300,"writeBytes":400,"readTime":0,"writeTime":0,"iopsInProgress":0,"ioTime":0,"weightedIO":0,"discardCount":500,"mergedDiscardCount":0,"discardBytes":0,"discardTime":0,"flushCount":600,"flushTime":0,"name":"sd01","serialNumber":"SERIAL","label":""}`
if e != fmt.Sprintf("%v", v) {
t.Errorf("DiskUsageStat string is invalid: %v", v)
}

@ -0,0 +1,4 @@
8 0 sda 251490562 587923 4907991349 207940386 418695352 7259232 8579533525 94584901 0 140322864 306361336 169975 208 4992138504 371249 984400 3464799
8 1 sda1 251488338 587923 4907983293 207938421 418695352 7259232 8579533525 94584901 0 140322088 302894572 169975 208 4992138504 371249 0 0
8 32 sdc 256838102 620512 5028599594 226563271 418236058 7573415 8577305933 171833267 0 141604084 402232601 168817 110 4991981424 387582 983197 3448479
8 33 sdc1 256835879 620512 5028591546 226561154 418236058 7573415 8577305933 171833267 0 141603284 398782004 168817 110 4991981424 387582 0 0

@ -0,0 +1,4 @@
8 0 sda 251490562 587923 4907991349 207940386 418695352 7259232 8579533525 94584901 0 140322864 306361336
8 1 sda1 251488338 587923 4907983293 207938421 418695352 7259232 8579533525 94584901 0 140322088 302894572
8 32 sdc 256838102 620512 5028599594 226563271 418236058 7573415 8577305933 171833267 0 141604084 402232601
8 33 sdc1 256835879 620512 5028591546 226561154 418236058 7573415 8577305933 171833267 0 141603284 398782004

@ -0,0 +1,4 @@
8 0 sda 251490562 587923 4907991349 207940386 418695352 7259232 8579533525 94584901 0 140322864 306361336
8 1 sda1 251488338 587923 4907983293 207938421 418695352 7259232 8579533525 94584901 0 140322088 302894572
8 32 sdc 256838102 620512 5028599594 226563271 418236058 7573415 8577305933 171833267 0 141604084 402232601
8 33 sdc1 256835879 620512 5028591546 226561154 418236058 7573415 8577305933 171833267 0 141603284 398782004

@ -0,0 +1,4 @@
8 0 sda 251490562 587923 4907991349 207940386 418695352 7259232 8579533525 94584901 0 140322864 306361336 169975 208 4992138504 371249
8 1 sda1 251488338 587923 4907983293 207938421 418695352 7259232 8579533525 94584901 0 140322088 302894572 169975 208 4992138504 371249
8 32 sdc 256838102 620512 5028599594 226563271 418236058 7573415 8577305933 171833267 0 141604084 402232601 168817 110 4991981424 387582
8 33 sdc1 256835879 620512 5028591546 226561154 418236058 7573415 8577305933 171833267 0 141603284 398782004 168817 110 4991981424 387582
Loading…
Cancel
Save