Skip to content

Commit c8e5b1e

Browse files
committed
Cumulative stats can't decrease
During removal of the container a stat value might be reported as zero; in this case the caluclation could end up with an extremely large number. If the cumulative stat decreases report zero. Signed-off-by: James Sturtevant <[email protected]> (cherry picked from commit f6677a4) Signed-off-by: James Sturtevant <[email protected]>
1 parent 9498548 commit c8e5b1e

2 files changed

Lines changed: 65 additions & 0 deletions

File tree

pkg/cri/server/container_stats_list_linux.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ func (c *criService) getUsageNanoCores(containerID string, isSandbox bool, curre
123123
return 0, nil
124124
}
125125

126+
// can't go backwards, this value might come in as 0 if the container was just removed
127+
if currentUsageCoreNanoSeconds < oldStats.UsageCoreNanoSeconds {
128+
return 0, nil
129+
}
130+
126131
newUsageNanoCores := uint64(float64(currentUsageCoreNanoSeconds-oldStats.UsageCoreNanoSeconds) /
127132
float64(nanoSeconds) * float64(time.Second/time.Nanosecond))
128133

pkg/cri/server/container_stats_list_linux_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,66 @@ import (
2828
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
2929
)
3030

31+
func TestContainerMetricsCPUNanoCoreUsage(t *testing.T) {
32+
c := newTestCRIService()
33+
timestamp := time.Now()
34+
tenSecondAftertimeStamp := timestamp.Add(time.Second * 10)
35+
36+
for _, test := range []struct {
37+
id string
38+
desc string
39+
firstCPUValue uint64
40+
secondCPUValue uint64
41+
expectedNanoCoreUsageFirst uint64
42+
expectedNanoCoreUsageSecond uint64
43+
}{
44+
{
45+
id: "id1",
46+
desc: "metrics",
47+
firstCPUValue: 50,
48+
secondCPUValue: 500,
49+
expectedNanoCoreUsageFirst: 0,
50+
expectedNanoCoreUsageSecond: 45,
51+
},
52+
{
53+
id: "id2",
54+
desc: "metrics",
55+
firstCPUValue: 234235,
56+
secondCPUValue: 0,
57+
expectedNanoCoreUsageFirst: 0,
58+
expectedNanoCoreUsageSecond: 0,
59+
},
60+
} {
61+
test := test
62+
t.Run(test.desc, func(t *testing.T) {
63+
container, err := containerstore.NewContainer(
64+
containerstore.Metadata{ID: test.id},
65+
)
66+
assert.NoError(t, err)
67+
assert.Nil(t, container.Stats)
68+
err = c.containerStore.Add(container)
69+
assert.NoError(t, err)
70+
71+
cpuUsage, err := c.getUsageNanoCores(test.id, false, test.firstCPUValue, timestamp)
72+
assert.NoError(t, err)
73+
74+
container, err = c.containerStore.Get(test.id)
75+
assert.NoError(t, err)
76+
assert.NotNil(t, container.Stats)
77+
78+
assert.Equal(t, test.expectedNanoCoreUsageFirst, cpuUsage)
79+
80+
cpuUsage, err = c.getUsageNanoCores(test.id, false, test.secondCPUValue, tenSecondAftertimeStamp)
81+
assert.NoError(t, err)
82+
assert.Equal(t, test.expectedNanoCoreUsageSecond, cpuUsage)
83+
84+
container, err = c.containerStore.Get(test.id)
85+
assert.NoError(t, err)
86+
assert.NotNil(t, container.Stats)
87+
})
88+
}
89+
}
90+
3191
func TestGetWorkingSet(t *testing.T) {
3292
for desc, test := range map[string]struct {
3393
memory *v1.MemoryStat

0 commit comments

Comments
 (0)