Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading and parsing Java exceptions [closed]

I have a small system, and I want to offer a product that can analyze errors / exceptions and suggest a possible solution.

So I want a way to parse a java Exception (since I have them only in logs [I don't want to affect the actual system]).

After parsing it, I want to save it in a DB and compare it to previously saved exceptions (in some format), so that I can find the closest matching exception.

I thought about the following idea: "XException at A at B at C at D" will be saved as [XException, A, B, C, D] and I will be somehow searching in my DB: [XException, ?, ?, ?] which is the closest. For example: [XException, A, G, C, D] is quite good.

What do you think of these ideas?

Any effiecient way to parse Exceptions?

Efficient or better ways to define distance between two Exceptions?

Know any open sources that can do this - I saure haven't found any.

Thank you.

like image 734
user967710 Avatar asked Apr 04 '12 14:04

user967710


2 Answers

It's quite hard work, but here is a demonstration of parsing some real-life exceptions generated on the fly.

  • the method is called generate_$ to try and cover oddly named methods. I'm sure I've not covered all cases though.
  • reconstruct them back into a list of java.lang.StackTraceElement since it seems the right type for the job.

Code:

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);

    }
}

Output:

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)]
like image 158
Adam Avatar answered Nov 16 '22 01:11

Adam


I guess this question is going to be closed as being too open-ended. SO is intended for questions that can be given clear and definitive answers.

Even so, before that happens I'd like to say that this seems like a pretty good idea and I hope you can make it work. It would be best to focus on those parts of the stack trace that clearly identify immutable information, like package, class and method names. As for detecting partial or complete matches, I suggest you look into known indexing and matching algorithms. Some well-known algorithms for text searches could be applied, but with the "atomic" units being method names or package-qualified class names instead if single letters or words.

Good luck!

EDIT: just thought of something else. You may wish to focus on making your implementation as generic as possible for stack traces of many different programming languages, frameworks etc. This would make the software more future-proof and widely applicable.

like image 43
G_H Avatar answered Nov 16 '22 03:11

G_H