You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 22:25:27