Skip to content

Commit cfe6b50

Browse files
authored
Merge pull request #2418 from dashpole/oom_5_kernel
Handle the new 5.0 linux format for oom messages
2 parents 7152b60 + f6f5fd2 commit cfe6b50

File tree

2 files changed

+86
-13
lines changed

2 files changed

+86
-13
lines changed

utils/oomparser/oomparser.go

+33-7
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ import (
2626
)
2727

2828
var (
29-
containerRegexp = regexp.MustCompile(`Task in (.*) killed as a result of limit of (.*)`)
29+
legacyContainerRegexp = regexp.MustCompile(`Task in (.*) killed as a result of limit of (.*)`)
30+
// Starting in 5.0 linux kernels, the OOM message changed
31+
containerRegexp = regexp.MustCompile(`oom-kill:constraint=(.*),nodemask=(.*),cpuset=(.*),mems_allowed=(.*),oom_memcg=(.*) (.*),task_memcg=(.*),task=(.*),pid=(.*),uid=(.*)`)
3032
lastLineRegexp = regexp.MustCompile(`Killed process ([0-9]+) \((.+)\)`)
3133
firstLineRegexp = regexp.MustCompile(`invoked oom-killer:`)
3234
)
@@ -51,11 +53,14 @@ type OomInstance struct {
5153
// the absolute name of the container that was killed
5254
// due to the OOM.
5355
VictimContainerName string
56+
// the constraint that triggered the OOM. One of CONSTRAINT_NONE,
57+
// CONSTRAINT_CPUSET, CONSTRAINT_MEMORY_POLICY, CONSTRAINT_MEMCG
58+
Constraint string
5459
}
5560

