65.9K
CodeProject 正在变化。 阅读更多。
Home

我为什么使用 Crashlytics——第二部分

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2014 年 8 月 14 日

CPOL

16分钟阅读

viewsIcon

20471

在本文中,我将讨论这些数据如何帮助您以最少的精力修复最关键的崩溃,并为您的企业创造满意的用户和客户。我还会谈谈我如何在非常大规模的应用程序中使用 Crashlytics。

我为什么使用 Crashlytics——第一部分

我为什么使用 Crashlytics——第二部分

在第一部分中,我讨论了如何设置 Crashlytics 以获取有关崩溃和设备的详细数据,以及如何在 Android Studio 中轻松查看这些数据。在本文中,我将讨论这些数据如何帮助您以最少的精力修复最关键的崩溃,并为您的企业创造满意的用户和客户。我还会谈谈我如何在非常大规模的应用程序中使用 Crashlytics。

细节之美

Crashlytics 的一个优点是崩溃发生时提供的高度详细信息。作为产品经理、开发负责人或工程师,您能够快速评估崩溃对整体安装基数的风险。通过设备和操作系统细分,您可以确定特定崩溃是否仅发生在 Android 2.x 或所有版本(或其他版本)上。您可以确定崩溃是否仅影响特定的设备制造商。这非常有帮助。

我与客户合作评估特定问题风险的方法之一是,将问题统计数据与 Crashlytics 的新移动分析服务 Answers by Crashlytics 的统计数据进行并列比较(如下所示)。利用这些信息,我可以通过查看 Crashlytics 崩溃报告中的用户计数以及来自 Answers 的操作系统版本和设备的每日活跃用户计数,来确定我大部分用户是否会遇到此问题。这些数据将为我提供洞察力,以确定问题是严重的还是仅仅是一个很少遇到的边缘情况(问题计数在这里非常有帮助,并在下一节中更详细地介绍)。

Answers by Crashlytics 提供按操作系统 (OS) 划分的每日活跃用户数的示例屏幕截图。

按设备类型划分的每日活跃用户数的示例屏幕截图。

这些图表提供了大量有用的信息,您可以将其与 Crashlytics 中的问题进行比较。如果您的应用程序偶尔会生成错误,很容易确定要修复什么、如何修复以及何时修复。但是,当您的应用程序规模庞大(数百万用户,数千种设备类型)时,这个过程会变得更加复杂。我学会了依赖 Crashlytics 来帮助确定哪些问题需要快速解决。为此,我们制定了一系列步骤,以帮助我们在 MyFitnessPal 应用程序出现新问题时降低风险。

应用规模和发布后风险缓解实施

Crashlytics 对小型和大型应用都很有用,但当它在规模化应用(数百万用户/安装量)中运行时,它会真正发挥作用,因为您会开始看到您从未遇到过或甚至没想到会在您的应用程序中发生的问题。您将收到有关第三方框架(如广告框架等)以及其他库中发生的崩溃的报告。

在 MyFitnessPal,Crashlytics 帮助我们发现了大量问题。由于 Crashlytics 能够快速、准确地提供大量详细信息来暴露问题,因此我们能够更快、更自信地评估这些问题。使用此工具也大大降低了成本,因为它是一个免费产品。我们的风险分析流程帮助我们确定问题是否需要通过热修复立即修复,或者问题是否足够轻微可以等到下一个次要版本(次要版本是从 3.0.1 变为 3.0.2 或从 3.0 变为 3.1 - 这取决于公司)。

仪表板和风险审查

我认为查看拥有数百万安装量的应用程序的 Crashlytics 仪表板非常重要,因为这种详细程度有助于我们确定下一步行动。下面的屏幕截图是 MyFitnessPal Android 应用程序在 2014 年下半年的 Crashlytics 仪表板。

MyFitnessPal Android 应用程序的 Crashlytics 仪表板

仪表板视图提供了大量详细信息,如下表所述。

