//go:build !remote package compat import ( "encoding/json" "time" "github.com/containers/podman/v5/libpod" "github.com/containers/podman/v5/libpod/define" "github.com/docker/docker/api/types/container" runccgroups "github.com/opencontainers/cgroups" "github.com/sirupsen/logrus" "go.podman.io/common/pkg/cgroups" "go.podman.io/storage/pkg/system" ) func getPreCPUStats(stats *define.ContainerStats) CPUStats { systemUsage, _ := cgroups.SystemCPUUsage() return CPUStats{ CPUUsage: container.CPUUsage{ TotalUsage: stats.CPUNano, PercpuUsage: stats.PerCPU, UsageInKernelmode: stats.CPUSystemNano, UsageInUsermode: stats.CPUNano - stats.CPUSystemNano, }, CPU: stats.CPU, SystemUsage: systemUsage, OnlineCPUs: 0, ThrottlingData: container.ThrottlingData{}, } } func statsContainerJSON(ctnr *libpod.Container, stats *define.ContainerStats, preCPUStats CPUStats, onlineCPUs int) (StatsJSON, error) { // Container stats inspect, err := ctnr.Inspect(false) if err != nil { logrus.Errorf("Unable to inspect container: %v", err) return StatsJSON{}, err } // Cgroup stats cgroupPath, err := ctnr.CgroupPath() if err != nil { logrus.Errorf("Unable to get cgroup path of container: %v", err) return StatsJSON{}, err } cgroup, err := cgroups.Load(cgroupPath) if err != nil { logrus.Errorf("Unable to load cgroup: %v", err) return StatsJSON{}, err } cgroupStat, err := cgroup.Stat() if err != nil { logrus.Errorf("Unable to get cgroup stats: %v", err) return StatsJSON{}, err } net := make(map[string]container.NetworkStats) for netName, netStats := range stats.Network { net[netName] = container.NetworkStats{ RxBytes: netStats.RxBytes, RxPackets: netStats.RxPackets, RxErrors: netStats.RxErrors, RxDropped: netStats.RxDropped, TxBytes: netStats.TxBytes, TxPackets: netStats.TxPackets, TxErrors: netStats.TxErrors, TxDropped: netStats.TxDropped, EndpointID: inspect.NetworkSettings.EndpointID, InstanceID: "", } } resources := ctnr.LinuxResources() memoryLimit := cgroupStat.MemoryStats.Usage.Limit if resources != nil && resources.Memory != nil && *resources.Memory.Limit > 0 { memoryLimit = uint64(*resources.Memory.Limit) } memInfo, err := system.ReadMemInfo() if err != nil { logrus.Errorf("Unable to get cgroup stats: %v", err) return StatsJSON{}, err } // cap the memory limit to the available memory. if memInfo.MemTotal > 0 && memoryLimit > uint64(memInfo.MemTotal) { memoryLimit = uint64(memInfo.MemTotal) } systemUsage, _ := cgroups.SystemCPUUsage() return StatsJSON{ Stats: Stats{ Read: time.Now(), PidsStats: container.PidsStats{ Current: cgroupStat.PidsStats.Current, Limit: 0, }, BlkioStats: container.BlkioStats{ IoServiceBytesRecursive: toBlkioStatEntry(cgroupStat.BlkioStats.IoServiceBytesRecursive), IoServicedRecursive: nil, IoQueuedRecursive: nil, IoServiceTimeRecursive: nil, IoWaitTimeRecursive: nil, IoMergedRecursive: nil, IoTimeRecursive: nil, SectorsRecursive: nil, }, CPUStats: CPUStats{ CPUUsage: container.CPUUsage{ TotalUsage: cgroupStat.CpuStats.CpuUsage.TotalUsage, PercpuUsage: cgroupStat.CpuStats.CpuUsage.PercpuUsage, UsageInKernelmode: cgroupStat.CpuStats.CpuUsage.UsageInKernelmode, UsageInUsermode: cgroupStat.CpuStats.CpuUsage.TotalUsage - cgroupStat.CpuStats.CpuUsage.UsageInKernelmode, }, CPU: stats.CPU, SystemUsage: systemUsage, OnlineCPUs: uint32(onlineCPUs), ThrottlingData: container.ThrottlingData{ Periods: 0, ThrottledPeriods: 0, ThrottledTime: 0, }, }, PreCPUStats: preCPUStats, MemoryStats: container.MemoryStats{ Usage: cgroupStat.MemoryStats.Usage.Usage, MaxUsage: cgroupStat.MemoryStats.Usage.MaxUsage, Stats: nil, Failcnt: 0, Limit: memoryLimit, Commit: 0, CommitPeak: 0, PrivateWorkingSet: 0, }, }, Name: stats.Name, ID: stats.ContainerID, Networks: net, }, nil } func toBlkioStatEntry(entries []runccgroups.BlkioStatEntry) []container.BlkioStatEntry { results := make([]container.BlkioStatEntry, len(entries)) for i, e := range entries { bits, err := json.Marshal(e) if err != nil { logrus.Errorf("Unable to marshal blkio stats: %q", err) } if err := json.Unmarshal(bits, &results[i]); err != nil { logrus.Errorf("Unable to unmarshal blkio stats: %q", err) } } return results }