in metric/system/cgroup/cgstats.go [117:151]
func (stat *StatsV2) FillPercentages(prev CGStats, curTime, prevTime time.Time) {
if prev != nil && prev.CGVersion() != CgroupsV2 {
return
}
prevStat, ok := prev.(*StatsV2)
if !ok || prevStat == nil || stat == nil || stat.CPU == nil || prevStat.CPU == nil {
return
}
timeDelta := curTime.Sub(prevTime)
timeDeltaNanos := timeDelta / time.Nanosecond
totalCPUDeltaNanos := int64(stat.CPU.Stats.Usage.NS - prevStat.CPU.Stats.Usage.NS)
pct := float64(totalCPUDeltaNanos) / float64(timeDeltaNanos)
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.CPU.Stats.User.NS - prevStat.CPU.Stats.User.NS)
systemCPUDeltaMillis := int64(stat.CPU.Stats.System.NS - prevStat.CPU.Stats.System.NS)
userPct := float64(userCPUDeltaMillis) / float64(timeDeltaNanos)
systemPct := float64(systemCPUDeltaMillis) / float64(timeDeltaNanos)
normalizedUser := userPct / float64(cpuCount)
normalizedSystem := systemPct / float64(cpuCount)
stat.CPU.Stats.Usage.Pct = opt.FloatWith(metric.Round(pct))
stat.CPU.Stats.Usage.Norm.Pct = opt.FloatWith(metric.Round(normalizedPct))
stat.CPU.Stats.User.Pct = opt.FloatWith(metric.Round(userPct))
stat.CPU.Stats.User.Norm.Pct = opt.FloatWith(metric.Round(normalizedUser))
stat.CPU.Stats.System.Pct = opt.FloatWith(metric.Round(systemPct))
stat.CPU.Stats.System.Norm.Pct = opt.FloatWith(metric.Round(normalizedSystem))
}