diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 3edfa840779..25b09e7bf86 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -79,6 +79,7 @@ https://github.com/elastic/beats/compare/v6.4.0...master[Check the HEAD diff] - Add docker diskio stats on Windows. {issue}6815[6815] {pull}8126[8126] - Fix incorrect type conversion of average response time in Haproxy dashboards {pull}8404[8404] - Fix dropwizard module parsing of metric names. {issue}8365[8365] {pull}6385[8385] +- Added io disk read and write times to system module {issue}8473[8473] {pull}8508[8508] - Avoid mapping issues in kubernetes module. {pull}8487[8487] *Packetbeat* diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 395a4bd14cd..67f074dc678 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -19918,6 +19918,16 @@ format: bytes The number of Bytes read from the device per second. +-- + +*`system.diskio.iostat.read.await`*:: ++ +-- +type: float + +The average time spent for read requests issued to the device to be served. + + -- *`system.diskio.iostat.write.per_sec.bytes`*:: @@ -19930,6 +19940,16 @@ format: bytes The number of Bytes write from the device per second. +-- + +*`system.diskio.iostat.write.await`*:: ++ +-- +type: float + +The average time spent for write requests issued to the device to be served. + + -- *`system.diskio.iostat.request.avg_size`*:: diff --git a/metricbeat/module/system/diskio/_meta/data.json b/metricbeat/module/system/diskio/_meta/data.json index 9c95874b755..0a415a2399f 100644 --- a/metricbeat/module/system/diskio/_meta/data.json +++ b/metricbeat/module/system/diskio/_meta/data.json @@ -27,7 +27,8 @@ "request": { "merges_per_sec": 0, "per_sec": 0 - } + }, + "await": 0 }, "request": { "avg_size": 0 @@ -40,7 +41,8 @@ "request": { "merges_per_sec": 0, "per_sec": 0 - } + }, + "await": 0 } }, "name": "sda", diff --git a/metricbeat/module/system/diskio/_meta/fields.yml b/metricbeat/module/system/diskio/_meta/fields.yml index 66423578b06..c11e62a0277 100644 --- a/metricbeat/module/system/diskio/_meta/fields.yml +++ b/metricbeat/module/system/diskio/_meta/fields.yml @@ -82,12 +82,22 @@ The number of Bytes read from the device per second. format: bytes + - name: iostat.read.await + type: float + description: > + The average time spent for read requests issued to the device to be served. + - name: iostat.write.per_sec.bytes type: float description: > The number of Bytes write from the device per second. format: bytes + - name: iostat.write.await + type: float + description: > + The average time spent for write requests issued to the device to be served. + - name: iostat.request.avg_size type: float description: > diff --git a/metricbeat/module/system/diskio/diskio.go b/metricbeat/module/system/diskio/diskio.go index 7e80c05fc23..d90bd900ebd 100644 --- a/metricbeat/module/system/diskio/diskio.go +++ b/metricbeat/module/system/diskio/diskio.go @@ -99,6 +99,7 @@ func (m *MetricSet) Fetch() ([]common.MapStr, error) { "per_sec": common.MapStr{ "bytes": extraMetrics.ReadBytesPerSec, }, + "await": extraMetrics.AvgReadAwaitTime, }, "write": common.MapStr{ "request": common.MapStr{ @@ -108,6 +109,7 @@ func (m *MetricSet) Fetch() ([]common.MapStr, error) { "per_sec": common.MapStr{ "bytes": extraMetrics.WriteBytesPerSec, }, + "await": extraMetrics.AvgWriteAwaitTime, }, "queue": common.MapStr{ "avg_size": extraMetrics.AvgQueueSize, diff --git a/metricbeat/module/system/diskio/diskstat.go b/metricbeat/module/system/diskio/diskstat.go index 518c0bcdc04..949d69778fa 100644 --- a/metricbeat/module/system/diskio/diskstat.go +++ b/metricbeat/module/system/diskio/diskstat.go @@ -35,13 +35,15 @@ type DiskIOMetric struct { ReadRequestCountPerSec float64 `json:"rrqCps"` WriteRequestCountPerSec float64 `json:"wrqCps"` // using bytes instead of sector - ReadBytesPerSec float64 `json:"rBps"` - WriteBytesPerSec float64 `json:"wBps"` - AvgRequestSize float64 `json:"avgrqSz"` - AvgQueueSize float64 `json:"avgquSz"` - AvgAwaitTime float64 `json:"await"` - AvgServiceTime float64 `json:"svctm"` - BusyPct float64 `json:"busy"` + ReadBytesPerSec float64 `json:"rBps"` + WriteBytesPerSec float64 `json:"wBps"` + AvgRequestSize float64 `json:"avgrqSz"` + AvgQueueSize float64 `json:"avgquSz"` + AvgAwaitTime float64 `json:"await"` + AvgReadAwaitTime float64 `json:"r_await"` + AvgWriteAwaitTime float64 `json:"w_await"` + AvgServiceTime float64 `json:"svctm"` + BusyPct float64 `json:"busy"` } type DiskIOStat struct { diff --git a/metricbeat/module/system/diskio/diskstat_linux.go b/metricbeat/module/system/diskio/diskstat_linux.go index 0a89de90940..1647adabc23 100644 --- a/metricbeat/module/system/diskio/diskstat_linux.go +++ b/metricbeat/module/system/diskio/diskstat_linux.go @@ -98,6 +98,8 @@ func (stat *DiskIOStat) CalIOStatistics(counter disk.IOCountersStat) (DiskIOMetr result.AvgRequestSize = size result.AvgQueueSize = queue result.AvgAwaitTime = wait + result.AvgReadAwaitTime = float64(rd_ticks) / float64(rd_ios) + result.AvgWriteAwaitTime = float64(wr_ticks) / float64(wr_ios) result.AvgServiceTime = svct result.BusyPct = 100.0 * float64(ticks) / deltams if result.BusyPct > 100.0 { diff --git a/metricbeat/module/system/diskio/diskstat_linux_test.go b/metricbeat/module/system/diskio/diskstat_linux_test.go index 5b3b9f7f044..7f0cb578932 100644 --- a/metricbeat/module/system/diskio/diskstat_linux_test.go +++ b/metricbeat/module/system/diskio/diskstat_linux_test.go @@ -22,6 +22,9 @@ package diskio import ( "testing" + sigar "github.com/elastic/gosigar" + + "github.com/shirou/gopsutil/disk" "github.com/stretchr/testify/assert" mbtest "github.com/elastic/beats/metricbeat/mb/testing" @@ -81,3 +84,42 @@ func TestDataEmptyFilter(t *testing.T) { assert.NoError(t, err) assert.Equal(t, 10, len(data)) } + +func TestDiskIOStat_CalIOStatistics(t *testing.T) { + counter := disk.IOCountersStat{ + ReadCount: 13, + WriteCount: 17, + ReadTime: 19, + WriteTime: 23, + Name: "iostat", + } + + stat := &DiskIOStat{ + lastDiskIOCounters: map[string]disk.IOCountersStat{ + "iostat": disk.IOCountersStat{ + ReadCount: 3, + WriteCount: 5, + ReadTime: 7, + WriteTime: 11, + Name: "iostat", + }, + }, + lastCpu: sigar.Cpu{Idle: 100}, + curCpu: sigar.Cpu{Idle: 1}, + } + + expected := DiskIOMetric{ + AvgAwaitTime: 24.0 / 22.0, + AvgReadAwaitTime: 1.2, + AvgWriteAwaitTime: 1, + } + + got, err := stat.CalIOStatistics(counter) + if err != nil { + t.Fatal(err) + } + + assert.Equal(t, expected.AvgAwaitTime, got.AvgAwaitTime) + assert.Equal(t, expected.AvgReadAwaitTime, got.AvgReadAwaitTime) + assert.Equal(t, expected.AvgWriteAwaitTime, got.AvgWriteAwaitTime) +} diff --git a/metricbeat/module/system/fields.go b/metricbeat/module/system/fields.go index 44915981115..0f8a61053cb 100644 --- a/metricbeat/module/system/fields.go +++ b/metricbeat/module/system/fields.go @@ -31,5 +31,5 @@ func init() { // Asset returns asset data func Asset() string { - return "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" + return "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" }