Revert "fix(docker): report current CPU usage instead of the lifetime average" (#6357)

This commit is contained in:
Thomas authored and GitHub committed 2026-07-15 14:55:18 +02:00
1 parent 7e4cb0201b
commit c6c4428f7d
2 files changed
+4 -37

No files matched your search

+4 -17
View File
@@ -300,10 +300,7 @@ async function getContainersWithStatsAsync() {
const stats = await instance
.getContainer(container.Id)
// Not in one-shot mode: the daemon then includes precpu_stats (the
// previous reading), which is required to compute the current CPU usage
// as a delta. One-shot omits it and would only expose lifetime totals.
.stats({ stream: false })
.stats({ stream: false, "one-shot": true })
.catch(
() =>
({
@@ -339,22 +336,12 @@ export function calculateCpuUsage(stats: ContainerStats): number {
}
const numberOfCpus = stats.cpu_stats.online_cpus;
// Docker's own formula for the current (instantaneous) CPU usage: it compares
// the latest reading against the previous one (precpu_stats). Dividing the
// cumulative total_usage by the cumulative system_cpu_usage instead would
// report the container's lifetime average, which stays high long after a load
// spike has ended. precpu_stats is only present when the stats are NOT fetched
// in one-shot mode; when it is absent (e.g. Podman) the deltas fall back to the
// cumulative totals, matching the previous behaviour.
const cpuDelta = stats.cpu_stats.cpu_usage.total_usage - (stats.precpu_stats?.cpu_usage?.total_usage ?? 0);
const systemDelta = (stats.cpu_stats.system_cpu_usage ?? 0) - (stats.precpu_stats?.system_cpu_usage ?? 0);
if (systemDelta <= 0 || cpuDelta < 0) {
const usage = stats.cpu_stats.system_cpu_usage;
if (!usage || usage === 0) {
return 0;
}
return (cpuDelta / systemDelta) * numberOfCpus * 100;
return (stats.cpu_stats.cpu_usage.total_usage / usage) * numberOfCpus * 100;
}
export function calculateMemoryUsage(stats: ContainerStats): number {
@@ -75,26 +75,6 @@ describe("calculateCpuUsage", () => {
// (500 / 100000) * 2 * 100 = 1
expect(calculateCpuUsage(stats)).toBe(1);
});
test("should use the delta against precpu_stats for the current usage", () => {
const stats = createStats({
cpu_stats: { online_cpus: 4, cpu_usage: { total_usage: 1_002_000 }, system_cpu_usage: 20_000 },
precpu_stats: { cpu_usage: { total_usage: 1_000_000 }, system_cpu_usage: 10_000 },
});
// Despite a large lifetime total_usage, only the recent delta counts:
// (2000 / 10000) * 4 * 100 = 80
expect(calculateCpuUsage(stats)).toBe(80);
});
test("should report 0 for a container that was busy over its lifetime but is idle now", () => {
const stats = createStats({
cpu_stats: { online_cpus: 4, cpu_usage: { total_usage: 1_000_000 }, system_cpu_usage: 20_000 },
precpu_stats: { cpu_usage: { total_usage: 1_000_000 }, system_cpu_usage: 10_000 },
});
// No CPU delta since the last reading -> current usage is 0, even though the
// lifetime average would be high. This is the regression the fix addresses.
expect(calculateCpuUsage(stats)).toBe(0);
});
});
describe("calculateMemoryUsage", () => {