• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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 package com.android.loganalysis;
17 
18 import com.android.loganalysis.item.BugreportItem;
19 import com.android.loganalysis.item.DvmLockSampleItem;
20 import com.android.loganalysis.item.IItem;
21 import com.android.loganalysis.item.KernelLogItem;
22 import com.android.loganalysis.item.LogcatItem;
23 import com.android.loganalysis.item.MemoryHealthItem;
24 import com.android.loganalysis.item.MonkeyLogItem;
25 import com.android.loganalysis.parser.BugreportParser;
26 import com.android.loganalysis.parser.DvmLockSampleParser;
27 import com.android.loganalysis.parser.KernelLogParser;
28 import com.android.loganalysis.parser.LogcatParser;
29 import com.android.loganalysis.parser.MemoryHealthParser;
30 import com.android.loganalysis.parser.MonkeyLogParser;
31 import com.android.loganalysis.rule.RuleEngine;
32 import com.android.loganalysis.rule.RuleEngine.RuleType;
33 import com.android.loganalysis.util.config.ArgsOptionParser;
34 import com.android.loganalysis.util.config.ConfigurationException;
35 import com.android.loganalysis.util.config.Option;
36 
37 import org.json.JSONArray;
38 import org.json.JSONException;
39 import org.json.JSONObject;
40 
41 import java.io.BufferedReader;
42 import java.io.Closeable;
43 import java.io.File;
44 import java.io.FileNotFoundException;
45 import java.io.FileReader;
46 import java.io.IOException;
47 
48 import java.util.ArrayList;
49 import java.util.List;
50 
51 /**
52  * A command line tool to parse a bugreport, logcat, or kernel log file and return the output.
53  */
54 public class LogAnalyzer {
55 
56     private enum OutputFormat{
57         // TODO: Add text output support.
58         JSON;
59     }
60 
61     private enum ResultType {
62         RAW, ANALYSIS;
63     }
64 
65     @Option(name="bugreport", description="The path to the bugreport")
66     private String mBugreportPath = null;
67 
68     @Option(name="logcat", description="The path to the logcat")
69     private String mLogcatPath = null;
70 
71     @Option(name="kernel-log", description="The path to the kernel log")
72     private String mKernelLogPath = null;
73 
74     @Option(name="monkey-log", description="The path to the monkey log")
75     private String mMonkeyLogPath = null;
76 
77     @Option(name="memory-health", description="The path to the memory health log")
78     private String mMemoryHealthLogPath = null;
79 
80     @Option(name="output", description="The output format, currently only JSON")
81     private OutputFormat mOutputFormat = OutputFormat.JSON;
82 
83     @Option(name="rule-type", description="The type of rules to be applied")
84     private RuleType mRuleType = RuleType.ALL;
85 
86     @Option(name="print", description="Print the result type")
87     private List<ResultType> mResultType = new ArrayList<ResultType>();
88 
89     @Option(name="events-log", description="The path to the events log")
90     private String mEventsLogPath = null;
91 
92     /** Constant for JSON output */
93     private static final String RAW_DATA = "RAW";
94     /** Constant for JSON output */
95     private static final String ANALYSIS_DATA = "ANALYSIS";
96 
97     /**
98      * Run the command line tool
99      */
run(String[] args)100     public void run(String[] args) {
101         try {
102             initArgs(args);
103         } catch (ConfigurationException e) {
104             printUsage();
105             return;
106         }
107 
108         if (!checkPreconditions()) {
109             printUsage();
110             return;
111         }
112 
113         BufferedReader reader = null;
114         try {
115             if (mBugreportPath != null) {
116                 reader = getBufferedReader(mBugreportPath);
117                 BugreportItem bugreport = new BugreportParser().parse(reader);
118                 printBugreport(bugreport);
119                 return;
120             }
121 
122             if (mLogcatPath != null) {
123                 reader = getBufferedReader(mLogcatPath);
124                 LogcatItem logcat = new LogcatParser().parse(reader);
125                 printLogcat(logcat);
126                 return;
127             }
128 
129             if (mKernelLogPath != null) {
130                 reader = getBufferedReader(mKernelLogPath);
131                 KernelLogItem kernelLog = new KernelLogParser().parse(reader);
132                 printKernelLog(kernelLog);
133                 return;
134             }
135 
136             if (mMonkeyLogPath != null) {
137                 reader = getBufferedReader(mMonkeyLogPath);
138                 MonkeyLogItem monkeyLog = new MonkeyLogParser().parse(reader);
139                 printMonkeyLog(monkeyLog);
140                 return;
141             }
142 
143             if (mMemoryHealthLogPath != null) {
144                 reader = getBufferedReader(mMemoryHealthLogPath);
145                 MemoryHealthItem item = new MemoryHealthParser().parse(reader);
146                 printMemoryHealthLog(item);
147                 return;
148             }
149 
150             if (mEventsLogPath != null) {
151                 reader = getBufferedReader(mEventsLogPath);
152 
153                 // The only log we know how to parse in the Events log are
154                 // DVM lock samples.
155                 DvmLockSampleItem item = new DvmLockSampleParser().parse(reader);
156                 printDVMLog(item);
157                 return;
158             }
159         } catch (FileNotFoundException e) {
160             System.err.println(e.getMessage());
161         } catch (IOException e) {
162             System.err.println(e.getMessage());
163         } finally {
164             close(reader);
165         }
166 
167         // Should never reach here.
168         printUsage();
169     }
170 
printMemoryHealthLog(MemoryHealthItem item)171     private void printMemoryHealthLog(MemoryHealthItem item) {
172         System.out.println(item.toJson().toString());
173     }
174 
175     /**
176      * Print the bugreport to stdout.
177      */
printBugreport(BugreportItem bugreport)178     private void printBugreport(BugreportItem bugreport) {
179         if (OutputFormat.JSON.equals(mOutputFormat)) {
180             if (mResultType.size() == 0) {
181                 printJson(bugreport);
182             } else if (mResultType.size() == 1) {
183                 switch (mResultType.get(0)) {
184                     case RAW:
185                         printJson(bugreport);
186                         break;
187                     case ANALYSIS:
188                         printBugreportAnalysis(getBugreportAnalysis(bugreport));
189                         break;
190                     default:
191                         // should not get here
192                         return;
193                 }
194             } else {
195                 JSONObject result = new JSONObject();
196                 try {
197                     for (ResultType resultType : mResultType) {
198                         switch (resultType) {
199                             case RAW:
200                                 result.put(RAW_DATA, bugreport.toJson());
201                                 break;
202                             case ANALYSIS:
203                                 result.put(ANALYSIS_DATA, getBugreportAnalysis(bugreport));
204                                 break;
205                             default:
206                                 // should not get here
207                                 break;
208                         }
209                     }
210                 } catch (JSONException e) {
211                     // Ignore
212                 }
213                 printJson(result);
214             }
215         }
216     }
217 
getBugreportAnalysis(BugreportItem bugreport)218     private JSONArray getBugreportAnalysis(BugreportItem bugreport) {
219         RuleEngine ruleEngine = new RuleEngine(bugreport);
220         ruleEngine.registerRules(mRuleType);
221         ruleEngine.executeRules();
222         if (ruleEngine.getAnalysis() != null) {
223             return ruleEngine.getAnalysis();
224         } else {
225             return new JSONArray();
226         }
227     }
228 
printBugreportAnalysis(JSONArray analysis)229     private void printBugreportAnalysis(JSONArray analysis) {
230         if (analysis != null && analysis.length() > 0) {
231             System.out.println(analysis.toString());
232         } else {
233             System.out.println(new JSONObject().toString());
234         }
235     }
236 
237     /**
238      * Print the logcat to stdout.
239      */
printLogcat(LogcatItem logcat)240     private void printLogcat(LogcatItem logcat) {
241         if (OutputFormat.JSON.equals(mOutputFormat)) {
242             printJson(logcat);
243         }
244         // TODO: Print logcat in human readable form.
245     }
246 
247     /**
248      * Print the kernel log to stdout.
249      */
printKernelLog(KernelLogItem kernelLog)250     private void printKernelLog(KernelLogItem kernelLog) {
251         if (OutputFormat.JSON.equals(mOutputFormat)) {
252             printJson(kernelLog);
253         }
254         // TODO: Print kernel log in human readable form.
255     }
256 
257     /**
258      * Print the monkey log to stdout.
259      */
printMonkeyLog(MonkeyLogItem monkeyLog)260     private void printMonkeyLog(MonkeyLogItem monkeyLog) {
261         if (OutputFormat.JSON.equals(mOutputFormat)) {
262             printJson(monkeyLog);
263         }
264         // TODO: Print monkey log in human readable form.
265     }
266 
267     /**
268      * Print a DVM log entry to stdout.
269      */
printDVMLog(DvmLockSampleItem dvmLog)270     private void printDVMLog(DvmLockSampleItem dvmLog) {
271         if (OutputFormat.JSON.equals(mOutputFormat)) {
272             printJson(dvmLog);
273         }
274         // TODO: Print DVM log in human readable form.
275     }
276 
277     /**
278      * Print an {@link IItem} to stdout.
279      */
printJson(IItem item)280     private void printJson(IItem item) {
281         if (item != null && item.toJson() != null) {
282             printJson(item.toJson());
283         } else {
284             printJson(new JSONObject());
285         }
286     }
287 
288     /**
289      * Print an {@link JSONObject} to stdout
290      */
printJson(JSONObject json)291     private void printJson(JSONObject json) {
292         if (json != null) {
293             System.out.println(json.toString());
294         } else {
295             System.out.println(new JSONObject().toString());
296         }
297     }
298 
299     /**
300      * Get a {@link BufferedReader} from a given filepath.
301      * @param filepath the path to the file.
302      * @return The {@link BufferedReader} containing the contents of the file.
303      * @throws FileNotFoundException if the file could not be found.
304      */
getBufferedReader(String filepath)305     private BufferedReader getBufferedReader(String filepath) throws FileNotFoundException {
306         return new BufferedReader(new FileReader(new File(filepath)));
307     }
308 
309     /**
310      * Helper to close a {@link Closeable}.
311      */
close(Closeable closeable)312     private void close(Closeable closeable) {
313         if (closeable != null) {
314             try {
315                 closeable.close();
316             } catch (IOException e) {
317                 // Ignore
318             }
319         }
320     }
321 
322     /**
323      * Parse the command line options and set {@link Option} annotated fields.
324      */
initArgs(String[] args)325     private void initArgs(String[] args) throws ConfigurationException {
326         ArgsOptionParser opt = new ArgsOptionParser(this);
327         opt.parse(args);
328     }
329 
330     /**
331      * Checks the arguments to see if they are valid.
332      *
333      * @return true if they are valid, false if they are not.
334      */
checkPreconditions()335     private boolean checkPreconditions() {
336         // Check to see that exactly one log is set.
337         int logCount = 0;
338         if (mBugreportPath != null) logCount++;
339         if (mLogcatPath != null) logCount++;
340         if (mKernelLogPath != null) logCount++;
341         if (mMonkeyLogPath != null) logCount++;
342         if (mMemoryHealthLogPath != null) logCount++;
343         return (logCount == 1);
344     }
345 
346     /**
347      * Print the usage for the command.
348      */
printUsage()349     private void printUsage() {
350         System.err.println("Usage: loganalysis [--bugreport FILE | --events-log FILE | --logcat FILE | " +
351                 "--kernel-log FILE | --monkey-log FILE]");
352     }
353 
354     /**
355      * Run the LogAnalyzer from the command line.
356      */
main(String[] args)357     public static void main(String[] args) {
358         LogAnalyzer analyzer = new LogAnalyzer();
359         analyzer.run(args);
360     }
361 }
362