Метрика cpuPercent из статистики докера и группы
Я новичок в cgroups, и пытаюсь получить статистику контейнера с помощью cgroups. Ранее я использовал docker stats
но, пытаясь собрать аналогичные показатели с cgroups
также.
В статистике докера раздел статистики процессора выглядит следующим образом:
"cpu_usage": {
"total_usage": 27120642519,
"percpu_usage": [27120642519],
"usage_in_kernelmode": 4550000000,
"usage_in_usermode": 19140000000
},
"system_cpu_usage": 42803030000000,
И показатель CPU% вычисляется с использованием приведенного ниже уравнения:
cpuDelta = float64(v.CpuStats.CpuUsage.TotalUsage - previousCPU)
systemDelta = float64(v.CpuStats.SystemUsage - previousSystem)
cpuPct = cpuDelta/systemDelta
Я смотрю на группы, чтобы собрать systemUsage
и totalUsage
, но у него нет похожих метрик:
cgroups имеет псевдо-файл cpuacct.stats, который имеет user
а также system
галочки, но они совпадают только с usage_in_user_mode
а также usage_in_kernel_mode
от docker stats
выход.
и псевдо-файл cpuacct.usage_per_cpu имеет использование на процессор, что соответствует total_usage
из вывода статистики докера выше.
$cat cpuacct.stat
user 1914
system 455
$cat cpuacct.usage_percpu
27120642519
Но я не мог найти способ выяснить, как собрать "systemUsage" из cgroups.
Любые выводы будут очень полезны!
Спасибо!
1 ответ
Ответ на ваш вопрос не лежит в группах. Пожалуйста, обратитесь ниже упомянутый пункт:
func calculateCPUPercentUnix(previousCPU, previousSystem uint64, v *types.StatsJSON) float64 {
var (
cpuPercent = 0.0
// calculate the change for the cpu usage of the container in between readings
cpuDelta = float64(v.CPUStats.CPUUsage.TotalUsage) - float64(previousCPU)
// calculate the change for the entire system between readings
systemDelta = float64(v.CPUStats.SystemUsage) - float64(previousSystem)
)
if systemDelta > 0.0 && cpuDelta > 0.0 {
cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CPUStats.CPUUsage.PercpuUsage)) * 100.0
}
return cpuPercent
}
- "System_cpu_usage" API статистики Docker относится к использованию ЦП хостом.
- "Cpu_usage" > "total_usage" API статистики Docker относится к использованию контейнера для каждого процессора.
- Следовательно, после вычисления (cpuDelta / systemDelta) мы получаем использование каждого процессора для каждого системного процессора.
- Теперь нам нужно умножить результат шага 3 и общее количество ЦП, выделенных для контейнера докера, чтобы получить общее использование ЦП на системный ЦП.
- Результат шага 4, умноженный на 100, дает нам загрузку ЦП в процентах.
Вернуться к вопросу: Как вычисляется системный процессор докером?
Чтобы вычислить использование ЦП системой, используется "/proc/stat", определенный POSIX. Он ищет строку статистики ЦП и затем суммирует первые семь предоставленных полей. Код golang, написанный для выполнения необходимых шагов, упомянут ниже.
// getSystemCPUUsage returns the host system's cpu usage in
// nanoseconds. An error is returned if the format of the underlying
// file does not match.
//
// Uses /proc/stat defined by POSIX. Looks for the cpu
// statistics line and then sums up the first seven fields
// provided. See `man 5 proc` for details on specific field
// information.
func (s *statsCollector) getSystemCPUUsage() (uint64, error) {
var line string
f, err := os.Open("/proc/stat")
if err != nil {
return 0, err
}
defer func() {
s.bufReader.Reset(nil)
f.Close()
}()
s.bufReader.Reset(f)
err = nil
for err == nil {
line, err = s.bufReader.ReadString('\n')
if err != nil {
break
}
parts := strings.Fields(line)
switch parts[0] {
case "cpu":
if len(parts) < 8 {
return 0, derr.ErrorCodeBadCPUFields
}
var totalClockTicks uint64
for _, i := range parts[1:8] {
v, err := strconv.ParseUint(i, 10, 64)
if err != nil {
return 0, derr.ErrorCodeBadCPUInt.WithArgs(i, err)
}
totalClockTicks += v
}
return (totalClockTicks * nanoSecondsPerSecond) /
s.clockTicksPerSecond, nil
}
}
return 0, derr.ErrorCodeBadStatFormat
}
Пожалуйста, сравните "system_cpu_usage" API статистики Docker с выводом нижеприведенной команды для подтверждения:
cat /proc/stat|grep -w cpu|awk '{split($0,a,\" \"); sum=0; for(i=2;i<8;i++)(sum+=a[i])} END{print sum }'