use of com.android.ddmlib.logcat.LogCatHeader in project android by JetBrains.
the class AndroidLogcatReceiver method processNewLine.
@Override
public void processNewLine(@NotNull String line) {
// Really, the user's log should never put any system characters in it ever - that will cause
// it to get filtered by our strict regex patterns (see AndroidLogcatFormatter). The reason
// this might happen in practice is due to a bug where either adb or logcat (not sure which)
// is too aggressive about converting \n's to \r\n's, including those that are quoted. This
// means that a user's log, if it uses \r\n itself, is converted to \r\r\n. Then, when
// MultiLineReceiver, which expects valid input, strips out \r\n, it leaves behind an extra \r.
//
// Unfortunately this isn't a case where we can fix the root cause because adb and logcat are
// both external to Android Studio. In fact, the latest adb/logcat versions have already fixed
// this issue! But we still need to run properly with older versions. Also, putting this fix in
// MultilineReceiver isn't right either because it is used for more than just receiving logcat.
line = line.replaceAll("\\r", "");
if (line.isEmpty()) {
myDelayedNewlineCount++;
return;
}
LogCatHeader header = myParser.processLogHeader(line, myDevice);
if (header != null) {
myStackTraceExpander.reset();
myActiveHeader = header;
myLineIndex = 0;
// Intentionally drop any trailing newlines once we hit a new header. Usually, logcat
// separates log entries with a single newline but sometimes it outputs more than one. As we
// can't know which is user newlines vs. system newlines, just drop all of them.
myDelayedNewlineCount = 0;
} else if (myActiveHeader != null) {
if (myDelayedNewlineCount > 0 && myLineIndex == 0) {
// Note: Since we trim trailing newlines, we trim leading newlines too. Most users won't
// use them intentionally and they don't look great, anyway.
myDelayedNewlineCount = 0;
} else {
processAnyDelayedNewlines(myActiveHeader);
}
for (String processedLine : myStackTraceExpander.process(line)) {
notifyLine(myActiveHeader, processedLine);
}
}
}
use of com.android.ddmlib.logcat.LogCatHeader in project android by JetBrains.
the class AndroidLogcatFormatter method tryParseMessage.
/**
* Returns the result of {@link #parseMessage(String)} or {@code null} if the format of the input
* text doesn't match.
*/
@Nullable
public static LogCatMessage tryParseMessage(@NotNull String msg) {
final Matcher matcher = MESSAGE_WITH_HEADER.matcher(msg);
if (!matcher.matches()) {
return null;
}
// matcher.matches verifies all groups below are non-null
@SuppressWarnings("ConstantConditions") LogCatHeader header = new LogCatHeader(Log.LogLevel.getByLetter(matcher.group(5).charAt(0)), Integer.parseInt(matcher.group(2)), Integer.parseInt(matcher.group(3)), matcher.group(4), matcher.group(6), LogCatTimestamp.fromString(matcher.group(1)));
String message = matcher.group(7);
return new LogCatMessage(header, message);
}
use of com.android.ddmlib.logcat.LogCatHeader in project android by JetBrains.
the class AndroidLogcatService method startReceiving.
private void startReceiving(@NotNull final IDevice device) {
synchronized (myLock) {
if (myLogReceivers.containsKey(device)) {
return;
}
connect(device);
final AndroidLogcatReceiver receiver = createReceiver(device);
myLogReceivers.put(device, receiver);
myLogBuffers.put(device, new LogcatBuffer());
ExecutorService executor = myExecutors.get(device);
executor.submit((() -> {
try {
AndroidUtils.executeCommandOnDevice(device, "logcat -v long", receiver, true);
} catch (Exception e) {
getLog().info(String.format("Caught exception when capturing logcat output from the device %1$s. Receiving logcat output from this device will be " + "stopped, and the listeners will be notified with this exception as the last message", device.getName()), e);
LogCatHeader dummyHeader = new LogCatHeader(Log.LogLevel.ERROR, 0, 0, "?", "Internal", LogCatTimestamp.ZERO);
receiver.notifyLine(dummyHeader, e.getMessage());
}
}));
}
}
use of com.android.ddmlib.logcat.LogCatHeader in project android by JetBrains.
the class AndroidLogcatFormatterTest method formatMessageToParseMessageKeepsAllInformation.
@Test
public void formatMessageToParseMessageKeepsAllInformation() {
LogCatHeader header = new LogCatHeader(LogLevel.DEBUG, 13, 123, "system_process", "ConnectivityService", LogCatTimestamp.fromString("02-12 14:32:46.526"));
String output = AndroidLogcatFormatter.formatMessageFull(header, "xyz");
LogCatMessage message = AndroidLogcatFormatter.parseMessage(output);
LogCatHeader header2 = message.getHeader();
assertEquals(header.getTimestamp(), header2.getTimestamp());
assertEquals(header.getLogLevel(), header2.getLogLevel());
assertEquals(header.getPid(), header2.getPid());
assertEquals(header.getTid(), header2.getTid());
assertEquals(header.getAppName(), header2.getAppName());
assertEquals(header.getTag(), header2.getTag());
assertEquals("xyz", message.getMessage());
}
use of com.android.ddmlib.logcat.LogCatHeader in project android by JetBrains.
the class AndroidLogcatFormatterTest method parseMessageForTagAndLogLevel.
@Test
public void parseMessageForTagAndLogLevel() {
String message = "02-12 17:04:44.005 1282-12/com.google.android.apps" + ".maps:GoogleLocationService D/dalvikvm: Debugger has detached; object " + "registry had 1 entries";
LogCatHeader header = AndroidLogcatFormatter.parseMessage(message).getHeader();
assertEquals(LogLevel.DEBUG, header.getLogLevel());
assertEquals("dalvikvm", header.getTag());
}
Aggregations