mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
Add reading of information from cpuacct.usage_all
Remove logrus logs from tests Signed-off-by: Katarzyna Kujawa <katarzyna.kujawa@intel.com>
This commit is contained in:
@@ -125,6 +125,8 @@ func convertLibcontainerStats(ls *libcontainer.Stats) *types.Stats {
|
||||
s.CPU.Usage.User = cg.CpuStats.CpuUsage.UsageInUsermode
|
||||
s.CPU.Usage.Total = cg.CpuStats.CpuUsage.TotalUsage
|
||||
s.CPU.Usage.Percpu = cg.CpuStats.CpuUsage.PercpuUsage
|
||||
s.CPU.Usage.PercpuKernel = cg.CpuStats.CpuUsage.PercpuUsageInKernelmode
|
||||
s.CPU.Usage.PercpuUser = cg.CpuStats.CpuUsage.PercpuUsageInUsermode
|
||||
s.CPU.Throttling.Periods = cg.CpuStats.ThrottlingData.Periods
|
||||
s.CPU.Throttling.ThrottledPeriods = cg.CpuStats.ThrottlingData.ThrottledPeriods
|
||||
s.CPU.Throttling.ThrottledTime = cg.CpuStats.ThrottlingData.ThrottledTime
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -15,9 +17,15 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
cgroupCpuacctStat = "cpuacct.stat"
|
||||
cgroupCpuacctStat = "cpuacct.stat"
|
||||
cgroupCpuacctUsageAll = "cpuacct.usage_all"
|
||||
|
||||
nanosecondsInSecond = 1000000000
|
||||
|
||||
userModeColumn = 1
|
||||
kernelModeColumn = 2
|
||||
cuacctUsageAllColumnsNumber = 3
|
||||
|
||||
// The value comes from `C.sysconf(C._SC_CLK_TCK)`, and
|
||||
// on Linux it's a constant which is safe to be hard coded,
|
||||
// so we can avoid using cgo here. For details, see:
|
||||
@@ -65,8 +73,15 @@ func (s *CpuacctGroup) GetStats(path string, stats *cgroups.Stats) error {
|
||||
return err
|
||||
}
|
||||
|
||||
percpuUsageInKernelmode, percpuUsageInUsermode, err := getPercpuUsageInModes(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stats.CpuStats.CpuUsage.TotalUsage = totalUsage
|
||||
stats.CpuStats.CpuUsage.PercpuUsage = percpuUsage
|
||||
stats.CpuStats.CpuUsage.PercpuUsageInKernelmode = percpuUsageInKernelmode
|
||||
stats.CpuStats.CpuUsage.PercpuUsageInUsermode = percpuUsageInUsermode
|
||||
stats.CpuStats.CpuUsage.UsageInUsermode = userModeUsage
|
||||
stats.CpuStats.CpuUsage.UsageInKernelmode = kernelModeUsage
|
||||
return nil
|
||||
@@ -123,3 +138,42 @@ func getPercpuUsage(path string) ([]uint64, error) {
|
||||
}
|
||||
return percpuUsage, nil
|
||||
}
|
||||
|
||||
func getPercpuUsageInModes(path string) ([]uint64, []uint64, error) {
|
||||
usageKernelMode := []uint64{}
|
||||
usageUserMode := []uint64{}
|
||||
|
||||
file, err := os.Open(filepath.Join(path, cgroupCpuacctUsageAll))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
scanner.Scan() //skipping header line
|
||||
|
||||
for scanner.Scan() {
|
||||
lineFields := strings.SplitN(scanner.Text(), " ", cuacctUsageAllColumnsNumber+1)
|
||||
if len(lineFields) != cuacctUsageAllColumnsNumber {
|
||||
continue
|
||||
}
|
||||
|
||||
usageInKernelMode, err := strconv.ParseUint(lineFields[kernelModeColumn], 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Unable to convert CPU usage in kernel mode to uint64: %s", err)
|
||||
}
|
||||
usageKernelMode = append(usageKernelMode, usageInKernelMode)
|
||||
|
||||
usageInUserMode, err := strconv.ParseUint(lineFields[userModeColumn], 10, 64)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Unable to convert CPU usage in user mode to uint64: %s", err)
|
||||
}
|
||||
usageUserMode = append(usageUserMode, usageInUserMode)
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, nil, fmt.Errorf("Problem in reading %s line by line, %s", cgroupCpuacctUsageAll, err)
|
||||
}
|
||||
|
||||
return usageKernelMode, usageUserMode, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
// +build linux
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
)
|
||||
|
||||
const (
|
||||
cpuAcctUsageContents = "12262454190222160"
|
||||
cpuAcctUsagePerCPUContents = "1564936537989058 1583937096487821 1604195415465681 1596445226820187 1481069084155629 1478735613864327 1477610593414743 1476362015778086"
|
||||
cpuAcctStatContents = "user 452278264\nsystem 291429664"
|
||||
cpuAcctUsageAll = `cpu user system
|
||||
0 962250696038415 637727786389114
|
||||
1 981956408513304 638197595421064
|
||||
2 1002658817529022 638956774598358
|
||||
3 994937703492523 637985531181620
|
||||
4 874843781648690 638837766495476
|
||||
5 872544369885276 638763309884944
|
||||
6 870104915696359 640081778921247
|
||||
7 870202363887496 638716766259495
|
||||
`
|
||||
)
|
||||
|
||||
func TestCpuacctStats(t *testing.T) {
|
||||
helper := NewCgroupTestUtil("cpuacct.", t)
|
||||
defer helper.cleanup()
|
||||
helper.writeFileContents(map[string]string{
|
||||
"cpuacct.usage": cpuAcctUsageContents,
|
||||
"cpuacct.usage_percpu": cpuAcctUsagePerCPUContents,
|
||||
"cpuacct.stat": cpuAcctStatContents,
|
||||
"cpuacct.usage_all": cpuAcctUsageAll,
|
||||
})
|
||||
|
||||
cpuacct := &CpuacctGroup{}
|
||||
actualStats := *cgroups.NewStats()
|
||||
err := cpuacct.GetStats(helper.CgroupPath, &actualStats)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
expectedStats := cgroups.CpuUsage{
|
||||
TotalUsage: uint64(12262454190222160),
|
||||
PercpuUsage: []uint64{1564936537989058, 1583937096487821, 1604195415465681, 1596445226820187,
|
||||
1481069084155629, 1478735613864327, 1477610593414743, 1476362015778086},
|
||||
PercpuUsageInKernelmode: []uint64{637727786389114, 638197595421064, 638956774598358, 637985531181620,
|
||||
638837766495476, 638763309884944, 640081778921247, 638716766259495},
|
||||
PercpuUsageInUsermode: []uint64{962250696038415, 981956408513304, 1002658817529022, 994937703492523,
|
||||
874843781648690, 872544369885276, 870104915696359, 870202363887496},
|
||||
UsageInKernelmode: (uint64(291429664) * nanosecondsInSecond) / clockTicks,
|
||||
UsageInUsermode: (uint64(452278264) * nanosecondsInSecond) / clockTicks,
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expectedStats, actualStats.CpuStats.CpuUsage) {
|
||||
t.Errorf("Expected CPU usage %#v but found %#v\n",
|
||||
expectedStats, actualStats.CpuStats.CpuUsage)
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,12 @@ type CpuUsage struct {
|
||||
// Total CPU time consumed per core.
|
||||
// Units: nanoseconds.
|
||||
PercpuUsage []uint64 `json:"percpu_usage,omitempty"`
|
||||
// CPU time consumed per core in kernel mode
|
||||
// Units: nanoseconds.
|
||||
PercpuUsageInKernelmode []uint64 `json:"percpu_usage_in_kernelmode"`
|
||||
// CPU time consumed per core in user mode
|
||||
// Units: nanoseconds.
|
||||
PercpuUsageInUsermode []uint64 `json:"percpu_usage_in_usermode"`
|
||||
// Time spent by tasks of the cgroup in kernel mode.
|
||||
// Units: nanoseconds.
|
||||
UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
|
||||
|
||||
+6
-4
@@ -55,10 +55,12 @@ type Throttling struct {
|
||||
|
||||
type CpuUsage struct {
|
||||
// Units: nanoseconds.
|
||||
Total uint64 `json:"total,omitempty"`
|
||||
Percpu []uint64 `json:"percpu,omitempty"`
|
||||
Kernel uint64 `json:"kernel"`
|
||||
User uint64 `json:"user"`
|
||||
Total uint64 `json:"total,omitempty"`
|
||||
Percpu []uint64 `json:"percpu,omitempty"`
|
||||
PercpuKernel []uint64 `json:"percpu_kernel,omitempty"`
|
||||
PercpuUser []uint64 `json:"percpu_user,omitempty"`
|
||||
Kernel uint64 `json:"kernel"`
|
||||
User uint64 `json:"user"`
|
||||
}
|
||||
|
||||
type Cpu struct {
|
||||
|
||||
Reference in New Issue
Block a user