diff --git a/containerd-shim-v2/metrics.go b/containerd-shim-v2/metrics.go index cb13f14a36..c936966bdf 100644 --- a/containerd-shim-v2/metrics.go +++ b/containerd-shim-v2/metrics.go @@ -19,7 +19,7 @@ func marshalMetrics(s *service, containerID string) (*google_protobuf.Any, error return nil, err } - metrics := statsToMetrics(stats.CgroupStats) + metrics := statsToMetrics(&stats) data, err := typeurl.MarshalAny(metrics) if err != nil { @@ -29,42 +29,164 @@ func marshalMetrics(s *service, containerID string) (*google_protobuf.Any, error return data, nil } -func statsToMetrics(cgStats *vc.CgroupStats) *cgroups.Metrics { - var hugetlb []*cgroups.HugetlbStat - for pageSize, v := range cgStats.HugetlbStats { - hugetlb = append( - hugetlb, +func statsToMetrics(stats *vc.ContainerStats) *cgroups.Metrics { + metrics := &cgroups.Metrics{} + + if stats.CgroupStats != nil { + metrics = &cgroups.Metrics{ + Hugetlb: setHugetlbStats(stats.CgroupStats.HugetlbStats), + Pids: setPidsStats(stats.CgroupStats.PidsStats), + CPU: setCPUStats(stats.CgroupStats.CPUStats), + Memory: setMemoryStats(stats.CgroupStats.MemoryStats), + Blkio: setBlkioStats(stats.CgroupStats.BlkioStats), + } + } + + metrics.Network = setNetworkStats(stats.NetworkStats) + + return metrics +} + +func setHugetlbStats(vcHugetlb map[string]vc.HugetlbStats) []*cgroups.HugetlbStat { + var hugetlbStats []*cgroups.HugetlbStat + for _, v := range vcHugetlb { + hugetlbStats = append( + hugetlbStats, &cgroups.HugetlbStat{ - Usage: v.Usage, - Max: v.MaxUsage, - Failcnt: v.Failcnt, - Pagesize: pageSize, + Usage: v.Usage, + Max: v.MaxUsage, + Failcnt: v.Failcnt, }) } + return hugetlbStats +} + +func setPidsStats(vcPids vc.PidsStats) *cgroups.PidsStat { + pidsStats := &cgroups.PidsStat{ + Current: vcPids.Current, + Limit: vcPids.Limit, + } + + return pidsStats +} + +func setCPUStats(vcCPU vc.CPUStats) *cgroups.CPUStat { + var perCPU []uint64 - perCPU = append(perCPU, cgStats.CPUStats.CPUUsage.PercpuUsage...) + perCPU = append(perCPU, vcCPU.CPUUsage.PercpuUsage...) + + cpuStats := &cgroups.CPUStat{ + Usage: &cgroups.CPUUsage{ + Total: vcCPU.CPUUsage.TotalUsage, + Kernel: vcCPU.CPUUsage.UsageInKernelmode, + User: vcCPU.CPUUsage.UsageInUsermode, + PerCPU: perCPU, + }, + Throttling: &cgroups.Throttle{ + Periods: vcCPU.ThrottlingData.Periods, + ThrottledPeriods: vcCPU.ThrottlingData.ThrottledPeriods, + ThrottledTime: vcCPU.ThrottlingData.ThrottledTime, + }, + } + + return cpuStats +} - metrics := &cgroups.Metrics{ - Hugetlb: hugetlb, - Pids: &cgroups.PidsStat{ - Current: cgStats.PidsStats.Current, - Limit: cgStats.PidsStats.Limit, +func setMemoryStats(vcMemory vc.MemoryStats) *cgroups.MemoryStat { + memoryStats := &cgroups.MemoryStat{ + Usage: &cgroups.MemoryEntry{ + Limit: vcMemory.Usage.Limit, + Usage: vcMemory.Usage.Usage, + Max: vcMemory.Usage.MaxUsage, + Failcnt: vcMemory.Usage.Failcnt, }, - CPU: &cgroups.CPUStat{ - Usage: &cgroups.CPUUsage{ - Total: cgStats.CPUStats.CPUUsage.TotalUsage, - PerCPU: perCPU, - }, + Swap: &cgroups.MemoryEntry{ + Limit: vcMemory.SwapUsage.Limit, + Usage: vcMemory.SwapUsage.Usage, + Max: vcMemory.SwapUsage.MaxUsage, + Failcnt: vcMemory.SwapUsage.Failcnt, }, - Memory: &cgroups.MemoryStat{ - Cache: cgStats.MemoryStats.Cache, - Usage: &cgroups.MemoryEntry{ - Limit: cgStats.MemoryStats.Usage.Limit, - Usage: cgStats.MemoryStats.Usage.Usage, - }, + Kernel: &cgroups.MemoryEntry{ + Limit: vcMemory.KernelUsage.Limit, + Usage: vcMemory.KernelUsage.Usage, + Max: vcMemory.KernelUsage.MaxUsage, + Failcnt: vcMemory.KernelUsage.Failcnt, + }, + KernelTCP: &cgroups.MemoryEntry{ + Limit: vcMemory.KernelTCPUsage.Limit, + Usage: vcMemory.KernelTCPUsage.Usage, + Max: vcMemory.KernelTCPUsage.MaxUsage, + Failcnt: vcMemory.KernelTCPUsage.Failcnt, }, } - return metrics + if vcMemory.UseHierarchy { + memoryStats.Cache = vcMemory.Stats["total_cache"] + memoryStats.RSS = vcMemory.Stats["total_rss"] + memoryStats.MappedFile = vcMemory.Stats["total_mapped_file"] + } else { + memoryStats.Cache = vcMemory.Stats["cache"] + memoryStats.RSS = vcMemory.Stats["rss"] + memoryStats.MappedFile = vcMemory.Stats["mapped_file"] + } + if v, ok := vcMemory.Stats["pgfault"]; ok { + memoryStats.PgFault = v + } + if v, ok := vcMemory.Stats["pgmajfault"]; ok { + memoryStats.PgMajFault = v + } + if v, ok := vcMemory.Stats["total_inactive_file"]; ok { + memoryStats.TotalInactiveFile = v + } + + return memoryStats +} + +func setBlkioStats(vcBlkio vc.BlkioStats) *cgroups.BlkIOStat { + blkioStats := &cgroups.BlkIOStat{ + IoServiceBytesRecursive: copyBlkio(vcBlkio.IoServiceBytesRecursive), + IoServicedRecursive: copyBlkio(vcBlkio.IoServicedRecursive), + IoQueuedRecursive: copyBlkio(vcBlkio.IoQueuedRecursive), + SectorsRecursive: copyBlkio(vcBlkio.SectorsRecursive), + IoServiceTimeRecursive: copyBlkio(vcBlkio.IoServiceTimeRecursive), + IoWaitTimeRecursive: copyBlkio(vcBlkio.IoWaitTimeRecursive), + IoMergedRecursive: copyBlkio(vcBlkio.IoMergedRecursive), + IoTimeRecursive: copyBlkio(vcBlkio.IoTimeRecursive), + } + + return blkioStats +} + +func copyBlkio(s []vc.BlkioStatEntry) []*cgroups.BlkIOEntry { + ret := make([]*cgroups.BlkIOEntry, len(s)) + for i, v := range s { + ret[i] = &cgroups.BlkIOEntry{ + Op: v.Op, + Major: v.Major, + Minor: v.Minor, + Value: v.Value, + } + } + + return ret +} + +func setNetworkStats(vcNetwork []*vc.NetworkStats) []*cgroups.NetworkStat { + networkStats := make([]*cgroups.NetworkStat, len(vcNetwork)) + for i, v := range vcNetwork { + networkStats[i] = &cgroups.NetworkStat{ + Name: v.Name, + RxBytes: v.RxBytes, + RxPackets: v.RxPackets, + RxErrors: v.RxErrors, + RxDropped: v.RxDropped, + TxBytes: v.TxBytes, + TxPackets: v.TxPackets, + TxErrors: v.TxErrors, + TxDropped: v.TxDropped, + } + } + + return networkStats } diff --git a/virtcontainers/container.go b/virtcontainers/container.go index dca9df5f0f..dc1fe9d377 100644 --- a/virtcontainers/container.go +++ b/virtcontainers/container.go @@ -194,9 +194,25 @@ type CgroupStats struct { HugetlbStats map[string]HugetlbStats `json:"hugetlb_stats,omitempty"` } +// NetworkStats describe all network stats. +type NetworkStats struct { + // Name is the name of the network interface. + Name string `json:"name,omitempty"` + + RxBytes uint64 `json:"rx_bytes,omitempty"` + RxPackets uint64 `json:"rx_packets,omitempty"` + RxErrors uint64 `json:"rx_errors,omitempty"` + RxDropped uint64 `json:"rx_dropped,omitempty"` + TxBytes uint64 `json:"tx_bytes,omitempty"` + TxPackets uint64 `json:"tx_packets,omitempty"` + TxErrors uint64 `json:"tx_errors,omitempty"` + TxDropped uint64 `json:"tx_dropped,omitempty"` +} + // ContainerStats describes a container stats. type ContainerStats struct { - CgroupStats *CgroupStats + CgroupStats *CgroupStats + NetworkStats []*NetworkStats } // ContainerResources describes container resources