aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pkg/api/handlers/generic/containers_stats.go7
-rw-r--r--pkg/cgroups/cgroups.go15
-rw-r--r--pkg/cgroups/cpu.go39
3 files changed, 54 insertions, 7 deletions
diff --git a/pkg/api/handlers/generic/containers_stats.go b/pkg/api/handlers/generic/containers_stats.go
index cfc14786f..85757c33e 100644
--- a/pkg/api/handlers/generic/containers_stats.go
+++ b/pkg/api/handlers/generic/containers_stats.go
@@ -64,6 +64,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
var preCPUStats docker.CPUStats
if query.Stream {
preRead = time.Now()
+ systemUsage, _ := cgroups.GetSystemCPUUsage()
preCPUStats = docker.CPUStats{
CPUUsage: docker.CPUUsage{
TotalUsage: stats.CPUNano,
@@ -71,7 +72,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
UsageInKernelmode: stats.CPUSystemNano,
UsageInUsermode: stats.CPUNano - stats.CPUSystemNano,
},
- SystemUsage: 0,
+ SystemUsage: systemUsage,
OnlineCPUs: 0,
ThrottlingData: docker.ThrottlingData{},
}
@@ -125,6 +126,8 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
InstanceID: "",
}
+ systemUsage, _ := cgroups.GetSystemCPUUsage()
+
s := handlers.Stats{StatsJSON: docker.StatsJSON{
Stats: docker.Stats{
Read: time.Now(),
@@ -150,7 +153,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
UsageInKernelmode: cgroupStat.CPU.Usage.Kernel,
UsageInUsermode: cgroupStat.CPU.Usage.Total - cgroupStat.CPU.Usage.Kernel,
},
- SystemUsage: 0,
+ SystemUsage: systemUsage,
OnlineCPUs: uint32(len(cgroupStat.CPU.Usage.PerCPU)),
ThrottlingData: docker.ThrottlingData{
Periods: 0,
diff --git a/pkg/cgroups/cgroups.go b/pkg/cgroups/cgroups.go
index 96786223d..6c5b7978c 100644
--- a/pkg/cgroups/cgroups.go
+++ b/pkg/cgroups/cgroups.go
@@ -536,15 +536,14 @@ func (c *CgroupControl) Stat() (*Metrics, error) {
return &m, nil
}
-func readCgroup2MapFile(ctr *CgroupControl, name string) (map[string][]string, error) {
+func readCgroup2MapPath(path string) (map[string][]string, error) {
ret := map[string][]string{}
- p := filepath.Join(cgroupRoot, ctr.path, name)
- f, err := os.Open(p)
+ f, err := os.Open(path)
if err != nil {
if os.IsNotExist(err) {
return ret, nil
}
- return nil, errors.Wrapf(err, "open file %s", p)
+ return nil, errors.Wrapf(err, "open file %s", path)
}
defer f.Close()
scanner := bufio.NewScanner(f)
@@ -557,7 +556,13 @@ func readCgroup2MapFile(ctr *CgroupControl, name string) (map[string][]string, e
ret[parts[0]] = parts[1:]
}
if err := scanner.Err(); err != nil {
- return nil, errors.Wrapf(err, "parsing file %s", p)
+ return nil, errors.Wrapf(err, "parsing file %s", path)
}
return ret, nil
}
+
+func readCgroup2MapFile(ctr *CgroupControl, name string) (map[string][]string, error) {
+ p := filepath.Join(cgroupRoot, ctr.path, name)
+
+ return readCgroup2MapPath(p)
+}
diff --git a/pkg/cgroups/cpu.go b/pkg/cgroups/cpu.go
index a43a76b22..5f0a18031 100644
--- a/pkg/cgroups/cpu.go
+++ b/pkg/cgroups/cpu.go
@@ -121,3 +121,42 @@ func (c *cpuHandler) Stat(ctr *CgroupControl, m *Metrics) error {
m.CPU = CPUMetrics{Usage: usage}
return nil
}
+
+// GetSystemCPUUsage returns the system usage for all the cgroups
+func GetSystemCPUUsage() (uint64, error) {
+ cgroupv2, err := IsCgroup2UnifiedMode()
+ if err != nil {
+ return 0, err
+ }
+ if !cgroupv2 {
+ p := filepath.Join(cgroupRoot, CPUAcct, "cpuacct.usage")
+ return readFileAsUint64(p)
+ }
+
+ files, err := ioutil.ReadDir(cgroupRoot)
+ if err != nil {
+ return 0, errors.Wrapf(err, "read directory %q", cgroupRoot)
+ }
+ var total uint64
+ for _, file := range files {
+ if !file.IsDir() {
+ continue
+ }
+ p := filepath.Join(cgroupRoot, file.Name(), "cpu.stat")
+
+ values, err := readCgroup2MapPath(p)
+ if err != nil {
+ return 0, err
+ }
+
+ if val, found := values["usage_usec"]; found {
+ v, err := strconv.ParseUint(cleanString(val[0]), 10, 0)
+ if err != nil {
+ return 0, err
+ }
+ total += v * 1000
+ }
+
+ }
+ return total, nil
+}