【发布时间】:2015-02-11 14:27:19
【问题描述】:
我有一个 Java 应用程序,当出错时,它会为每个错误写入一个类似于下面的错误堆栈。
<Errors>
<Error ErrorCode="Code" ErrorDescription="Description" ErrorInfo="" ErrorId="ID">
<Attribute Name="ErrorCode" Value="Code"/>
<Attribute Name="ErrorDescription" Value="Description"/>
<Attribute Name="Key" Value="Key"/>
<Attribute Name="Number" Value="Number"/>
<Attribute Name="ErrorId" Value="ID"/>
<Attribute Name="UserId" Value="User"/>
<Attribute Name="ProgId" Value="Prog"/>
<Stack>typical Java stack</Stack>
</Error>
<Error>
Similar info to the above
</Error>
</Errors>
我编写了一个 Java 日志解析器来检查日志文件并收集有关此类错误的信息,虽然它确实有效,但它速度慢且效率低,尤其是对于数百兆字节的日志文件。我基本上只是使用字符串操作来检测开始/结束标签的位置并计算它们。
有没有办法(通过 Unix grep、Python 或 Java)有效地提取错误并计算每个错误发生的次数?整个日志文件不是 XML,所以我不能使用 XML 解析器或 Xpath。我面临的另一个问题是,有时错误的结尾可能会滚动到另一个文件中,因此当前文件可能没有上面的整个堆栈。
编辑1:
这是我目前拥有的(相关部分只是为了节省空间)。
//Parse files
for (File f : allFiles) {
System.out.println("Parsing: " + f.getAbsolutePath());
BufferedReader br = new BufferedReader(new FileReader(f));
String line = "";
String fullErrorStack = "";
while ((line = br.readLine()) != null) {
if (line.contains("<Errors>")) {
fullErrorStack = line;
while (!line.contains("</Errors>")) {
line = br.readLine();
try {
fullErrorStack = fullErrorStack + line.trim() + " ";
} catch (NullPointerException e) {
//End of file but end of error stack is in another file.
fullErrorStack = fullErrorStack + "</Stack></Error></Errors> ";
break;
}
}
String errorCode = fullErrorStack.substring(fullErrorStack.indexOf("ErrorCode=\"") + "ErrorCode=\"".length(), fullErrorStack.indexOf("\" ", fullErrorStack.indexOf("ErrorCode=\"")));
String errorDescription = fullErrorStack.substring(fullErrorStack.indexOf("ErrorDescription=\"") + "ErrorDescription=\"".length(), fullErrorStack.indexOf("\" ", fullErrorStack.indexOf("ErrorDescription=\"")));
String errorStack = fullErrorStack.substring(fullErrorStack.indexOf("<Stack>") + "<Stack>".length(), fullErrorStack.indexOf("</Stack>", fullErrorStack.indexOf("<Stack>")));
apiErrors.add(f.getAbsolutePath() + splitter + errorCode + ": " + errorDescription + splitter + errorStack.trim());
fullErrorStack = "";
}
}
}
Set<String> uniqueApiErrors = new HashSet<String>(apiErrors);
for (String uniqueApiError : uniqueApiErrors) {
apiErrorsUnique.add(uniqueApiError + splitter + Collections.frequency(apiErrors, uniqueApiError));
}
Collections.sort(apiErrorsUnique);
编辑 2:
很抱歉忘记提及所需的输出。像下面这样的东西是理想的。
Count、ErrorCode、ErrorDescription、它出现的文件列表(如果可能的话)
【问题讨论】:
-
你能发布你目前拥有的Java代码吗?
-
请查看编辑 - 我不确定它是否太大而无法容纳,但我只包括了重要的部分。
-
尝试使用 StringBuilder 而不是 String 来收集堆栈跟踪。