iOS Swift:移除Crashlytics堆栈跟踪最后方法,实现错误正确分组
解决Crashlytics中非致命错误被合并分组的问题
核心原因
你遇到的问题是因为Crashlytics默认根据错误堆栈的顶层调用帧来分组错误,而所有上报都经过你的工具类,导致顶层帧始终是工具类里调用Crashlytics.crashlytics().record()的那行,所以被归为同一错误实例。
方案1:修改错误的堆栈跟踪(最直接有效)
可以手动过滤掉工具类的调用栈元素,让Crashlytics拿到的错误堆栈顶层帧变成调用你工具方法的代码行。
示例代码(Kotlin)
fun recordNonFatalError(error: Throwable) { // 过滤掉当前工具类的堆栈条目 val filteredStack = error.stackTrace.filterNot { // 匹配当前工具类的类名和当前方法名 it.className == this::class.java.name && it.methodName == "recordNonFatalError" } // 创建新的Throwable,保留原错误的信息和过滤后的堆栈 val adjustedError = Throwable(error.message, error.cause).apply { stackTrace = filteredStack.toTypedArray() } // 上报调整后的错误 Crashlytics.crashlytics().record(error = adjustedError) }
示例代码(Swift)
Swift里直接修改Error的堆栈比较麻烦,可以通过自定义Error类型补充调用栈信息:
func recordNonFatalError(_ error: Error) { // 获取调用栈,跳过当前方法和工具类的内部调用 let callStack = Thread.callStackSymbols.dropFirst(2) // 封装带自定义调用栈的错误 let nsError = error as NSError var userInfo = nsError.userInfo userInfo["callerStack"] = callStack.joined(separator: "\n") let adjustedError = NSError( domain: nsError.domain, code: nsError.code, userInfo: userInfo ) Crashlytics.crashlytics().record(error: adjustedError) }
注:Swift中如果要让Crashlytics完全基于调用者分组,可能需要更底层的堆栈处理,但上面的方法至少能让你在控制台区分不同的调用来源,部分版本的Crashlytics也会参考自定义堆栈信息调整分组。
方案2:其他替代思路
- 直接在业务代码中上报:如果工具类的封装带来的分组问题无法接受,可以去掉工具类,直接在每个需要上报的地方调用
Crashlytics.record(),但这会导致代码冗余,不符合代码复用原则。 - 添加自定义标识:在上报时通过
Crashlytics.crashlytics().setCustomKey("callerInfo", value: callerInfo)添加调用者的类名、方法名作为自定义属性,虽然不能改变Crashlytics的自动分组逻辑,但可以在控制台通过自定义键筛选不同的错误实例,方便排查。
内容的提问来源于stack exchange,提问作者Christmasso
相关产品推荐
相关产品推荐

