1 Star 0 Fork 1

Derek Ray/podman

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
stats.go 3.43 KB
一键复制 编辑 原始数据 按行查看 历史
baude 提交于 2018-10-01 12:10 . Add ability for ubuntu to be tested
// +build linux
package libpod
import (
"strings"
"syscall"
"time"
"github.com/containerd/cgroups"
"github.com/pkg/errors"
)
// GetContainerStats gets the running stats for a given container
func (c *Container) GetContainerStats(previousStats *ContainerStats) (*ContainerStats, error) {
stats := new(ContainerStats)
stats.ContainerID = c.ID()
stats.Name = c.Name()
if !c.batched {
c.lock.Lock()
defer c.lock.Unlock()
if err := c.syncContainer(); err != nil {
return stats, err
}
}
if c.state.State != ContainerStateRunning {
return stats, ErrCtrStateInvalid
}
cgroupPath, err := c.CGroupPath()
if err != nil {
return nil, err
}
v1CGroups := GetV1CGroups(getExcludedCGroups())
cgroup, err := cgroups.Load(v1CGroups, cgroups.StaticPath(cgroupPath))
if err != nil {
return stats, errors.Wrapf(err, "unable to load cgroup at %s", cgroupPath)
}
// Ubuntu does not have swap memory in cgroups because swap is often not enabled.
cgroupStats, err := cgroup.Stat(cgroups.IgnoreNotExist)
if err != nil {
return stats, errors.Wrapf(err, "unable to obtain cgroup stats")
}
conState := c.state.State
if err != nil {
return stats, errors.Wrapf(err, "unable to determine container state")
}
netStats, err := getContainerNetIO(c)
if err != nil {
return nil, err
}
previousCPU := previousStats.CPUNano
previousSystem := previousStats.SystemNano
stats.CPU = calculateCPUPercent(cgroupStats, previousCPU, previousSystem)
stats.MemUsage = cgroupStats.Memory.Usage.Usage
stats.MemLimit = getMemLimit(cgroupStats.Memory.Usage.Limit)
stats.MemPerc = (float64(stats.MemUsage) / float64(stats.MemLimit)) * 100
stats.PIDs = 0
if conState == ContainerStateRunning {
stats.PIDs = cgroupStats.Pids.Current
}
stats.BlockInput, stats.BlockOutput = calculateBlockIO(cgroupStats)
stats.CPUNano = cgroupStats.CPU.Usage.Total
stats.SystemNano = cgroupStats.CPU.Usage.Kernel
// Handle case where the container is not in a network namespace
if netStats != nil {
stats.NetInput = netStats.TxBytes
stats.NetOutput = netStats.RxBytes
} else {
stats.NetInput = 0
stats.NetOutput = 0
}
return stats, nil
}
// getMemory limit returns the memory limit for a given cgroup
// If the configured memory limit is larger than the total memory on the sys, the
// physical system memory size is returned
func getMemLimit(cgroupLimit uint64) uint64 {
si := &syscall.Sysinfo_t{}
err := syscall.Sysinfo(si)
if err != nil {
return cgroupLimit
}
physicalLimit := uint64(si.Totalram)
if cgroupLimit > physicalLimit {
return physicalLimit
}
return cgroupLimit
}
func calculateCPUPercent(stats *cgroups.Metrics, previousCPU, previousSystem uint64) float64 {
var (
cpuPercent = 0.0
cpuDelta = float64(stats.CPU.Usage.Total - previousCPU)
systemDelta = float64(uint64(time.Now().UnixNano()) - previousSystem)
)
if systemDelta > 0.0 && cpuDelta > 0.0 {
// gets a ratio of container cpu usage total, multiplies it by the number of cores (4 cores running
// at 100% utilization should be 400% utilization), and multiplies that by 100 to get a percentage
cpuPercent = (cpuDelta / systemDelta) * float64(len(stats.CPU.Usage.PerCPU)) * 100
}
return cpuPercent
}
func calculateBlockIO(stats *cgroups.Metrics) (read uint64, write uint64) {
for _, blkIOEntry := range stats.Blkio.IoServiceBytesRecursive {
switch strings.ToLower(blkIOEntry.Op) {
case "read":
read += blkIOEntry.Value
case "write":
write += blkIOEntry.Value
}
}
return
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/derekhjray/podman.git
git@gitee.com:derekhjray/podman.git
derekhjray
podman
podman
v1.0.1

搜索帮助