mirror of
https://github.com/containers/podman.git
synced 2025-06-19 16:33:24 +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.BlockInput, stats.BlockOutput = calculateBlockIO(cgroupStats)
|
||||||
stats.CPUNano = cgroupStats.CPU.Usage.Total
|
stats.CPUNano = cgroupStats.CPU.Usage.Total
|
||||||
|
stats.CPUSystemNano = cgroupStats.CPU.Usage.Kernel
|
||||||
stats.SystemNano = now
|
stats.SystemNano = now
|
||||||
|
stats.PerCPU = cgroupStats.CPU.Usage.PerCPU
|
||||||
// Handle case where the container is not in a network namespace
|
// Handle case where the container is not in a network namespace
|
||||||
if netStats != nil {
|
if netStats != nil {
|
||||||
stats.NetInput = netStats.TxBytes
|
stats.NetInput = netStats.TxBytes
|
||||||
|
@ -2,17 +2,19 @@ package libpod
|
|||||||
|
|
||||||
// ContainerStats contains the statistics information for a running container
|
// ContainerStats contains the statistics information for a running container
|
||||||
type ContainerStats struct {
|
type ContainerStats struct {
|
||||||
ContainerID string
|
ContainerID string
|
||||||
Name string
|
Name string
|
||||||
CPU float64
|
PerCPU []uint64
|
||||||
CPUNano uint64
|
CPU float64
|
||||||
SystemNano uint64
|
CPUNano uint64
|
||||||
MemUsage uint64
|
CPUSystemNano uint64
|
||||||
MemLimit uint64
|
SystemNano uint64
|
||||||
MemPerc float64
|
MemUsage uint64
|
||||||
NetInput uint64
|
MemLimit uint64
|
||||||
NetOutput uint64
|
MemPerc float64
|
||||||
BlockInput uint64
|
NetInput uint64
|
||||||
BlockOutput uint64
|
NetOutput uint64
|
||||||
PIDs uint64
|
BlockInput uint64
|
||||||
|
BlockOutput uint64
|
||||||
|
PIDs uint64
|
||||||
}
|
}
|
||||||
|
@ -61,14 +61,15 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
var preCPUStats docker.CPUStats
|
var preCPUStats docker.CPUStats
|
||||||
if query.Stream {
|
if query.Stream {
|
||||||
preRead = time.Now()
|
preRead = time.Now()
|
||||||
|
systemUsage, _ := cgroups.GetSystemCPUUsage()
|
||||||
preCPUStats = docker.CPUStats{
|
preCPUStats = docker.CPUStats{
|
||||||
CPUUsage: docker.CPUUsage{
|
CPUUsage: docker.CPUUsage{
|
||||||
TotalUsage: stats.CPUNano,
|
TotalUsage: stats.CPUNano,
|
||||||
PercpuUsage: []uint64{uint64(stats.CPU)},
|
PercpuUsage: stats.PerCPU,
|
||||||
UsageInKernelmode: 0,
|
UsageInKernelmode: stats.CPUSystemNano,
|
||||||
UsageInUsermode: 0,
|
UsageInUsermode: stats.CPUNano - stats.CPUSystemNano,
|
||||||
},
|
},
|
||||||
SystemUsage: 0,
|
SystemUsage: systemUsage,
|
||||||
OnlineCPUs: 0,
|
OnlineCPUs: 0,
|
||||||
ThrottlingData: docker.ThrottlingData{},
|
ThrottlingData: docker.ThrottlingData{},
|
||||||
}
|
}
|
||||||
@ -122,6 +123,8 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
InstanceID: "",
|
InstanceID: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
systemUsage, _ := cgroups.GetSystemCPUUsage()
|
||||||
|
|
||||||
s := handlers.Stats{StatsJSON: docker.StatsJSON{
|
s := handlers.Stats{StatsJSON: docker.StatsJSON{
|
||||||
Stats: docker.Stats{
|
Stats: docker.Stats{
|
||||||
Read: time.Now(),
|
Read: time.Now(),
|
||||||
@ -143,11 +146,11 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
CPUStats: docker.CPUStats{
|
CPUStats: docker.CPUStats{
|
||||||
CPUUsage: docker.CPUUsage{
|
CPUUsage: docker.CPUUsage{
|
||||||
TotalUsage: cgroupStat.CPU.Usage.Total,
|
TotalUsage: cgroupStat.CPU.Usage.Total,
|
||||||
PercpuUsage: []uint64{uint64(stats.CPU)},
|
PercpuUsage: cgroupStat.CPU.Usage.PerCPU,
|
||||||
UsageInKernelmode: cgroupStat.CPU.Usage.Kernel,
|
UsageInKernelmode: cgroupStat.CPU.Usage.Kernel,
|
||||||
UsageInUsermode: cgroupStat.CPU.Usage.Total - cgroupStat.CPU.Usage.Kernel,
|
UsageInUsermode: cgroupStat.CPU.Usage.Total - cgroupStat.CPU.Usage.Kernel,
|
||||||
},
|
},
|
||||||
SystemUsage: 0,
|
SystemUsage: systemUsage,
|
||||||
OnlineCPUs: uint32(len(cgroupStat.CPU.Usage.PerCPU)),
|
OnlineCPUs: uint32(len(cgroupStat.CPU.Usage.PerCPU)),
|
||||||
ThrottlingData: docker.ThrottlingData{
|
ThrottlingData: docker.ThrottlingData{
|
||||||
Periods: 0,
|
Periods: 0,
|
||||||
|
@ -536,15 +536,14 @@ func (c *CgroupControl) Stat() (*Metrics, error) {
|
|||||||
return &m, nil
|
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{}
|
ret := map[string][]string{}
|
||||||
p := filepath.Join(cgroupRoot, ctr.path, name)
|
f, err := os.Open(path)
|
||||||
f, err := os.Open(p)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
return nil, errors.Wrapf(err, "open file %s", p)
|
return nil, errors.Wrapf(err, "open file %s", path)
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
scanner := bufio.NewScanner(f)
|
scanner := bufio.NewScanner(f)
|
||||||
@ -557,7 +556,13 @@ func readCgroup2MapFile(ctr *CgroupControl, name string) (map[string][]string, e
|
|||||||
ret[parts[0]] = parts[1:]
|
ret[parts[0]] = parts[1:]
|
||||||
}
|
}
|
||||||
if err := scanner.Err(); err != nil {
|
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
|
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}
|
m.CPU = CPUMetrics{Usage: usage}
|
||||||
return nil
|
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