Expose oom_kill as part of SwapMemory

oom_kill from `/proc/vmstat` represents the number of times OOM Killer killed a process. It's useful to debug process memory issues.
pull/1782/head
Szymon Matejczyk 2 months ago committed by Szymon Stanislaw Matejczyk
parent c8110d7c08
commit 9baca975ac

@ -97,6 +97,7 @@ type SwapMemoryStat struct {
// Linux specific numbers // Linux specific numbers
// https://www.kernel.org/doc/Documentation/cgroup-v2.txt // https://www.kernel.org/doc/Documentation/cgroup-v2.txt
PgMajFault uint64 `json:"pgMajFault"` PgMajFault uint64 `json:"pgMajFault"`
OomKill uint64 `json:"oomKill"`
} }
func (m VirtualMemoryStat) String() string { func (m VirtualMemoryStat) String() string {

@ -375,6 +375,12 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
continue continue
} }
ret.PgMajFault = value * 4 * 1024 ret.PgMajFault = value * 4 * 1024
case "oom_kill":
value, err := strconv.ParseUint(fields[1], 10, 64)
if err != nil {
continue
}
ret.OomKill = value
} }
} }
return ret, nil return ret, nil

@ -177,3 +177,48 @@ func TestParseSwapsFile_EmptyFile(t *testing.T) {
_, err := parseSwapsFile(context.Background(), strings.NewReader("")) _, err := parseSwapsFile(context.Background(), strings.NewReader(""))
assert.Error(t, err) assert.Error(t, err)
} }
var swapMemoryVmstatTests = []struct {
mockedRootFS string
swap *SwapMemoryStat
}{
{
"oomkill", &SwapMemoryStat{
// not checked
Total: 0,
Used: 0,
Free: 0,
UsedPercent: 0,
// checked
PgIn: 1 * 4 * 1024,
PgOut: 2 * 4 * 1024,
PgFault: 3 * 4 * 1024,
PgMajFault: 4 * 4 * 1024,
Sin: 3 * 4 * 1024,
Sout: 4 * 4 * 1024,
OomKill: 5,
},
},
}
func TestSwapVmstatMemoryLinux(t *testing.T) {
for _, tt := range swapMemoryVmstatTests {
t.Run(tt.mockedRootFS, func(t *testing.T) {
t.Setenv("HOST_PROC", filepath.Join("testdata/linux/swapmemory/", tt.mockedRootFS, "proc"))
stat, err := SwapMemory()
stat.Total = 0
stat.Used = 0
stat.Free = 0
stat.UsedPercent = 0
skipIfNotImplementedErr(t, err)
if err != nil {
t.Errorf("error %v", err)
}
if !reflect.DeepEqual(stat, tt.swap) {
t.Errorf("got: %+v\nwant: %+v", stat, tt.swap)
}
})
}
}

@ -108,8 +108,9 @@ func TestSwapMemoryStat_String(t *testing.T) {
PgOut: 4, PgOut: 4,
PgFault: 5, PgFault: 5,
PgMajFault: 6, PgMajFault: 6,
OomKill: 7,
} }
e := `{"total":10,"used":30,"free":40,"usedPercent":30.1,"sin":1,"sout":2,"pgIn":3,"pgOut":4,"pgFault":5,"pgMajFault":6}` e := `{"total":10,"used":30,"free":40,"usedPercent":30.1,"sin":1,"sout":2,"pgIn":3,"pgOut":4,"pgFault":5,"pgMajFault":6,"oomKill":7}`
if e != fmt.Sprintf("%v", v) { if e != fmt.Sprintf("%v", v) {
t.Errorf("SwapMemoryStat string is invalid: %v", v) t.Errorf("SwapMemoryStat string is invalid: %v", v)
} }

@ -0,0 +1,15 @@
pgpgin 1
pgpgout 2
pswpin 3
pswpout 4
pgalloc_dma 5
pgalloc_dma32 6
pgalloc_normal 7
pgalloc_movable 8
pgfree 9
pgactivate 10
pgdeactivate 1
pglazyfree 2
pgfault 3
pgmajfault 4
oom_kill 5
Loading…
Cancel
Save