in metric/system/cgroup/cgstats.go [57:96]
func (stat *StatsV1) FillPercentages(prev CGStats, curTime, prevTime time.Time) {
if prev != nil && prev.CGVersion() != CgroupsV1 {
return
}
prevStat, ok := prev.(*StatsV1)
if !ok || prevStat == nil || stat == nil || stat.CPUAccounting == nil || prevStat.CPUAccounting == nil {
return
}
timeDelta := curTime.Sub(prevTime)
timeDeltaNanos := timeDelta / time.Nanosecond
totalCPUDeltaNanos := int64(stat.CPUAccounting.Total.NS - prevStat.CPUAccounting.Total.NS)
pct := float64(totalCPUDeltaNanos) / float64(timeDeltaNanos)
var cpuCount int
if len(stat.CPUAccounting.UsagePerCPU) > 0 {
cpuCount = len(stat.CPUAccounting.UsagePerCPU)
} else {
cpuCount = numcpu.NumCPU()
}
// if you look at the raw cgroup stats, the following normalized value is literally an average of per-cpu numbers.
normalizedPct := pct / float64(cpuCount)
userCPUDeltaMillis := int64(stat.CPUAccounting.Stats.User.NS - prevStat.CPUAccounting.Stats.User.NS)
systemCPUDeltaMillis := int64(stat.CPUAccounting.Stats.System.NS - prevStat.CPUAccounting.Stats.System.NS)
userPct := float64(userCPUDeltaMillis) / float64(timeDeltaNanos)
systemPct := float64(systemCPUDeltaMillis) / float64(timeDeltaNanos)
normalizedUser := userPct / float64(cpuCount)
normalizedSystem := systemPct / float64(cpuCount)
stat.CPUAccounting.Total.Pct = opt.FloatWith(metric.Round(pct))
stat.CPUAccounting.Total.Norm.Pct = opt.FloatWith(metric.Round(normalizedPct))
stat.CPUAccounting.Stats.User.Pct = opt.FloatWith(metric.Round(userPct))
stat.CPUAccounting.Stats.User.Norm.Pct = opt.FloatWith(metric.Round(normalizedUser))
stat.CPUAccounting.Stats.System.Pct = opt.FloatWith(metric.Round(systemPct))
stat.CPUAccounting.Stats.System.Norm.Pct = opt.FloatWith(metric.Round(normalizedSystem))
}