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