1. 应用/包名 应用程序名称和包名。
2. 版本选择器 选择一个版本进行检查,或查看所有版本的汇总。我选择了版本 3.1.1 (4685)。这是您的 AndroidManifest.xml 中的版本名称 (3.1.1) 和版本代码 (4685)。所选版本与下面的 #12 相关。
3. 打开/关闭问题 在打开和关闭的问题之间切换,或显示所有问题。
4. 崩溃/非致命 在崩溃和非致命问题之间切换。
5. 日期/时间选择器 选择要检查问题的时间或日期范围。
6. 搜索 搜索日志、键、问题等。
7. 问题总数 为所选版本创建的各种崩溃和非致命事件导致的问题总数/如果选择了“全部”,则为整个应用程序的崩溃和非致命事件的总数。
8. 总崩溃数和总非致命数(含用户数) 受非致命崩溃影响的总非致命崩溃次数和总用户数。正下方是总崩溃次数和受崩溃影响的总用户数。
9. 时间/日期范围图 给定时间内崩溃次数的可视化图表。
10. 按严重性划分的问题列表计数/全选 给定严重性的崩溃总数。Crashlytics 将问题严重性分为 1-5 级。在此屏幕截图中,您会注意到 5/5 的条形是蓝色的。这意味着该问题是 5 级(最高严重级别)。您还可以使用问题计数旁边的复选框来选择列表中的所有问题并执行批量编辑。
11. Issue 这是问题行。它显示了问题 ID (#26909) 以及关于该问题的一些其他信息。显示了根本代码原因及行号。点击此处可访问本文前面显示的详细问题页面。
12. 版本号 发生崩溃时应用程序的版本号。如果您在版本选择器中选择了“全部”,您将在列表的此列中看到各种值。由于我已在版本选择器中选择了“3.1.1 (4685)”,因此列表中的所有问题在此处都将具有相同的值。
13. 崩溃次数 此问题导致的崩溃总数。
14. 受影响用户数 受此问题影响的总用户数。

结合上述数据和 Crashlytics Answers 中的数据,您可以轻松评估风险。使用 Crashlytics 的另一个免费好处是,它们的严重性排名相当准确,是评估风险的好起点。我不确定它们的严重性算法的确切实现,但它似乎是崩溃发生频率/问题持久性(它是否会持续发生)以及崩溃在 Android OS 和设备中的广度和受影响用户数的组合。

风险分析很简单。一旦您发布了新版本的应用程序。每天检查 Crashlytics 仪表板并执行以下审查

查找在各种操作系统上跨安装量分布最高的崩溃。

例如:如果一个崩溃仅影响运行 Android 2.3.9 的 Droid Razr 设备,而我们的安装量显示只有 0.03% 的用户使用此设备,这占我们总用户量的 0.001%……好吧……这可能不是什么大问题。但是,如果我们看到所有运行 Android 4+ 的三星 S3 和三星 S4 设备都出现了崩溃,并且我们的安装数据表明这占我们安装量和/或用户群的 60%,那么这意味着我们面临一个优先级更高的问题,可能需要热修复。我们需要尽快发布热修复,以降低丢失现有和新用户的风险。

下面是我进行崩溃风险分析的方法。请注意,第一次执行此操作会花费几分钟额外的时间,因为您需要交叉引用数据,但在执行几次后,此过程将变得非常快,您可能不再需要经常参考 Crashlytics Answers 来获取统计数据。我确实建议您每隔几周至少每月检查一次 Crashlytics Answers 中的统计数据,以确保您的启发式方法保持最新(更不用说其中所有其他有用的信息——这本身就应该是一篇帖子)。

Crashlytics 问题风险分析步骤

  1. 审查问题列表和以下指标
    1. 严重性(Crashlytics 通常对此处理得相当好)。我总是先查看 5/5 的问题。
    2. 此问题导致的崩溃总数。
    3. 受影响的用户总数。
  2. 选择一个问题进行深入研究。在问题详细信息屏幕(如上文各部分所示)中打开问题后,审查以下指标
    1. Android 操作系统暴露情况 - 受影响的 OS 有多少?
    2. Android 设备暴露情况 - 受影响的各种设备的百分比?
  3. 现在,将这些指标与您当前的 Crashlytics Answers 统计数据进行交叉引用,以查找您应用程序最受欢迎的 Android 设备和 Android OS。不要跳过此步骤! 这对于每个应用程序和每个市场都不同!
    1. 记录/记住 Top 80% 的 Android OS:通常前 3-5 个将代表您的 80%
    2. 记录/记住 Top 10 Android 设备 - 随着您的应用程序安装基数的增长(尤其是在安装量达到数百万时),您会发现您的顶级设备通常在 10 万到 100 万+ 的安装量之间。请特别关注这些设备,因为您需要能够快速识别可能受影响的顶级设备。
  4. 确定这是否是热修复问题(需要立即修复的问题,还是可以等到下一个版本再修复)。请注意,每个公司的风险承受能力都不同。根据您的风险承受能力进行调整。MyFitnessPal 的风险承受能力与我的新闻阅读应用程序不同。以下数字仅为一般情况。
    1. 如果该问题影响了您 1% 以上的用户,那肯定是一个热修复问题。
      1. 同样,这非常主观。如果您有 1000 个用户中有 10 个遇到了某种非常晦涩且很少发生的错误,那么您可能需要暂时搁置修复。这取决于您。但至少您现在有了得出结论的数据。
    2. 如果该问题影响了您的热门设备之一,且影响比例超过了该问题设备比例的 10%(按设备类型的问题数),那么它很可能需要进行热修复版本发布。
  5. 如果需要热修复,只需更新源代码并发布更新,然后重新开始此过程。

注意:如果您觉得当前问题是需要立即修复的(不考虑指标),那么请务必修复。这只是一个粗略的流程,我用它来帮助确定我是否应该立即或稍后修复某个问题。这是一个我使用的通用指南,您可以随时根据需要进行调整。

大规模崩溃

当您的应用程序达到规模时,您会注意到的另一个现象是,您开始收到关于您不拥有的代码部分中发生的应用程序崩溃报告。例如,这包括广告框架、开源库或商业第三方库(图表等)。当遇到此类问题时,您有几种选择

  1. 如果可能,扩展导致问题的类并修复该问题。
  2. 如果代码是开源的,则 fork 它并修复它,向开源项目提交一个 pull request,并用您 fork 的代码发布应用程序,直到修复被合并到开源项目中。
  3. 联系供应商并让他们修复。

我都用过这三种方法,效果参半。然而,有时有些错误是您根本无法修复的;例如,Android 框架中的错误(是的,这确实会发生)。您最好的做法是尝试在您的源代码中捕获错误并优雅地处理它,因为 Android OS 更新在设备上并不经常发生(除非用户幸运地运行的是 Nexus 设备 - 但即使是这样也会受到限制且速度缓慢)。

使用 Crashlytics 记录异常

好了,报告和数据都很棒,但我该如何记录这些异常呢!?!

Crashlytics 中的崩溃监控是内置的。您只需将其添加到应用程序的入口点(就像在应用的安装部分通过插件完成的那样),然后崩溃报告就会为您处理。报告通过 SSL 传输,因此您不必担心传输信息的安全性。Crashlytics 的源代码非常小(约 45kb),并且对应用程序的启动时间影响极小。但是,Crashlytics 的功能不止于此。它可以做更多的事情。

记录捕获的异常

在编写应用程序时,有时需要将代码包装在 try/catch 中。也许是您预期的网络故障,也许是文件读/写问题,也许是在应用程序处于某种状态时偶尔发生的 null。这些异常本不应发生,但有时却会发生。您和您的团队会尽最大努力优雅地处理这些问题,以避免应用程序崩溃。不幸的是,最终您可能根本不知道某个特定异常被捕获了多少次。Crashlytics 允许您像这样记录捕获的异常

Crashlytics.logException(e);

这会将异常记录为 Crashlytics 中的非致命异常。您可以像查看正常崩溃一样查看这些数据。所有相同的数据都会显示出来。错误行号、堆栈跟踪、操作系统、设备类型等。下面是最近开发的跨平台游戏 QONQR 的屏幕截图。

QONQR Android 应用程序的非致命异常详细信息屏幕截图。在这里,我们在 Android 的 QonqrMap activity 的 onPause 事件中遇到了问题。我们已经修复了它(因为日期图表中没有数据),但我们仍然将其保持打开状态以供审查,因为我们仍在进行更改。

用户信息

在调试生命周期的某些时候,您会发现特定的崩溃仅发生在特定的用户身上。这些问题可能特别难以解决。为了帮助跟踪用户和崩溃,Crashlytics 允许您记录用户信息以帮助您识别用户。这可以通过以下方法之一完成

  • Crashlytics.setUserIdentifier(String identifier);
  • Crashlytics.setUserName(String name);
  • Crashlytics.setUserEmail(String email);

您可以使用 `setUserIdentifier` 方法设置一个 ID、数字或哈希值,该值可以唯一标识您的应用程序用户,而不会泄露或传输他们的任何个人信息。您还可以使用上面列出的其他方法来发送有关用户的数据。

自定义键

除了用户信息之外,跟踪崩溃发生时的上下文也很有用。上下文可以帮助您相对快速地确定问题的根本原因。Crashlytics 允许您通过自定义键记录上下文数据,如下所示

  • Crashlytics.setBool(String key, boolean value);
  • Crashlytics.setDouble(String key, double value);
  • Crashlytics.setFloat(String key, float value);
  • Crashlytics.setInt(String key, int value);

这里有一些如何使用它的示例

  • Crashlytics.setInt("health_points", 1337);
  • Crashlytics.setString("last_action", "logged-food-entry");

这些数据会随崩溃一起发送到 Crashlytics,您可以在问题详细信息屏幕中查看。请注意,Crashlytics 将您限制为 64 个键/值对,但如果您联系支持部门,可能会允许更多。

提示与技巧

以下是我通常与刚开始使用 Crashlytics 的人分享的一些技巧和窍门。希望它们能帮助您。

用于调试和发布构建的 Gradle 构建变体

Crashlytics 应用会自动通过包名添加到组织。您可以在 Crashlytics 初始化周围添加一些逻辑,使其仅在发布模式下运行。如果您不这样做,您将在 Crashlytics 仪表板中遇到一些误报。要解决此问题,我使用 Gradle 和构建变体。因此,在调试模式下,我的包名是 `com.donnfelker.myapp.debug`,而在发布模式下,它是 `com.donnfelker.myapp`。这有助于我将开发中的崩溃与发布中的崩溃分开。

您可以使用简单的 Gradle 构建变体来实现这一点,如下面的代码所示(如果需要,可以编辑/删除混淆配置)

 buildTypes {
        debug {
            packageNameSuffix '.debug'
        }
        release {
            proguardFile 'proguard-project.txt'
        }
    }

现在,当您构建时,“.debug”将附加到调试构建的包名中。请注意,您会注意到我上面包含了 ProGuard。Crashlytics 插件会自动将 ProGuard 映射上传到 Crashlytics,这样您的堆栈跟踪就不会被混淆!太棒了!

Fragment 的 getActivity() 是至少 50% 的错误根源

这很简单。超过 50%(甚至可以说 80%)使用 Fragment 的应用程序在调用 `getActivity()` 方法时都不会检查 null。这会导致大量 `NullPointerException` 被抛出(这会导致应用程序崩溃)。

您的新经验法则应该是:`getActivity()` 始终为 null。如果您这样想,您在使用 `getActivity()` 时的编码方式就会改变,从而始终检查 null。这样做将为您节省大量崩溃报告。

NullPointerException 是您最好的朋友

说起空指针异常……正如我在许多演讲中所说的——预期所有内容都可能为 null,尤其是在 Fragment 中使用 `getActivity()` 时。`NullPointerException` 是最容易修复的异常之一(当它在您的代码中时)。这些问题很快就能解决——只需修复它、测试它、发布它。这些问题很容易解决。但请注意,在规模化应用中,您会遇到比您想象中更多的 `NullPointerException`,而且很多都会发生在您最意想不到的地方。祝您好运。

总结

自 2008 年 Android 公开发布以来,我一直在为 Android 平台开发应用程序。我最初的许多应用程序都属于首批 1000 个发布到 Android Market(现称为 Google Play)的应用程序之列,即使在当时,我的主要关注点也围绕着崩溃报告。多年来,我使用过大量的工具,虽然有些工具在易用性、成本和功能集方面接近 Crashlytics,但没有一个能够超越它。Crashlytics 是我在任何要发布到 Google Play 或 Amazon App Store 的应用程序上安装的第一个库。它可能也应该是您的第一个库。

附注:Crashlytics 现在通过 Beta by Crashlytics(有点像 Testflight,但由 Crashlytics 提供)提供 Beta 分发,并通过 Answers by Crashlytics 提供移动分析。与它们在崩溃报告方面的体验类似,这些新服务是我工具箱中的一个强大工具。如果您使用 Beta 分发或正在寻找强大的移动应用分析工具,您绝对应该尝试一下。

了解更多关于 Android 版 Crashlytics 的信息.

© . All rights reserved.