5661
// gets the container name from a line and adds it to the oomInstance.
57-
func getContainerName(line string, currentOomInstance *OomInstance) error {
58-
parsedLine := containerRegexp.FindStringSubmatch(line)
62+
func getLegacyContainerName(line string, currentOomInstance *OomInstance) error {
63+
parsedLine := legacyContainerRegexp.FindStringSubmatch(line)
5964
if parsedLine == nil {
6065
return nil
6166
}
@@ -64,6 +69,25 @@ func getContainerName(line string, currentOomInstance *OomInstance) error {
6469
return nil
6570
}
6671

72+
// gets the container name from a line and adds it to the oomInstance.
73+
func getContainerName(line string, currentOomInstance *OomInstance) (bool, error) {
74+
parsedLine := containerRegexp.FindStringSubmatch(line)
75+
if parsedLine == nil {
76+
// Fall back to the legacy format if it isn't found here.
77+
return false, getLegacyContainerName(line, currentOomInstance)
78+
}
79+
currentOomInstance.ContainerName = parsedLine[7]
80+
currentOomInstance.VictimContainerName = parsedLine[5]
81+
currentOomInstance.Constraint = parsedLine[1]
82+
pid, err := strconv.Atoi(parsedLine[9])
83+
if err != nil {
84+
return false, err
85+
}
86+
currentOomInstance.Pid = pid
87+
currentOomInstance.ProcessName = parsedLine[8]
88+
return true, nil
89+
}
90+
6791
// gets the pid, name, and date from a line and adds it to oomInstance
6892
func getProcessNamePid(line string, currentOomInstance *OomInstance) (bool, error) {
6993
reList := lastLineRegexp.FindStringSubmatch(line)
@@ -106,13 +130,15 @@ func (self *OomParser) StreamOoms(outStream chan<- *OomInstance) {
106130
TimeOfDeath: msg.Timestamp,
107131
}
108132
for msg := range kmsgEntries {
109-
err := getContainerName(msg.Message, oomCurrentInstance)
133+
finished, err := getContainerName(msg.Message, oomCurrentInstance)
110134
if err != nil {
111135
klog.Errorf("%v", err)
112136
}
113-
finished, err := getProcessNamePid(msg.Message, oomCurrentInstance)
114-
if err != nil {
115-
klog.Errorf("%v", err)
137+
if !finished {
138+
finished, err = getProcessNamePid(msg.Message, oomCurrentInstance)
139+
if err != nil {
140+
klog.Errorf("%v", err)
141+
}
116142
}
117143
if finished {
118144
oomCurrentInstance.TimeOfDeath = msg.Timestamp

utils/oomparser/oomparser_test.go

+53-6
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,33 @@ import (
2323
"github.com/stretchr/testify/assert"
2424
)
2525

26-
const startLine = "ruby invoked oom-killer: gfp_mask=0x201da, order=0, oom_score_adj=0"
27-
const endLine = "Killed process 19667 (evil-program2) total-vm:1460016kB, anon-rss:1414008kB, file-rss:4kB"
28-
const containerLine = "Task in /mem2 killed as a result of limit of /mem3"
26+
const (
27+
startLine = "ruby invoked oom-killer: gfp_mask=0x201da, order=0, oom_score_adj=0"
28+
endLine = "Killed process 19667 (evil-program2) total-vm:1460016kB, anon-rss:1414008kB, file-rss:4kB"
29+
legacyContainerLine = "Task in /mem2 killed as a result of limit of /mem3"
30+
containerLine = "oom-kill:constraint=CONSTRAINT_MEMCG,nodemask=(null),cpuset=ef807430361e6e82b45db92e2e9b6fbec98f419b12c591e655c1a725565e73a8,mems_allowed=0,oom_memcg=/kubepods/burstable/podfbdfe8e3-1c87-4ff2-907 c-b2ec8e25d012,task_memcg=/kubepods/burstable/podfbdfe8e3-1c87-4ff2-907c-b2ec8e25d012/ef807430361e6e82b45db92e2e9b6fbec98f419b12c591e655c1a725565e73a8,task=manager,pid=966,uid=0"
31+
)
2932

30-
func TestGetContainerName(t *testing.T) {
33+
func TestGetLegacyContainerName(t *testing.T) {
3134
currentOomInstance := new(OomInstance)
32-
err := getContainerName(startLine, currentOomInstance)
35+
finished, err := getContainerName(startLine, currentOomInstance)
3336
if err != nil {
3437
t.Errorf("bad line fed to getContainerName should yield no error, but had error %v", err)
3538
}
39+
if finished {
40+
t.Errorf("bad line fed to getContainerName should not result in a finished oom log, but it did")
41+
}
3642
if currentOomInstance.ContainerName != "" {
3743
t.Errorf("bad line fed to getContainerName yielded no container name but set it to %s", currentOomInstance.ContainerName)
3844
}
39-
err = getContainerName(containerLine, currentOomInstance)
45+
finished, err = getContainerName(legacyContainerLine, currentOomInstance)
4046
if err != nil {
4147
t.Errorf("container line fed to getContainerName should yield no error, but had error %v", err)
4248
}
49+
if finished {
50+
t.Errorf("getContainerName with the legacy log line should not result in a finished oom log, but it did")
51+
52+
}
4353
if currentOomInstance.ContainerName != "/mem2" {
4454
t.Errorf("getContainerName should have set containerName to /mem2, not %s", currentOomInstance.ContainerName)
4555
}
@@ -48,6 +58,43 @@ func TestGetContainerName(t *testing.T) {
4858
}
4959
}
5060

61+
func TestGetContainerName(t *testing.T) {
62+
currentOomInstance := new(OomInstance)
63+
finished, err := getContainerName(startLine, currentOomInstance)
64+
if err != nil {
65+
t.Errorf("bad line fed to getContainerName should yield no error, but had error %v", err)
66+
}
67+
if finished {
68+
t.Errorf("bad line fed to getContainerName should not result in a finished oom log, but it did")
69+
}
70+
if currentOomInstance.ContainerName != "" {
71+
t.Errorf("bad line fed to getContainerName yielded no container name but set it to %s", currentOomInstance.ContainerName)
72+
}
73+
finished, err = getContainerName(containerLine, currentOomInstance)
74+
if err != nil {
75+
t.Errorf("container line fed to getContainerName should yield no error, but had error %v", err)
76+
}
77+
if !finished {
78+
t.Errorf("getContainerName with the complete log line should result in a finished oom log, but it did not")
79+
80+
}
81+
if currentOomInstance.ContainerName != "/kubepods/burstable/podfbdfe8e3-1c87-4ff2-907c-b2ec8e25d012/ef807430361e6e82b45db92e2e9b6fbec98f419b12c591e655c1a725565e73a8" {
82+
t.Errorf("getContainerName should have set containerName to /kubepods/burstable/podfbdfe8e3-1c87-4ff2-907c-b2ec8e25d012/ef807430361e6e82b45db92e2e9b6fbec98f419b12c591e655c1a725565e73a8, not %s", currentOomInstance.ContainerName)
83+
}
84+
if currentOomInstance.VictimContainerName != "/kubepods/burstable/podfbdfe8e3-1c87-4ff2-907" {
85+
t.Errorf("getContainerName should have set victimContainerName to /kubepods/burstable/podfbdfe8e3-1c87-4ff2-907, not %s", currentOomInstance.VictimContainerName)
86+
}
87+
if currentOomInstance.Pid != 966 {
88+
t.Errorf("getContainerName should have set Pid to 966, not %d", currentOomInstance.Pid)
89+
}
90+
if currentOomInstance.ProcessName != "manager" {
91+
t.Errorf("getContainerName should have set ProcessName to manager, not %s", currentOomInstance.ProcessName)
92+
}
93+
if currentOomInstance.Constraint != "CONSTRAINT_MEMCG" {
94+
t.Errorf("getContainerName should have set ProcessName to CONSTRAINT_MEMCG, not %s", currentOomInstance.Constraint)
95+
}
96+
}
97+
5198
func TestGetProcessNamePid(t *testing.T) {
5299
currentOomInstance := new(OomInstance)
53100
couldParseLine, err := getProcessNamePid(startLine, currentOomInstance)

0 commit comments

Comments
 (0)