mirror of
https://github.com/containers/podman.git
synced 2025-05-31 15:42:48 +08:00
Merge pull request #5172 from giuseppe/api-fix-cpu-stats
api: fix the CPU stats reported
This commit is contained in:
@ -66,7 +66,9 @@ func (c *Container) GetContainerStats(previousStats *ContainerStats) (*Container
|
||||
}
|
||||
stats.BlockInput, stats.BlockOutput = calculateBlockIO(cgroupStats)
|
||||
stats.CPUNano = cgroupStats.CPU.Usage.Total
|
||||
stats.CPUSystemNano = cgroupStats.CPU.Usage.Kernel
|
||||
stats.SystemNano = now
|
||||
stats.PerCPU = cgroupStats.CPU.Usage.PerCPU
|
||||
// Handle case where the container is not in a network namespace
|
||||
if netStats != nil {
|
||||
stats.NetInput = netStats.TxBytes
|
||||
|
@ -2,17 +2,19 @@ package libpod
|
||||
|
||||
// ContainerStats contains the statistics information for a running container
|
||||
type ContainerStats struct {
|
||||
ContainerID string
|
||||
Name string
|
||||
CPU float64
|
||||
CPUNano uint64
|
||||
SystemNano uint64
|
||||
MemUsage uint64
|
||||
MemLimit uint64
|
||||
MemPerc float64
|
||||
NetInput uint64
|
||||
NetOutput uint64
|
||||
BlockInput uint64
|
||||
BlockOutput uint64
|
||||
PIDs uint64
|
||||
ContainerID string
|
||||
Name string
|
||||
PerCPU []uint64
|
||||
CPU float64
|
||||
CPUNano uint64
|
||||
CPUSystemNano uint64
|
||||
SystemNano uint64
|
||||
MemUsage uint64
|
||||
MemLimit uint64
|
||||
MemPerc float64
|
||||
NetInput uint64
|
||||
NetOutput uint64
|
||||
BlockInput uint64
|
||||
BlockOutput uint64
|
||||
PIDs uint64
|
||||
}
|
||||
|
@ -61,14 +61,15 @@ 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,
|
||||
PercpuUsage: []uint64{uint64(stats.CPU)},
|
||||
UsageInKernelmode: 0,
|
||||
UsageInUsermode: 0,
|
||||
PercpuUsage: stats.PerCPU,
|
||||
UsageInKernelmode: stats.CPUSystemNano,
|
||||
UsageInUsermode: stats.CPUNano - stats.CPUSystemNano,
|
||||
},
|
||||
SystemUsage: 0,
|
||||
SystemUsage: systemUsage,
|
||||
OnlineCPUs: 0,
|
||||
ThrottlingData: docker.ThrottlingData{},
|
||||
}
|
||||
@ -122,6 +123,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(),
|
||||
@ -143,11 +146,11 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
|
||||
CPUStats: docker.CPUStats{
|
||||
CPUUsage: docker.CPUUsage{
|
||||
TotalUsage: cgroupStat.CPU.Usage.Total,
|
||||
PercpuUsage: []uint64{uint64(stats.CPU)},
|
||||
PercpuUsage: cgroupStat.CPU.Usage.PerCPU,
|
||||
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,
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user