summaryrefslogtreecommitdiff
path: root/libkpod/stats.go
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2017-11-01 11:24:59 -0400
committerMatthew Heon <matthew.heon@gmail.com>2017-11-01 11:24:59 -0400
commita031b83a09a8628435317a03f199cdc18b78262f (patch)
treebc017a96769ce6de33745b8b0b1304ccf38e9df0 /libkpod/stats.go
parent2b74391cd5281f6fdf391ff8ad50fd1490f6bf89 (diff)
downloadpodman-a031b83a09a8628435317a03f199cdc18b78262f.tar.gz
podman-a031b83a09a8628435317a03f199cdc18b78262f.tar.bz2
podman-a031b83a09a8628435317a03f199cdc18b78262f.zip
Initial checkin from CRI-O repo
Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
Diffstat (limited to 'libkpod/stats.go')
-rw-r--r--libkpod/stats.go111
1 files changed, 111 insertions, 0 deletions
diff --git a/libkpod/stats.go b/libkpod/stats.go
new file mode 100644
index 000000000..f4d645d65
--- /dev/null
+++ b/libkpod/stats.go
@@ -0,0 +1,111 @@
+package libkpod
+
+import (
+ "path/filepath"
+ "syscall"
+ "time"
+
+ "strings"
+
+ "github.com/kubernetes-incubator/cri-o/oci"
+ "github.com/opencontainers/runc/libcontainer"
+)
+
+// ContainerStats contains the statistics information for a running container
+type ContainerStats struct {
+ Container string
+ CPU float64
+ cpuNano uint64
+ systemNano uint64
+ MemUsage uint64
+ MemLimit uint64
+ MemPerc float64
+ NetInput uint64
+ NetOutput uint64
+ BlockInput uint64
+ BlockOutput uint64
+ PIDs uint64
+}
+
+// GetContainerStats gets the running stats for a given container
+func (c *ContainerServer) GetContainerStats(ctr *oci.Container, previousStats *ContainerStats) (*ContainerStats, error) {
+ previousCPU := previousStats.cpuNano
+ previousSystem := previousStats.systemNano
+ libcontainerStats, err := c.LibcontainerStats(ctr)
+ if err != nil {
+ return nil, err
+ }
+ cgroupStats := libcontainerStats.CgroupStats
+ stats := new(ContainerStats)
+ stats.Container = ctr.ID()
+ stats.CPU = calculateCPUPercent(libcontainerStats, previousCPU, previousSystem)
+ stats.MemUsage = cgroupStats.MemoryStats.Usage.Usage
+ stats.MemLimit = getMemLimit(cgroupStats.MemoryStats.Usage.Limit)
+ stats.MemPerc = float64(stats.MemUsage) / float64(stats.MemLimit)
+ stats.PIDs = cgroupStats.PidsStats.Current
+ stats.BlockInput, stats.BlockOutput = calculateBlockIO(libcontainerStats)
+ stats.NetInput, stats.NetOutput = getContainerNetIO(libcontainerStats)
+
+ return stats, nil
+}
+
+func loadFactory(root string) (libcontainer.Factory, error) {
+ abs, err := filepath.Abs(root)
+ if err != nil {
+ return nil, err
+ }
+ cgroupManager := libcontainer.Cgroupfs
+ return libcontainer.New(abs, cgroupManager, libcontainer.CriuPath(""))
+}
+
+// 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
+}
+
+// Returns the total number of bytes transmitted and received for the given container stats
+func getContainerNetIO(stats *libcontainer.Stats) (received uint64, transmitted uint64) {
+ for _, iface := range stats.Interfaces {
+ received += iface.RxBytes
+ transmitted += iface.TxBytes
+ }
+ return
+}
+
+func calculateCPUPercent(stats *libcontainer.Stats, previousCPU, previousSystem uint64) float64 {
+ var (
+ cpuPercent = 0.0
+ cpuDelta = float64(stats.CgroupStats.CpuStats.CpuUsage.TotalUsage - 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.CgroupStats.CpuStats.CpuUsage.PercpuUsage)) * 100
+ }
+ return cpuPercent
+}
+
+func calculateBlockIO(stats *libcontainer.Stats) (read uint64, write uint64) {
+ for _, blkIOEntry := range stats.CgroupStats.BlkioStats.IoServiceBytesRecursive {
+ switch strings.ToLower(blkIOEntry.Op) {
+ case "read":
+ read += blkIOEntry.Value
+ case "write":
+ write += blkIOEntry.Value
+ }
+ }
+ return
+}