func()

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

}