summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Rosenfeld <mrosenfeld@google.com>2016-12-08 11:44:46 -0800
committerMichael Rosenfeld <mrosenfeld@google.com>2016-12-13 10:11:20 -0800
commitf8181495ecc95c356452fda7662dae74f9a2406e (patch)
tree996b0ca75be37706ef33f61a4d863fe6b1c9d0ed
parentbd7041191323e65f977135668c94a42df99f2445 (diff)
downloadloganalysis-f8181495ecc95c356452fda7662dae74f9a2406e.tar.gz
Add LMK and page allocation failure parsing from kernel logs
Bug: 33272479 Test: Added to KernelLogParserTest class Change-Id: I579a2ddae503f98f9b4447f57f9547d125f808f2
-rw-r--r--src/com/android/loganalysis/item/KernelLogItem.java26
-rw-r--r--src/com/android/loganalysis/item/LowMemoryKillerItem.java89
-rw-r--r--src/com/android/loganalysis/item/PageAllocationFailureItem.java57
-rw-r--r--src/com/android/loganalysis/parser/KernelLogParser.java33
-rw-r--r--tests/src/com/android/loganalysis/parser/KernelLogParserTest.java66
5 files changed, 270 insertions, 1 deletions
diff --git a/src/com/android/loganalysis/item/KernelLogItem.java b/src/com/android/loganalysis/item/KernelLogItem.java
index 81c84ce..eb86972 100644
--- a/src/com/android/loganalysis/item/KernelLogItem.java
+++ b/src/com/android/loganalysis/item/KernelLogItem.java
@@ -130,6 +130,32 @@ public class KernelLogItem extends GenericItem {
}
/**
+ * Get the list of all {@link LowMemoryKillerItem} events.
+ */
+ public List<LowMemoryKillerItem> getLowMemoryKillerEvents() {
+ List<LowMemoryKillerItem> items = new LinkedList<LowMemoryKillerItem>();
+ for (MiscKernelLogItem item : getEvents()) {
+ if (item instanceof LowMemoryKillerItem) {
+ items.add((LowMemoryKillerItem)item);
+ }
+ }
+ return items;
+ }
+
+ /**
+ * Get the list of all {@link PageAllocationFailureItem} events.
+ */
+ public List<PageAllocationFailureItem> getPageAllocationFailureEvents() {
+ List<PageAllocationFailureItem> items = new LinkedList<PageAllocationFailureItem>();
+ for (MiscKernelLogItem item : getEvents()) {
+ if (item instanceof PageAllocationFailureItem) {
+ items.add((PageAllocationFailureItem)item);
+ }
+ }
+ return items;
+ }
+
+ /**
* {@inheritDoc}
*/
@Override
diff --git a/src/com/android/loganalysis/item/LowMemoryKillerItem.java b/src/com/android/loganalysis/item/LowMemoryKillerItem.java
new file mode 100644
index 0000000..e7a4525
--- /dev/null
+++ b/src/com/android/loganalysis/item/LowMemoryKillerItem.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.loganalysis.item;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+
+/**
+ * An {@link IItem} used to store traces info.
+ * <p>
+ * This stores info about page allocation failures, i.e. order.
+ * </p>
+ */
+public class LowMemoryKillerItem extends MiscKernelLogItem {
+ /** Constant for JSON output */
+ public static final String PID = "PID";
+ /** Constant for JSON output */
+ public static final String PROCESS_NAME = "PROCESS_NAME";
+ /** Constant for JSON output */
+ public static final String ADJUSTMENT = "ADJUSTMENT";
+
+ private static final Set<String> ATTRIBUTES = new HashSet<String>(Arrays.asList(
+ PID, PROCESS_NAME, ADJUSTMENT));
+
+ /**
+ * The constructor for {@link LowMemoryKillerItem}.
+ */
+ public LowMemoryKillerItem() {
+ super(ATTRIBUTES);
+ }
+
+ /**
+ * Get the pid of the killed process.
+ */
+ public int getPid() {
+ return (int) getAttribute(PID);
+ }
+
+ /**
+ * Set the pid of the killed process.
+ */
+ public void setPid(int pid) {
+ setAttribute(PID, pid);
+ }
+
+ /**
+ * Get the name of the killed process.
+ */
+ public String getProcessName() {
+ return (String) getAttribute(PROCESS_NAME);
+ }
+
+ /**
+ * Set the name of the killed process.
+ */
+ public void setProcessName(String name) {
+ setAttribute(PROCESS_NAME, name);
+ }
+
+ /**
+ * Get the adjustment score of the LMK action.
+ */
+ public int getAdjustment() {
+ return (int) getAttribute(ADJUSTMENT);
+ }
+
+ /**
+ * Set the adjustment score of the LMK action.
+ */
+ public void setAdjustment(int adjustment) {
+ setAttribute(ADJUSTMENT, adjustment);
+ }
+}
diff --git a/src/com/android/loganalysis/item/PageAllocationFailureItem.java b/src/com/android/loganalysis/item/PageAllocationFailureItem.java
new file mode 100644
index 0000000..44a85c2
--- /dev/null
+++ b/src/com/android/loganalysis/item/PageAllocationFailureItem.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.loganalysis.item;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+
+/**
+ * An {@link IItem} used to store traces info.
+ * <p>
+ * This stores info about page allocation failures, i.e. order.
+ * </p>
+ */
+public class PageAllocationFailureItem extends MiscKernelLogItem {
+
+ /** Constant for JSON output */
+ public static final String ORDER = "ORDER";
+
+ private static final Set<String> ATTRIBUTES = new HashSet<String>(Arrays.asList(ORDER));
+
+ /**
+ * The constructor for {@link PageAllocationFailureItem}.
+ */
+ public PageAllocationFailureItem() {
+ super(ATTRIBUTES);
+ }
+
+ /**
+ * Get the order of the page allocation failure.
+ */
+ public int getOrder() {
+ return (int) getAttribute(ORDER);
+ }
+
+ /**
+ * Set the order of the page allocation failure.
+ */
+ public void setOrder(int order) {
+ setAttribute(ORDER, order);
+ }
+}
diff --git a/src/com/android/loganalysis/parser/KernelLogParser.java b/src/com/android/loganalysis/parser/KernelLogParser.java
index 2a9deaf..1ae323f 100644
--- a/src/com/android/loganalysis/parser/KernelLogParser.java
+++ b/src/com/android/loganalysis/parser/KernelLogParser.java
@@ -16,7 +16,9 @@
package com.android.loganalysis.parser;
import com.android.loganalysis.item.KernelLogItem;
+import com.android.loganalysis.item.LowMemoryKillerItem;
import com.android.loganalysis.item.MiscKernelLogItem;
+import com.android.loganalysis.item.PageAllocationFailureItem;
import com.android.loganalysis.item.SELinuxItem;
import com.android.loganalysis.util.LogPatternUtil;
import com.android.loganalysis.util.LogTailUtil;
@@ -28,13 +30,16 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
-* A {@link IParser} to parse {@code /proc/last_kmsg} and the output from {@code dmsg}.
+* A {@link IParser} to parse {@code /proc/last_kmsg}, {@code /proc/kmsg}, and the output from
+* {@code dmesg}.
*/
public class KernelLogParser implements IParser {
public static final String KERNEL_RESET = "KERNEL_RESET";
public static final String KERNEL_ERROR = "KERNEL_ERROR";
public static final String SELINUX_DENIAL = "SELINUX_DENIAL";
public static final String NORMAL_REBOOT = "NORMAL_REBOOT";
+ public static final String PAGE_ALLOC_FAILURE = "PAGE_ALLOC_FAILURE";
+ public static final String LOW_MEMORY_KILLER = "LOW_MEMORY_KILLER";
/**
* Matches: [ 0.000000] Message<br />
@@ -44,6 +49,12 @@ public class KernelLogParser implements IParser {
"^(<\\d+>)?\\[\\s*(\\d+\\.\\d{6})\\] (.*)$");
private static final Pattern SELINUX_DENIAL_PATTERN = Pattern.compile(
".*avc:\\s.*scontext=\\w*:\\w*:([\\w\\s]*):\\w*\\s.*");
+ // Matches: page allocation failure: order:3, mode:0x10c0d0
+ private static final Pattern PAGE_ALLOC_FAILURE_PATTERN = Pattern.compile(
+ ".*page\\s+allocation\\s+failure:\\s+order:(\\d+).*");
+ // Matches: Killing '.qcrilmsgtunnel' (3699), adj 100,
+ private static final Pattern LOW_MEMORY_KILLER_PATTERN = Pattern.compile(
+ ".*Killing\\s+'(.*)'\\s+\\((\\d+)\\),.*adj\\s+(\\d+).*");
/**
* Regular expression representing all known bootreasons which are bad.
@@ -163,6 +174,22 @@ public class KernelLogParser implements IParser {
selinuxItem.setSContext(m.group(1));
}
kernelLogItem = selinuxItem;
+ } else if (category.equals(PAGE_ALLOC_FAILURE)) {
+ PageAllocationFailureItem allocItem = new PageAllocationFailureItem();
+ Matcher m = PAGE_ALLOC_FAILURE_PATTERN.matcher(message);
+ if (m.matches()) {
+ allocItem.setOrder(Integer.parseInt(m.group(1)));
+ }
+ kernelLogItem = allocItem;
+ } else if (category.equals(LOW_MEMORY_KILLER)) {
+ LowMemoryKillerItem lmkItem = new LowMemoryKillerItem();
+ Matcher m = LOW_MEMORY_KILLER_PATTERN.matcher(message);
+ if (m.matches()) {
+ lmkItem.setProcessName(m.group(1));
+ lmkItem.setPid(Integer.parseInt(m.group(2)));
+ lmkItem.setAdjustment(Integer.parseInt(m.group(3)));
+ }
+ kernelLogItem = lmkItem;
} else {
kernelLogItem = new MiscKernelLogItem();
}
@@ -229,6 +256,10 @@ public class KernelLogParser implements IParser {
// SELINUX denials
mPatternUtil.addPattern(SELINUX_DENIAL_PATTERN, SELINUX_DENIAL);
+ // Page allocation failures
+ mPatternUtil.addPattern(PAGE_ALLOC_FAILURE_PATTERN, PAGE_ALLOC_FAILURE);
+ // Lowmemorykiller kills
+ mPatternUtil.addPattern(LOW_MEMORY_KILLER_PATTERN, LOW_MEMORY_KILLER);
}
/**
diff --git a/tests/src/com/android/loganalysis/parser/KernelLogParserTest.java b/tests/src/com/android/loganalysis/parser/KernelLogParserTest.java
index 813862e..159a90e 100644
--- a/tests/src/com/android/loganalysis/parser/KernelLogParserTest.java
+++ b/tests/src/com/android/loganalysis/parser/KernelLogParserTest.java
@@ -16,7 +16,9 @@
package com.android.loganalysis.parser;
import com.android.loganalysis.item.KernelLogItem;
+import com.android.loganalysis.item.LowMemoryKillerItem;
import com.android.loganalysis.item.MiscKernelLogItem;
+import com.android.loganalysis.item.PageAllocationFailureItem;
import com.android.loganalysis.item.SELinuxItem;
import com.android.loganalysis.util.LogPatternUtil;
@@ -234,6 +236,70 @@ public class KernelLogParserTest extends TestCase {
assertEquals(SELINUX_DENIAL_STACK, selinuxItem.getStack());
}
+ /**
+ * Test that an LowMemoryKiller event can be parsed out of a list of log lines.
+ */
+ public void testLowMemoryKillerParse() {
+ final String LMK_MESSAGE = "Killing '.qcrilmsgtunnel' (3699), adj 100,";
+ List<String> lines = Arrays.asList(
+ "<4>[ 0.000000] Memory policy: ECC disabled, Data cache writealloc",
+ "<7>[ 7.896355] SELinux: initialized (dev cgroup, type cgroup)" +
+ ", uses genfs_contexts",
+ "<3>[ 43.399164] " + LMK_MESSAGE);
+ KernelLogItem kernelLog = new KernelLogParser().parse(lines);
+
+ assertNotNull(kernelLog);
+ assertEquals(0.0, kernelLog.getStartTime(), 0.0000005);
+ assertEquals(43.399164, kernelLog.getStopTime(), 0.0000005);
+ assertEquals(2, kernelLog.getEvents().size());
+ assertEquals(1, kernelLog.getMiscEvents(KernelLogParser.LOW_MEMORY_KILLER).size());
+ assertEquals(1, kernelLog.getLowMemoryKillerEvents().size());
+
+ MiscKernelLogItem miscItem = kernelLog.getMiscEvents(KernelLogParser.LOW_MEMORY_KILLER)
+ .get(0);
+ assertEquals(43.399164, miscItem.getEventTime(), 0.0000005);
+ assertEquals(KernelLogParser.LOW_MEMORY_KILLER, miscItem.getCategory());
+ assertEquals(LMK_MESSAGE, miscItem.getStack());
+
+ LowMemoryKillerItem lmkItem = kernelLog.getLowMemoryKillerEvents().get(0);
+ assertEquals(KernelLogParser.LOW_MEMORY_KILLER, lmkItem.getCategory());
+ assertEquals(3699, lmkItem.getPid());
+ assertEquals(".qcrilmsgtunnel", lmkItem.getProcessName());
+ assertEquals(100, lmkItem.getAdjustment());
+ assertEquals(LMK_MESSAGE, lmkItem.getStack());
+ }
+
+ /**
+ * Test that page allocation failures can be parsed out of a list of log lines.
+ */
+ public void testPageAllocationFailureParse() {
+ final String ALLOC_FAILURE = "page allocation failure: order:3, mode:0x10c0d0";
+ List<String> lines = Arrays.asList(
+ "<4>[ 0.000000] Memory policy: ECC disabled, Data cache writealloc",
+ "<7>[ 7.896355] SELinux: initialized (dev cgroup, type cgroup)" +
+ ", uses genfs_contexts",
+ "<3>[ 43.399164] " + ALLOC_FAILURE);
+ KernelLogItem kernelLog = new KernelLogParser().parse(lines);
+
+ assertNotNull(kernelLog);
+ assertEquals(0.0, kernelLog.getStartTime(), 0.0000005);
+ assertEquals(43.399164, kernelLog.getStopTime(), 0.0000005);
+ assertEquals(2, kernelLog.getEvents().size());
+ assertEquals(1, kernelLog.getMiscEvents(KernelLogParser.PAGE_ALLOC_FAILURE).size());
+ assertEquals(1, kernelLog.getPageAllocationFailureEvents().size());
+
+ MiscKernelLogItem miscItem = kernelLog.getMiscEvents(KernelLogParser.PAGE_ALLOC_FAILURE)
+ .get(0);
+ assertEquals(43.399164, miscItem.getEventTime(), 0.0000005);
+ assertEquals(KernelLogParser.PAGE_ALLOC_FAILURE, miscItem.getCategory());
+ assertEquals(ALLOC_FAILURE, miscItem.getStack());
+
+ PageAllocationFailureItem failItem = kernelLog.getPageAllocationFailureEvents().get(0);
+ assertEquals(KernelLogParser.PAGE_ALLOC_FAILURE, failItem.getCategory());
+ assertEquals(3, failItem.getOrder());
+ assertEquals(ALLOC_FAILURE, failItem.getStack());
+ }
+
public void testMantaReset() {
final List<String> lines = Arrays.asList("[ 3281.347296] ---fimc_is_ischain_close(0)",
"[ 3281.432055] fimc_is_scalerc_video_close",