我们在我们的应用中使用Crashlytics作为崩溃报告工具。 对于Android本机崩溃,它工作正常并正确分组崩溃。 我们的应用程序在react-native中也没有很少的组件。对于这些组件中发生的崩溃,我们会捕获它们,然后将它们作为非致命异常记录到Crashlytics。
public class PlatformNativeModuleCallExceptionhandler implements
NativeModuleCallExceptionHandler {
@Override
public void handleException(Exception e) {
try {
.
.
.
Crashlytics.logException(new Exception(exceptionString));
} catch (Exception ex) {}
}
Crashlytics仪表板中记录了崩溃,但它显示了单个选项卡中的所有崩溃。这些可能是相同或不同反应原生组件的不同崩溃。
由于这个原因,我们无法找到特定崩溃的实例。需要手动完成崩溃的每个实例。
我想它需要创建异常的类的名称,在本例中为 PlatformNativeModuleCallExceptionHandler 。 我尝试创建自己的自定义异常类,但这也无济于事。
有人知道我们如何更好地将非致命异常分组在这里吗? 所有类似的崩溃应该与它们的总实例组合在一起。
答案 0 :(得分:3)
Crashlytics使用该方法和崩溃行号来对崩溃进行分组,因此如果您有一个针对所有非致命因素的异常处理程序方法,它们将被组合在一起。目前没有解决方法。
答案 1 :(得分:2)
根据生成异常的行号对Crashlytics进行分组,并使用异常类型对其进行标记。如果您知道所有类型的例外,则可以在不同的行上生成每个例外。您还可以将字符串映射到自定义异常类型,以便在Crashlytics中更容易识别它们。
以下是一个例子:
public void crashlyticsIsGarbage(String exceptionString) {
Exception exception = null;
switch(exceptionString) {
case "string1": exception = new String1Exception(exceptionString);
case "string2": exception = new String2Exception(exceptionString);
case "string3": exception = new String3Exception(exceptionString);
case "string4": exception = new String4Exception(exceptionString);
default: exception = new Exception(exceptionString);
}
Crashlytics.logException(exception);
}
class String1Exception extends Exception { String1Exception(String exceptionString) { super(exceptionString); } }
class String2Exception extends Exception { String2Exception(String exceptionString) { super(exceptionString); } }
class String3Exception extends Exception { String3Exception(String exceptionString) { super(exceptionString); } }
class String4Exception extends Exception { String4Exception(String exceptionString) { super(exceptionString); } }
BTW,Crashlytics将忽略Exception中的消息字符串。
答案 2 :(得分:2)
我通过将自定义堆栈跟踪设置为异常来解决此问题。 new Exception(exceptionMessage)
会自己在其中创建异常,我们所做的是抛出一个异常,该异常在catch中称为我的handleException()
的对应对象,并带有exceptionMessage中提供的实际堆栈跟踪。某些解析和exceptionMessage可用于使用exception.setStackTrace()
对新创建的异常设置堆栈跟踪。实际上,这在我的项目中是必需的,只是因为它是跨语言的,对于常规项目,只需传递引发并捕获到感兴趣的位置的异常就行了。
答案 3 :(得分:2)
我发现执行此操作的最佳方法是手动将stacktrace的共享部分切掉:
private fun buildCrashlyticsSyntheticException(message: String): Exception {
val stackTrace = Thread.currentThread().stackTrace
val numToRemove = 8
val lastToRemove = stackTrace[numToRemove - 1]
// This ensures that if the stacktrace format changes, we get notified immediately by the app
// crashing (as opposed to silently mis-grouping crashes for an entire release).
check(lastToRemove.className == "timber.log.Timber" && lastToRemove.methodName == "e",
{ "Got unexpected stacktrace: $stackTrace" })
val abbreviatedStackTrace = stackTrace.takeLast(stackTrace.size - numToRemove).toTypedArray()
return SyntheticException("Synthetic Exception: $message", abbreviatedStackTrace)
}
class SyntheticException(
message: String,
private val abbreviatedStackTrace: Array<StackTraceElement>
) : Exception(message) {
override fun getStackTrace(): Array<StackTraceElement> {
return abbreviatedStackTrace
}
}
通过这种方式可以将消息Timber.e("Got a weird error $error while eating a taco")
参数化,并且该行的所有呼叫都将分组在一起。
显然,numToRemove将需要根据触发非致命事件的确切机制进行更改。
答案 4 :(得分:0)
我刚才正在研究这个问题,因为documentation says:
记录的异常按异常类型和消息分组。
警告: 开发人员应避免在“异常”消息字段中使用唯一值,例如用户ID,产品ID和时间戳。在这些字段中使用唯一值将导致要创建的问题的基数很高。在这种情况下,Crashlytics将限制报告您应用程序中记录的错误。相反,应该将唯一值添加到日志和自定义键。
但是我的经历与众不同。根据我的发现,Alexizamerican said in his answer是正确的,但有一点警告:
按创建异常的方法和行将问题分组,但需要注意的是,此处是考虑到异常的根本原因。
从根本上讲,我的意思是:
public static Throwable getRootCause(Throwable throwable) {
Throwable cause = throwable;
while (cause.getCause() != null) {
cause = cause.getCause();
}
return cause;
}
因此,如果您这样做:
@Override
public void handleException(Exception e) {
// ...
Crashlytics.logException(e);
}
那应该将异常正确地分组在一起。
此外,如果您这样做:
@Override
public void handleException(Exception e) {
// ...
Crashlytics.logException(new Exception(exceptionString, e));
}
这也将正确地将异常分组,因为它将查看e
或其原因,或诸如此类的原因,依此类推,直到到达没有其他原因的异常为止,并且查看堆栈跟踪的创建位置。
最后,与what miguel said不同,根据我的经验,异常类型或消息完全不会影响分组。如果您在特定方法的特定行上有FooException("foo")
,并且用BarException("bar")
替换了它,则由于行和方法没有改变,两者将被分组在一起。