• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.ddmuilib.logcat;
18 
19 import com.android.ddmlib.Log.LogLevel;
20 
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.regex.Matcher;
24 import java.util.regex.Pattern;
25 
26 /**
27  * Class to parse raw output of {@code adb logcat -v long} to {@link LogCatMessage} objects.
28  */
29 public final class LogCatMessageParser {
30     private LogLevel mCurLogLevel = LogLevel.WARN;
31     private String mCurPid = "?";
32     private String mCurTag = "?";
33     private String mCurTime = "?:??";
34 
35     /**
36      * This pattern is meant to parse the first line of a log message with the option
37      * 'logcat -v long'. The first line represents the date, tag, severity, etc.. while the
38      * following lines are the message (can be several lines).<br>
39      * This first line looks something like:<br>
40      * {@code "[ 00-00 00:00:00.000 <pid>:0x<???> <severity>/<tag>]"}
41      * <br>
42      * Note: severity is one of V, D, I, W, E, A? or F. However, there doesn't seem to be
43      *       a way to actually generate an A (assert) message. Log.wtf is supposed to generate
44      *       a message with severity A, however it generates the undocumented F level. In
45      *       such a case, the parser will change the level from F to A.<br>
46      * Note: the fraction of second value can have any number of digit.<br>
47      * Note: the tag should be trimmed as it may have spaces at the end.
48      */
49     private static Pattern sLogHeaderPattern = Pattern.compile(
50             "^\\[\\s(\\d\\d-\\d\\d\\s\\d\\d:\\d\\d:\\d\\d\\.\\d+)"
51           + "\\s+(\\d*):(0x[0-9a-fA-F]+)\\s([VDIWEAF])/(.*)\\]$");
52 
53     /**
54      * Parse a list of strings into {@link LogCatMessage} objects. This method
55      * maintains state from previous calls regarding the last seen header of
56      * logcat messages.
57      * @param lines list of raw strings obtained from logcat -v long
58      * @param pidToNameMapper mapper to obtain the app name given a pid
59      * @return list of LogMessage objects parsed from the input
60      */
processLogLines(String[] lines, LogCatPidToNameMapper pidToNameMapper)61     public List<LogCatMessage> processLogLines(String[] lines,
62             LogCatPidToNameMapper pidToNameMapper) {
63         List<LogCatMessage> messages = new ArrayList<LogCatMessage>(lines.length);
64 
65         for (String line : lines) {
66             if (line.length() == 0) {
67                 continue;
68             }
69 
70             Matcher matcher = sLogHeaderPattern.matcher(line);
71             if (matcher.matches()) {
72                 mCurTime = matcher.group(1);
73                 mCurPid = matcher.group(2);
74                 mCurLogLevel = LogLevel.getByLetterString(matcher.group(4));
75                 mCurTag = matcher.group(5).trim();
76 
77                 /* LogLevel doesn't support messages with severity "F". Log.wtf() is supposed
78                  * to generate "A", but generates "F". */
79                 if (mCurLogLevel == null && matcher.group(4).equals("F")) {
80                     mCurLogLevel = LogLevel.ASSERT;
81                 }
82             } else {
83                 LogCatMessage m = new LogCatMessage(mCurLogLevel, mCurPid,
84                         pidToNameMapper.getName(mCurPid),
85                         mCurTag, mCurTime, line);
86                 messages.add(m);
87             }
88         }
89 
90         return messages;
91     }
92 }
93