Trace the Java / Android stack to a unique bucket

When a stack trace of unhandled exceptions is recorded in Java or Android (for example, through acra), the stack trace is usually treated as a simple long string

Now, all services that provide crash reporting and analysis (such as Google play developer console, crash Analytics) group these stack traces into a unique storage area This is obviously helpful – otherwise, you may have thousands of crash reports on your list, but only a dozen may be unique

Example:

java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:200)
at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
at java.lang.Thread.run(Thread.java:1027)
Caused by: java.lang.Arrayindexoutofboundsexception
at com.my.package.MyClass.i(SourceFile:1059)
...

The above stack track may appear in multiple variants, for example Due to different platform versions, platform classes such as asynctask may have different line numbers

What is the best technique for obtaining a unique identifier for each crash report?

Obviously, with each new application release you release, crash reports should be handled separately because the source of compilation is different In acra, you can consider using the field app_ VERSION_ CODE.

Otherwise, how do you identify reports with unique causes? By taking the first line and searching for custom (non platform) classes for the first time, and looking for files and line numbers?

Solution

If you are looking for a way to get the unique value of an exception without ignoring the operating system specific class, you can iterate getstacktrace() and hash every frame that does not come from a known operating system class I think it makes sense to add cause exceptions to the hash It may produce some false negatives, but if the hash exception is similar to executionexception, it will be better than false positives

import com.google.common.base.Charsets;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;

public class Test
{

    // add more system packages here
    private static final String[] SYstem_PACKAGES = new String[] {
        "java.","javax.","android."
    };

    public static void main( String[] args )
    {
        Exception e = new Exception();
        HashCode eh = hashApplicationException( e );
        System.out.println( eh.toString() );
    }

    private static HashCode hashApplicationException( Throwable exception )
    {
        Hasher md5 = Hashing.md5().newHasher();
        hashApplicationException( exception,md5 );
        return md5.hash();
    }

    private static void hashApplicationException( Throwable exception,Hasher hasher )
    {
        for( StackTraceElement stackFrame : exception.getStackTrace() ) {
            if( isSystemPackage( stackFrame ) ) {
                continue;
            }

            hasher.putString( stackFrame.getClassName(),Charsets.UTF_8 );
            hasher.putString( ":",Charsets.UTF_8 );
            hasher.putString( stackFrame.getmethodName(),Charsets.UTF_8 );
            hasher.putInt( stackFrame.getLineNumber() );
        }
        if( exception.getCause() != null ) {
            hasher.putString( "...",Charsets.UTF_8 );
            hashApplicationException( exception.getCause(),hasher );
        }
    }

    private static boolean isSystemPackage( StackTraceElement stackFrame )
    {
        for( String ignored : SYstem_PACKAGES ) {
            if( stackFrame.getClassName().startsWith( ignored ) ) {
                return true;
            }
        }

        return false;
    }
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>