Skip to content
Snippets Groups Projects
Commit f8181495 authored by Michael Rosenfeld's avatar Michael Rosenfeld
Browse files

Add LMK and page allocation failure parsing from kernel logs

Bug: 33272479
Test: Added to KernelLogParserTest class
Change-Id: I579a2ddae503f98f9b4447f57f9547d125f808f2
parent bd704119
No related branches found
No related tags found
No related merge requests found
...@@ -129,6 +129,32 @@ public class KernelLogItem extends GenericItem { ...@@ -129,6 +129,32 @@ public class KernelLogItem extends GenericItem {
return items; return items;
} }
/**
* 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} * {@inheritDoc}
*/ */
......
/*
* 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);
}
}
/*
* 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);
}
}
...@@ -16,7 +16,9 @@ ...@@ -16,7 +16,9 @@
package com.android.loganalysis.parser; package com.android.loganalysis.parser;
import com.android.loganalysis.item.KernelLogItem; import com.android.loganalysis.item.KernelLogItem;
import com.android.loganalysis.item.LowMemoryKillerItem;
import com.android.loganalysis.item.MiscKernelLogItem; import com.android.loganalysis.item.MiscKernelLogItem;
import com.android.loganalysis.item.PageAllocationFailureItem;
import com.android.loganalysis.item.SELinuxItem; import com.android.loganalysis.item.SELinuxItem;
import com.android.loganalysis.util.LogPatternUtil; import com.android.loganalysis.util.LogPatternUtil;
import com.android.loganalysis.util.LogTailUtil; import com.android.loganalysis.util.LogTailUtil;
...@@ -28,13 +30,16 @@ import java.util.regex.Matcher; ...@@ -28,13 +30,16 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; 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 class KernelLogParser implements IParser {
public static final String KERNEL_RESET = "KERNEL_RESET"; public static final String KERNEL_RESET = "KERNEL_RESET";
public static final String KERNEL_ERROR = "KERNEL_ERROR"; public static final String KERNEL_ERROR = "KERNEL_ERROR";
public static final String SELINUX_DENIAL = "SELINUX_DENIAL"; public static final String SELINUX_DENIAL = "SELINUX_DENIAL";
public static final String NORMAL_REBOOT = "NORMAL_REBOOT"; 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 /> * Matches: [ 0.000000] Message<br />
...@@ -44,6 +49,12 @@ public class KernelLogParser implements IParser { ...@@ -44,6 +49,12 @@ public class KernelLogParser implements IParser {
"^(<\\d+>)?\\[\\s*(\\d+\\.\\d{6})\\] (.*)$"); "^(<\\d+>)?\\[\\s*(\\d+\\.\\d{6})\\] (.*)$");
private static final Pattern SELINUX_DENIAL_PATTERN = Pattern.compile( private static final Pattern SELINUX_DENIAL_PATTERN = Pattern.compile(
".*avc:\\s.*scontext=\\w*:\\w*:([\\w\\s]*):\\w*\\s.*"); ".*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. * Regular expression representing all known bootreasons which are bad.
...@@ -163,6 +174,22 @@ public class KernelLogParser implements IParser { ...@@ -163,6 +174,22 @@ public class KernelLogParser implements IParser {
selinuxItem.setSContext(m.group(1)); selinuxItem.setSContext(m.group(1));
} }
kernelLogItem = selinuxItem; 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 { } else {
kernelLogItem = new MiscKernelLogItem(); kernelLogItem = new MiscKernelLogItem();
} }
...@@ -229,6 +256,10 @@ public class KernelLogParser implements IParser { ...@@ -229,6 +256,10 @@ public class KernelLogParser implements IParser {
// SELINUX denials // SELINUX denials
mPatternUtil.addPattern(SELINUX_DENIAL_PATTERN, SELINUX_DENIAL); 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);
} }
/** /**
......
...@@ -16,7 +16,9 @@ ...@@ -16,7 +16,9 @@
package com.android.loganalysis.parser; package com.android.loganalysis.parser;
import com.android.loganalysis.item.KernelLogItem; import com.android.loganalysis.item.KernelLogItem;
import com.android.loganalysis.item.LowMemoryKillerItem;
import com.android.loganalysis.item.MiscKernelLogItem; import com.android.loganalysis.item.MiscKernelLogItem;
import com.android.loganalysis.item.PageAllocationFailureItem;
import com.android.loganalysis.item.SELinuxItem; import com.android.loganalysis.item.SELinuxItem;
import com.android.loganalysis.util.LogPatternUtil; import com.android.loganalysis.util.LogPatternUtil;
...@@ -234,6 +236,70 @@ public class KernelLogParserTest extends TestCase { ...@@ -234,6 +236,70 @@ public class KernelLogParserTest extends TestCase {
assertEquals(SELINUX_DENIAL_STACK, selinuxItem.getStack()); 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() { public void testMantaReset() {
final List<String> lines = Arrays.asList("[ 3281.347296] ---fimc_is_ischain_close(0)", final List<String> lines = Arrays.asList("[ 3281.347296] ---fimc_is_ischain_close(0)",
"[ 3281.432055] fimc_is_scalerc_video_close", "[ 3281.432055] fimc_is_scalerc_video_close",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment