2012-04-04 83 views
6

我有一个小系统,我想提供一个产品,可以分析错误/异常并提出可能的解决方案。所以我想要一种解析java异常的方式(因为我只有在日志中有它们[我不想影响实际系统])。阅读和解析Java异常

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

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

您对这些想法有什么看法?

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

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

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

谢谢。

+0

如果你精心设计的系统,你会在适当的地方已经被捕获的异常,并会显示相应的人类可读的消息。如果你想写一个分析别人的应用程序错误的应用程序。我认为该应用可能最终变得模糊。只是我的想法。 – Nishant 2012-04-04 15:07:56

回答

4

这是非常艰苦的工作,但这里是解析一些实时异常生成的例外的演示。

  • 该方法被称为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)] 
+0

谢谢,很棒的工作。但是,在正则表达式中有一个小错误:在结果文件名中有一个额外的'('。改变...(\\\(。* java)... to ... \\\((。* java)... – roesslerj 2016-01-08 12:18:39

+0

另外,这个正则表达式不能正确解析“\ tat sun.nio.ch.WindowsSelectorImpl $ 1.access $ 400(Unknown Source)\ n”或“\ tat sun.nio.ch.WindowsSelectorImpl $ SubSelector.poll0 (Native Method)\ n“。 – roesslerj 2016-01-08 13:05:40

2

我想这个问题将被封闭,因为太开放。 SO旨在用于可以给出明确和明确答案的问题。

即便如此,在此之前,我想说这似乎是一个不错的主意,我希望你能使它工作。最好把重点放在堆栈跟踪的那些清楚标识不可变信息的部分,如包,类和方法名称。至于检测部分或完整的匹配,我建议你看看已知的索引和匹配算法。一些众所周知的用于文本搜索的算法可以被应用,但是“原子”单元是方法名称或包限定类名,而不是单个字母或单词。

祝你好运!

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