blob: 4196e71ce8e34fdc35ed92bcbbe8b853a63733d1 [file] [log] [blame]
/*
* Copyright (C) 2013 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.parser;
import com.android.loganalysis.item.SmartMonkeyLogItem;
import java.io.BufferedReader;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A {@link IParser} to parse monkey logs.
*/
public class SmartMonkeyLogParser implements IParser {
private static final String TIME_STAMP_GROUP =
"^(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}.\\d{3}): ";
private static final String INVOKE_NUM_GROUP = "\\[.*?(\\d+)\\]";
private static final String SEQ_NUM_GROUP = "\\(Seq:.*?(\\d+)\\)";
private static final Pattern START_TIME = Pattern.compile(
TIME_STAMP_GROUP + "Starting.*");
private static final Pattern START_UPTIME = Pattern.compile(
TIME_STAMP_GROUP + "Device uptime: (\\d+) sec$");
private static final Pattern STOP_UPTIME = Pattern.compile(
TIME_STAMP_GROUP + "Device uptime: (\\d+) sec, Monkey run duration: (\\d+) sec$");
private static final Pattern THROTTLE = Pattern.compile(
TIME_STAMP_GROUP + "Throttle: (\\d+).*");
private static final Pattern TARGET_INVOCATIONS = Pattern.compile(
TIME_STAMP_GROUP + "Target invocation count: (\\d+)");
private static final Pattern INTERMEDIATE_COUNT = Pattern.compile(
TIME_STAMP_GROUP + INVOKE_NUM_GROUP + SEQ_NUM_GROUP + ".*");
private static final Pattern INTERMEDIATE_TIME = Pattern.compile(TIME_STAMP_GROUP + ".*");
private static final Pattern FINISHED = Pattern.compile(
TIME_STAMP_GROUP + "Monkey finished");
private static final Pattern FINAL_COUNT = Pattern.compile(
TIME_STAMP_GROUP + "Invocations completed: (\\d+)");
private static final Pattern APPS_PACKAGES = Pattern.compile(
TIME_STAMP_GROUP + "Starting \\[(.*)\\]\\[(.*)\\]");
private static final Pattern ABORTED = Pattern.compile(
TIME_STAMP_GROUP + "Monkey aborted.");
private static final Pattern UI_ANR = Pattern.compile(
TIME_STAMP_GROUP + INVOKE_NUM_GROUP + SEQ_NUM_GROUP + "-UI Exception: ANR: (.*)");
private static final Pattern UI_CRASH = Pattern.compile(
TIME_STAMP_GROUP + INVOKE_NUM_GROUP + SEQ_NUM_GROUP + "-UI Exception: CRASH: (.*)");
private final SmartMonkeyLogItem mSmartMonkeyLog = new SmartMonkeyLogItem();
/**
* Parse a monkey log from a {@link BufferedReader} into an {@link SmartMonkeyLogItem}
* object.
*
* @param input a {@link BufferedReader}.
* @return The {@link SmartMonkeyLogItem}.
* @see #parse(List)
*/
public SmartMonkeyLogItem parse(BufferedReader input) throws IOException {
String line;
while ((line = input.readLine()) != null) {
parseLine(line);
}
return mSmartMonkeyLog;
}
/**
* {@inheritDoc}
*
* @return The {@link SmartMonkeyLogItem}.
*/
@Override
public SmartMonkeyLogItem parse(List<String> lines) {
for (String line : lines) {
parseLine(line);
}
if (mSmartMonkeyLog.getStopUptimeDuration() == 0)
mSmartMonkeyLog.setIsFinished(false);
else
mSmartMonkeyLog.setIsFinished(true);
return mSmartMonkeyLog;
}
/**
* Parse a line of input.
*/
private void parseLine(String line) {
Matcher m = THROTTLE.matcher(line);
if (m.matches()) {
mSmartMonkeyLog.setThrottle(Integer.parseInt(m.group(2)));
}
m = TARGET_INVOCATIONS.matcher(line);
if (m.matches()) {
mSmartMonkeyLog.setTargetInvocations(Integer.parseInt(m.group(2)));
}
m = APPS_PACKAGES.matcher(line);
if (m.matches()) {
String apps = m.group(2);
String packages = m.group(3);
String[] appsArray = apps.split("\\|");
for (String a : appsArray) {
mSmartMonkeyLog.addApplication(a);
}
String[] pkgsArray = packages.split("\\|");
for (String p : pkgsArray) {
mSmartMonkeyLog.addPackage(p);
}
}
m = INTERMEDIATE_COUNT.matcher(line);
if (m.matches()) {
mSmartMonkeyLog.setIntermediateCount(Integer.parseInt(m.group(2)));
}
m = START_TIME.matcher(line);
if (m.matches()) {
mSmartMonkeyLog.setStartTime(parseTime(m.group(1)));
}
m = START_UPTIME.matcher(line);
if (m.matches()) {
mSmartMonkeyLog.setStartUptimeDuration((Long.parseLong(m.group(2))));
}
m = STOP_UPTIME.matcher(line);
if (m.matches()) {
mSmartMonkeyLog.setStopTime(parseTime(m.group(1)));
mSmartMonkeyLog.setStopUptimeDuration(Long.parseLong(m.group(2)));
mSmartMonkeyLog.setTotalDuration(Long.parseLong(m.group(3)));
}
m = INTERMEDIATE_TIME.matcher(line);
if (m.matches()) {
mSmartMonkeyLog.setIntermediateTime(parseTime(m.group(1)));
}
m = FINAL_COUNT.matcher(line);
if (m.matches()) {
mSmartMonkeyLog.setFinalCount(Integer.parseInt(m.group(2)));
}
m = FINISHED.matcher(line);
if (m.matches()) {
mSmartMonkeyLog.setIsFinished(true);
}
m = ABORTED.matcher(line);
if (m.matches()) {
mSmartMonkeyLog.setIsAborted(true);
}
m = UI_CRASH.matcher(line);
if (m.matches()) {
mSmartMonkeyLog.addCrashTime(parseTime(m.group(1)));
}
m = UI_ANR.matcher(line);
if (m.matches()) {
mSmartMonkeyLog.addAnrTime(parseTime(m.group(1)));
}
}
/**
* Parse the timestamp and return a date.
*
* @param timeStr The timestamp in the format {@code yyyy-MM-dd HH:mm:ss.SSS}
* @return The {@link Date}.
*/
public static Date parseTime(String timeStr) {
try {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").parse(timeStr);
} catch (ParseException e) {
}
return null;
}
}