diff options
author | Michael Rosenfeld <mrosenfeld@google.com> | 2016-12-08 11:44:46 -0800 |
---|---|---|
committer | Michael Rosenfeld <mrosenfeld@google.com> | 2016-12-13 10:11:20 -0800 |
commit | f8181495ecc95c356452fda7662dae74f9a2406e (patch) | |
tree | 996b0ca75be37706ef33f61a4d863fe6b1c9d0ed | |
parent | bd7041191323e65f977135668c94a42df99f2445 (diff) | |
download | loganalysis-f8181495ecc95c356452fda7662dae74f9a2406e.tar.gz |
Add LMK and page allocation failure parsing from kernel logs
Bug: 33272479
Test: Added to KernelLogParserTest class
Change-Id: I579a2ddae503f98f9b4447f57f9547d125f808f2
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", |