2012-04-04 82 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旨在用於可以給出明確和明確答案的問題。

即便如此,在此之前,我想說這似乎是一個不錯的主意,我希望你能使它工作。最好把重點放在堆棧跟蹤的那些清楚標識不可變信息的部分,如包,類和方法名稱。至於檢測部分或完整的匹配,我建議你看看已知的索引和匹配算法。一些衆所周知的用於文本搜索的算法可以被應用,但是「原子」單元是方法名稱或包限定類名,而不是單個字母或單詞。

祝你好運!

編輯:只是想到別的東西。您可能希望將重點放在使您的實現儘可能通用,以用於許多不同編程語言,框架等的堆棧跟蹤。這將使該軟件更具前瞻性並且廣泛適用。