10

我有一个小系统,我想提供一个可以分析错误/异常并提出可能解决方案的产品。

所以我想要一种解析java异常的方法(因为我只在日志中拥有它们[我不想影响实际系统])。

解析后,我想将其保存在数据库中,并将其与之前保存的异常(以某种格式)进行比较,以便找到最接近的匹配异常。

我想到了以下想法:“XException at A at B at C at D”将保存为 [XException, A, B, C, D] 并且我将以某种方式在我的数据库中搜索: [XException, ?, ?, ?] 哪个是最接近的。例如:[XException, A, G, C, D] 相当不错。

您如何看待这些想法?

解析异常的任何有效方法?

定义两个异常之间距离的有效或更好的方法?

知道任何可以做到这一点的开源 - 我还没有找到任何。

谢谢你。

4

2 回答 2

7

这是一项相当艰巨的工作,但这里是解析一些动态生成的现实异常的演示。

  • 该方法称为 generate_$ 以尝试覆盖奇怪命名的方法。我确定我没有涵盖所有情况。
  • 将它们重新构建为 java.lang.StackTraceElement 列表,因为它似乎是适合该工作的类型。

代码:

private static List<String> generate_$() {
    List<String> returnValue = new LinkedList<String>();
    Exception[] exceptions = { new ClassCastException(),
            new NullPointerException(), new IOException("foo") };
    for (Exception exception : exceptions) {
        try {
            throw exception;
        } catch (Exception e) {
            StringWriter writer = new StringWriter();
            e.printStackTrace(new PrintWriter(writer));
            returnValue.add(writer.getBuffer().toString());
        }
    }
    return returnValue;
}

public static void main(String[] args) {
    List<String> examples = generate_$();
    for (String trace : examples) {
        Pattern headLinePattern = Pattern.compile("([\\w\\.]+)(:.*)?");
        Matcher headLineMatcher = headLinePattern.matcher(trace);
        if (headLineMatcher.find()) {
            System.out.println("Headline: " + headLineMatcher.group(1));
            if (headLineMatcher.group(2) != null) {
                System.out.println("Optional message "
                        + headLineMatcher.group(2));
            }
        }
        // "at package.class.method(source.java:123)"
        Pattern tracePattern = Pattern
                .compile("\\s*at\\s+([\\w\\.$_]+)\\.([\\w$_]+)(\\(.*java)?:(\\d+)\\)(\\n|\\r\\n)");
        Matcher traceMatcher = tracePattern.matcher(trace);
        List<StackTraceElement> stackTrace = new ArrayList<StackTraceElement>();
        while (traceMatcher.find()) {
            String className = traceMatcher.group(1);
            String methodName = traceMatcher.group(2);
            String sourceFile = traceMatcher.group(3);
            int lineNum = Integer.parseInt(traceMatcher.group(4));
            stackTrace.add(new StackTraceElement(className, methodName,
                    sourceFile, lineNum));
        }
        System.out.println("Stack: " + stackTrace);

    }
}

输出:

Headline: java.lang.ClassCastException
Stack: [com.adamish.ExceptionParse.generate_$((ExceptionParse.java:16), com.adamish.ExceptionParse.main((ExceptionParse.java:31)]

Headline: java.lang.NullPointerException
Stack: [com.adamish.ExceptionParse.generate_$((ExceptionParse.java:17), com.adamish.ExceptionParse.main((ExceptionParse.java:31)]

Headline: java.io.IOException
Optional message : foo
Stack: [com.adamish.ExceptionParse.generate_$((ExceptionParse.java:17), com.adamish.ExceptionParse.main((ExceptionParse.java:31)]
于 2012-04-04T15:46:51.390 回答
3

我想这个问题会因为过于开放而被关闭。SO 适用于可以给出明确和明确答案的问题。

即便如此,在此之前,我想说这似乎是一个不错的主意,我希望你能做到。最好关注堆栈跟踪中清楚识别不可变信息的那些部分,例如包、类和方法名称。至于检测部分或完全匹配,我建议您查看已知的索引和匹配算法。可以应用一些著名的文本搜索算法,但“原子”单元是方法名称或包限定的类名称,而不是单个字母或单词。

祝你好运!

编辑:只是想到了别的东西。您可能希望专注于使您的实现尽可能通用,以适应许多不同编程语言、框架等的堆栈跟踪。这将使软件更具前瞻性和广泛适用性。

于 2012-04-04T15:02:25.777 回答