diff --git a/agent/stats/utils_unix.go b/agent/stats/utils_unix.go index b68c7a1889d..b4f384c90a3 100644 --- a/agent/stats/utils_unix.go +++ b/agent/stats/utils_unix.go @@ -27,7 +27,7 @@ import ( // dockerStatsToContainerStats returns a new object of the ContainerStats object from docker stats. func dockerStatsToContainerStats(dockerStats *types.StatsJSON) (*ContainerStats, error) { cpuUsage := dockerStats.CPUStats.CPUUsage.TotalUsage / numCores - memoryUsage := dockerStats.MemoryStats.Usage - dockerStats.MemoryStats.Stats["cache"] + memoryUsage := getMemUsage(dockerStats.MemoryStats) storageReadBytes, storageWriteBytes := getStorageStats(dockerStats) networkStats := getNetworkStats(dockerStats) return &ContainerStats{ @@ -40,6 +40,21 @@ func dockerStatsToContainerStats(dockerStats *types.StatsJSON) (*ContainerStats, }, nil } +func getMemUsage(mem types.MemoryStats) uint64 { + if config.CgroupV2 { + // for cgroupv2 systems, mem usage calculation uses the same method that the docker cli uses + // https://github.com/docker/cli/blob/e198123693b1aaa724041fff602c7d75c8fe4b57/cli/command/container/stats_helpers.go#L227-L249 + // see https://github.com/aws/amazon-ecs-agent/issues/3323 + if v, ok := mem.Stats["inactive_file"]; ok && v < mem.Usage { + return mem.Usage - v + } + } + if v, ok := mem.Stats["cache"]; ok && v < mem.Usage { + return mem.Usage - v + } + return mem.Usage +} + func validateDockerStats(dockerStats *types.StatsJSON) error { if config.CgroupV2 { // PercpuUsage is not available in cgroupv2