mirror of
https://github.com/containers/podman.git
synced 2025-10-20 20:54:45 +08:00
Podman Stats additional features
added Avg Cpu calculation and CPU up time to podman stats. Adding different feature sets in different PRs, CPU first. resolves #9258 Signed-off-by: cdoern <cbdoer23@g.holycross.edu>
This commit is contained in:
@ -146,7 +146,9 @@ func stats(cmd *cobra.Command, args []string) error {
|
|||||||
func outputStats(reports []define.ContainerStats) error {
|
func outputStats(reports []define.ContainerStats) error {
|
||||||
headers := report.Headers(define.ContainerStats{}, map[string]string{
|
headers := report.Headers(define.ContainerStats{}, map[string]string{
|
||||||
"ID": "ID",
|
"ID": "ID",
|
||||||
|
"UpTime": "CPU TIME",
|
||||||
"CPUPerc": "CPU %",
|
"CPUPerc": "CPU %",
|
||||||
|
"AVGCPU": "Avg CPU %",
|
||||||
"MemUsage": "MEM USAGE / LIMIT",
|
"MemUsage": "MEM USAGE / LIMIT",
|
||||||
"MemUsageBytes": "MEM USAGE / LIMIT",
|
"MemUsageBytes": "MEM USAGE / LIMIT",
|
||||||
"MemPerc": "MEM %",
|
"MemPerc": "MEM %",
|
||||||
@ -166,7 +168,7 @@ func outputStats(reports []define.ContainerStats) error {
|
|||||||
if report.IsJSON(statsOptions.Format) {
|
if report.IsJSON(statsOptions.Format) {
|
||||||
return outputJSON(stats)
|
return outputJSON(stats)
|
||||||
}
|
}
|
||||||
format := "{{.ID}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDS}}\n"
|
format := "{{.ID}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDS}}\t{{.UpTime}}\t{{.AVGCPU}}\n"
|
||||||
if len(statsOptions.Format) > 0 {
|
if len(statsOptions.Format) > 0 {
|
||||||
format = report.NormalizeFormat(statsOptions.Format)
|
format = report.NormalizeFormat(statsOptions.Format)
|
||||||
}
|
}
|
||||||
@ -202,6 +204,14 @@ func (s *containerStats) CPUPerc() string {
|
|||||||
return floatToPercentString(s.CPU)
|
return floatToPercentString(s.CPU)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *containerStats) AVGCPU() string {
|
||||||
|
return floatToPercentString(s.AvgCPU)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *containerStats) Up() string {
|
||||||
|
return (s.UpTime.String())
|
||||||
|
}
|
||||||
|
|
||||||
func (s *containerStats) MemPerc() string {
|
func (s *containerStats) MemPerc() string {
|
||||||
return floatToPercentString(s.ContainerStats.MemPerc)
|
return floatToPercentString(s.ContainerStats.MemPerc)
|
||||||
}
|
}
|
||||||
@ -257,7 +267,9 @@ func outputJSON(stats []containerStats) error {
|
|||||||
type jstat struct {
|
type jstat struct {
|
||||||
Id string `json:"id"` // nolint
|
Id string `json:"id"` // nolint
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
CPUTime string `json:"cpu_time"`
|
||||||
CpuPercent string `json:"cpu_percent"` // nolint
|
CpuPercent string `json:"cpu_percent"` // nolint
|
||||||
|
AverageCPU string `json:"avg_cpu"`
|
||||||
MemUsage string `json:"mem_usage"`
|
MemUsage string `json:"mem_usage"`
|
||||||
MemPerc string `json:"mem_percent"`
|
MemPerc string `json:"mem_percent"`
|
||||||
NetIO string `json:"net_io"`
|
NetIO string `json:"net_io"`
|
||||||
@ -269,7 +281,9 @@ func outputJSON(stats []containerStats) error {
|
|||||||
jstats = append(jstats, jstat{
|
jstats = append(jstats, jstat{
|
||||||
Id: j.ID(),
|
Id: j.ID(),
|
||||||
Name: j.Name,
|
Name: j.Name,
|
||||||
|
CPUTime: j.Up(),
|
||||||
CpuPercent: j.CPUPerc(),
|
CpuPercent: j.CPUPerc(),
|
||||||
|
AverageCPU: j.AVGCPU(),
|
||||||
MemUsage: j.MemUsage(),
|
MemUsage: j.MemUsage(),
|
||||||
MemPerc: j.MemPerc(),
|
MemPerc: j.MemPerc(),
|
||||||
NetIO: j.NetIO(),
|
NetIO: j.NetIO(),
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
package define
|
package define
|
||||||
|
|
||||||
import "github.com/pkg/errors"
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
// ContainerStatus represents the current state of a container
|
// ContainerStatus represents the current state of a container
|
||||||
type ContainerStatus int
|
type ContainerStatus int
|
||||||
@ -120,12 +124,14 @@ func (s ContainerExecStatus) String() string {
|
|||||||
|
|
||||||
// ContainerStats contains the statistics information for a running container
|
// ContainerStats contains the statistics information for a running container
|
||||||
type ContainerStats struct {
|
type ContainerStats struct {
|
||||||
|
AvgCPU float64
|
||||||
ContainerID string
|
ContainerID string
|
||||||
Name string
|
Name string
|
||||||
PerCPU []uint64
|
PerCPU []uint64
|
||||||
CPU float64
|
CPU float64
|
||||||
CPUNano uint64
|
CPUNano uint64
|
||||||
CPUSystemNano uint64
|
CPUSystemNano uint64
|
||||||
|
DataPoints int64
|
||||||
SystemNano uint64
|
SystemNano uint64
|
||||||
MemUsage uint64
|
MemUsage uint64
|
||||||
MemLimit uint64
|
MemLimit uint64
|
||||||
@ -135,4 +141,6 @@ type ContainerStats struct {
|
|||||||
BlockInput uint64
|
BlockInput uint64
|
||||||
BlockOutput uint64
|
BlockOutput uint64
|
||||||
PIDs uint64
|
PIDs uint64
|
||||||
|
UpTime time.Duration
|
||||||
|
Duration uint64
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,11 @@ func (c *Container) GetContainerStats(previousStats *define.ContainerStats) (*de
|
|||||||
|
|
||||||
previousCPU := previousStats.CPUNano
|
previousCPU := previousStats.CPUNano
|
||||||
now := uint64(time.Now().UnixNano())
|
now := uint64(time.Now().UnixNano())
|
||||||
|
stats.Duration = cgroupStats.CPU.Usage.Total
|
||||||
|
stats.UpTime = time.Duration(stats.Duration)
|
||||||
stats.CPU = calculateCPUPercent(cgroupStats, previousCPU, now, previousStats.SystemNano)
|
stats.CPU = calculateCPUPercent(cgroupStats, previousCPU, now, previousStats.SystemNano)
|
||||||
|
stats.AvgCPU = calculateAvgCPU(stats.CPU, previousStats.AvgCPU, previousStats.DataPoints)
|
||||||
|
stats.DataPoints = previousStats.DataPoints + 1
|
||||||
stats.MemUsage = cgroupStats.Memory.Usage.Usage
|
stats.MemUsage = cgroupStats.Memory.Usage.Usage
|
||||||
stats.MemLimit = getMemLimit(cgroupStats.Memory.Usage.Limit)
|
stats.MemLimit = getMemLimit(cgroupStats.Memory.Usage.Limit)
|
||||||
stats.MemPerc = (float64(stats.MemUsage) / float64(stats.MemLimit)) * 100
|
stats.MemPerc = (float64(stats.MemUsage) / float64(stats.MemLimit)) * 100
|
||||||
@ -127,3 +131,9 @@ func calculateBlockIO(stats *cgroups.Metrics) (read uint64, write uint64) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calculateAvgCPU calculates the avg CPU percentage given the previous average and the number of data points.
|
||||||
|
func calculateAvgCPU(statsCPU float64, prevAvg float64, prevData int64) float64 {
|
||||||
|
avgPer := ((prevAvg * float64(prevData)) + statsCPU) / (float64(prevData) + 1)
|
||||||
|
return avgPer
|
||||||
|
}
|
||||||
|
@ -83,6 +83,17 @@ var _ = Describe("Podman stats", func() {
|
|||||||
Expect(session.ExitCode()).To(Equal(0))
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman stats only output CPU data", func() {
|
||||||
|
session := podmanTest.RunTopContainer("")
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
session = podmanTest.Podman([]string{"stats", "--all", "--no-stream", "--format", "\"{{.ID}} {{.UpTime}} {{.AVGCPU}}\""})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.LineInOutputContains("UpTime")).To(BeTrue())
|
||||||
|
Expect(session.LineInOutputContains("AVGCPU")).To(BeTrue())
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
})
|
||||||
|
|
||||||
It("podman stats with json output", func() {
|
It("podman stats with json output", func() {
|
||||||
var found bool
|
var found bool
|
||||||
session := podmanTest.RunTopContainer("")
|
session := podmanTest.RunTopContainer("")
|
||||||
|
Reference in New Issue
Block a user