in metric/system/diskio/diskstat_linux.go [81:151]
func (stat *IOStat) CalcIOStatistics(counter disk.IOCountersStat) (IOMetric, error) {
var last disk.IOCountersStat
var ok bool
// if last counter not found, create one and return all 0
if last, ok = stat.lastDiskIOCounters[counter.Name]; !ok {
stat.lastDiskIOCounters[counter.Name] = counter
return IOMetric{}, nil
}
// calculate the delta ms between the CloseSampling and OpenSampling
deltams := 1000.0 * float64(stat.curCPU.Total()-stat.lastCPU.Total()) / float64(numcpu.NumCPU()) / float64(GetCLKTCK())
if deltams <= 0 {
return IOMetric{}, errors.New("the delta cpu time between close sampling and open sampling is less or equal to 0")
}
rdIOs := counter.ReadCount - last.ReadCount
rdMerges := counter.MergedReadCount - last.MergedReadCount
rdBytes := counter.ReadBytes - last.ReadBytes
rdTicks := returnOrFix32BitRollover(counter.ReadTime, last.ReadTime)
wrIOs := counter.WriteCount - last.WriteCount
wrMerges := counter.MergedWriteCount - last.MergedWriteCount
wrBytes := counter.WriteBytes - last.WriteBytes
wrTicks := returnOrFix32BitRollover(counter.WriteTime, last.WriteTime)
ticks := returnOrFix32BitRollover(counter.IoTime, last.IoTime)
aveq := returnOrFix32BitRollover(counter.WeightedIO, last.WeightedIO)
nIOs := rdIOs + wrIOs
nTicks := rdTicks + wrTicks
nBytes := rdBytes + wrBytes
size := float64(0)
wait := float64(0)
svct := float64(0)
if nIOs > 0 {
size = float64(nBytes) / float64(nIOs)
wait = float64(nTicks) / float64(nIOs)
svct = float64(ticks) / float64(nIOs)
}
queue := float64(aveq) / deltams
perSec := func(x uint64) float64 {
return metric.Round(1000.0 * float64(x) / deltams)
}
result := IOMetric{}
result.ReadRequestMergeCountPerSec = perSec(rdMerges)
result.WriteRequestMergeCountPerSec = perSec(wrMerges)
result.ReadRequestCountPerSec = perSec(rdIOs)
result.WriteRequestCountPerSec = perSec(wrIOs)
result.ReadBytesPerSec = perSec(rdBytes)
result.WriteBytesPerSec = perSec(wrBytes)
result.AvgRequestSize = metric.Round(size)
result.AvgQueueSize = metric.Round(queue)
result.AvgAwaitTime = metric.Round(wait)
if rdIOs > 0 {
result.AvgReadAwaitTime = metric.Round(float64(rdTicks) / float64(rdIOs))
}
if wrIOs > 0 {
result.AvgWriteAwaitTime = metric.Round(float64(wrTicks) / float64(wrIOs))
}
result.AvgServiceTime = metric.Round(svct)
result.BusyPct = metric.Round(100.0 * float64(ticks) / deltams)
if result.BusyPct > 100.0 {
result.BusyPct = 100.0
}
stat.lastDiskIOCounters[counter.Name] = counter
return result, nil
}