gpt4 book ai didi

java - 将 Java/Android 堆栈跟踪分组到唯一的桶中

转载 作者:搜寻专家 更新时间:2023-10-30 21:09:47 25 4
gpt4 key购买 nike

在 Java 或 Android 中记录未处理异常的堆栈跟踪(例如通过 ACRA)时,您通常会以普通长字符串的形式获取堆栈跟踪。

现在,所有提供崩溃报告和分析的服务(例如 Google Play Developer Console、Crashlytics)都将这些堆栈跟踪分组到唯一的桶中。这显然很有帮助——否则,您的列表中可能有数万个崩溃报告,但其中可能只有十几个是独一无二的。

例子:

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

上面的堆栈跟踪可能以多种形式出现,例如由于不同的平台版本,像 AsyncTask 这样的平台类可能会出现不同的行号。

为每个崩溃报告获取唯一标识符的最佳技术是什么?

清楚的是,对于您发布的每个新应用程序版本,崩溃报告都应该单独处理,因为编译源是不同的。在 ACRA 中,您可以考虑使用字段 APP_VERSION_CODE

但除此之外,您如何识别具有独特原因的报告?通过第一行搜索自定义(非平台)类的第一次出现并查找文件和行号?

最佳答案

如果您正在寻找一种方法来获取异常的唯一值,同时忽略特定于操作系统的类,您可以迭代 getStackTrace() 并对不是来自已知操作系统类的每个帧进行哈希处理。我认为将原因异常添加到哈希中也很有意义。它可能会产生一些漏报,但如果您散列的异常是通用的,例如 ExecutionException,那会比误报好。

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.putString( ":", 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;
}
}

关于java - 将 Java/Android 堆栈跟踪分组到唯一的桶中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29063286/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com