From 62b6e44b36572d06b5c4e9a78103f253d8978057 Mon Sep 17 00:00:00 2001 From: Arnav Singh Date: Mon, 27 Oct 2025 11:01:23 -0700 Subject: [PATCH] Update module memory metric calculation based on dockerd recommendations. The original code calculated the used memory metric as `usage - cache`. However, per [^1], dockerd wants us to do `usage - inactive_file` on cgroup v2 hosts and `usage - total_inactive_file` on cgroup v1 hosts, because `cache` was deprecated after dockerd v19.03 . This is also what docker CLI does [^2] vs what it used to in v19.03 and earlier [^3]. So we replicate the same behavior in EA, but we keep the fallback to `cache` just in case someone is running on an old dockerd, and we check the cgroup v2 field before the cgroup v1 field which is the opposite of what docker CLI does. [^1]: https://docs.docker.com/reference/cli/docker/container/stats/ [^2]: https://github.com/docker/cli/blob/965a0e3518c5740e9fe645ca19aa991b39fb1357/cli/command/container/stats_helpers.go#L239-L249 [^3]: https://github.com/docker/cli/commit/a4a07c643042f4e2a75bf872f38b134502848214#diff-5daf453974f7b038c7e40119b1acd4cdd9a82dc878bc4b4c0925b29b2a1dd107 --- .../models/DockerStats.cs | 10 +++++++++- .../SystemResourcesMetrics.cs | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Docker/models/DockerStats.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Docker/models/DockerStats.cs index 71a40b719f7..4920947d572 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Docker/models/DockerStats.cs +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Docker/models/DockerStats.cs @@ -158,13 +158,21 @@ public MemoryStats(double? privateworkingset, double? limit, double? max_usage, public class MemoryStatsExtended { [JsonConstructor] - public MemoryStatsExtended(double? cache) + public MemoryStatsExtended(double? cache, double? inactive_file, double? total_inactive_file) { this.Cache = Option.Maybe(cache); + this.InactiveFile = Option.Maybe(inactive_file); + this.TotalInactiveFile = Option.Maybe(total_inactive_file); } [JsonProperty("cache", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] public Option Cache { get; } + + [JsonProperty("inactive_file", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] + public Option InactiveFile { get; } + + [JsonProperty("total_inactive_file", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] + public Option TotalInactiveFile { get; } } public class NetworkInfo diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet.Docker/SystemResourcesMetrics.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet.Docker/SystemResourcesMetrics.cs index a00428e42e9..bde0c9f0ffc 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet.Docker/SystemResourcesMetrics.cs +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet.Docker/SystemResourcesMetrics.cs @@ -184,7 +184,7 @@ void SetModuleStats(SystemResources systemResources) ms.Limit.ForEach(limit => this.totalMemory.Set(limit, tags)); ms.Usage.ForEach(usage => { - double actualUsage = usage - ms.Stats.AndThen(s => s.Cache).GetOrElse(0); + double actualUsage = usage - ms.Stats.AndThen(s => s.InactiveFile.Else(s.TotalInactiveFile).Else(s.Cache)).OrDefault(); this.usedMemory.Set((long)actualUsage, tags); }); }