资讯动态

Expo expo-app-metrics 版本演进详解:从 JS 异常捕获到崩溃报告与网络请求观测

发布时间:2026/9/10 3:23:28 来源:尧图企业网站定制
Expo expo-app-metrics 版本演进详解从 JS 异常捕获到崩溃报告与网络请求观测【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expo本文以 packages/expo-app-metrics/CHANGELOG.md 为骨架完整梳理expo-app-metrics模块的变更历史Unpublished、57.0.0 及此前的补丁版本并结合仓库中的 JS 源码src/installErrorHandler.ts、src/AppMetricsErrorBoundary.tsx与 Android/iOS 原生目录结构解释每一条变更背后的实现机制。读完后你可以掌握如何理解该模块的启动、帧率、内存、会话指标体系JS 异常与崩溃如何落盘并在下次启动时被摄入以及NetworkRequestObserver的原生侧过滤原理。模块概览expo-app-metrics是什么package.json 将其描述为 “Expo module that collects app startup, frame rate, memory, and session metrics”当前版本为57.0.7。从 README.md 可知其安装方式托管managedExpo 项目按官方 API 文档操作裸bareReact Native 项目npm install expo-app-metricsAndroid 无需额外配置iOS 需运行npx pod-install。从源码结构看该模块由三层组成JS 层 src/module.ts通过requireNativeModule(ExpoAppMetrics)暴露原生能力src/module.ts并附带错误处理器安装、错误边界、网络请求 HookAndroid 层 android/src/main/java/expo/modules/appmetrics/appstartup/、frames/、memory/、networkrequests/、jserrors/、crashreporting/、logevents/、storage/、updates/等子包iOS 层 ios/AppStartup/、CrashReporting/、Database/、FrameRate/、LogEvents/、Memory/、NetworkRequests/、Sessions/、Storage/、Updates/等目录。JS 公开 API 与类型定义集中在 src/types.ts核心类型包括AppStartupTimes启动耗时细分、MemoryUsageSnapshot内存快照、FrameRateMetrics帧率统计、Metric/LogRecord指标与日志记录、CrashReport崩溃报告以及NetworkRequestObserver相关类型。Changelog 逐节解读Unpublished未发布变更原文档的 Unpublished 段落共分为四组这里完整继承并按主题重排。破坏性变更Breaking changes[Android] 移除SessionManager插入监听器与JsMetric.metricIdPR #49547。在 Android 侧SessionManager是会话存储的核心见 android/.../storage/SessionManager.kt。移除插入监听器意味着写入路径不再通过回调链路同步派生状态从源码结构看这是为减少数据库插入与监听器之间的竞态所做的简化。[iOS] [Android] JavaScript 异常日志事件从exception重命名为js.exceptionPR #49594。这一点可以从 JS 层类型定义得到印证src/types.ts 中reportError的文档注释明确写道“recorded natively as ajs.exceptionlog event following OpenTelemetrys exception conventions”即异常事件统一遵循 OpenTelemetry 的exception.type/exception.message/exception.stacktrace约定。新特性New features[iOS] [Android] 将带归属信息的原生崩溃派发为 fatal 异常日志PR #49489。崩溃的捕获链路在原生侧实现Android 有 JvmCrashHandler.kt、CrashFileWriter.kt 等先把崩溃写入本地文件下次启动再摄入iOS 则依赖 MetricKit见 ios/MetricKitSubscriber.swift 与 ios/CrashReporting/ 目录。这条变更让这些崩溃数据以fatal级别进入统一的日志事件流而不是只存在于独立的崩溃报告中。logEvent增加可选displayNamePR #47289。在 src/types.ts 中可以看到LogEventOptions.displayName的语义name是稳定的机器标识符而displayName是用于仪表盘展示的人类可读标签不受命名规范约束。原生侧对应的校验逻辑位于 ios/LogEvents/DisplayNameValidation.swift 与 android/.../logevents/DisplayNameValidation.kt。通过AppMetricsErrorBoundary捕获 React 渲染阶段错误PR #47341。实现见 src/AppMetricsErrorBoundary.tsx渲染阶段错误不会到达global.ErrorUtils错误边界是携带 React 组件栈捕获这类错误的手段componentDidCatch中调用AppMetrics.reportErrorsource为errorBoundaryisFatal恒为false因为边界渲染了 fallback应用继续运行React 组件栈作为expo.error.component_stack属性记录见 src/types.tsreportError自身抛出异常时被静默吞掉开发模式下console.warn保证观测边界不会成为新错误的来源fallback支持 React 元素、null或渲染函数函数形态提供error与resetError回调可用于实现“重试”。描述启动所运行的网络连接成本、请求吞吐量以及以slowest.*组取代expo.network.requests.slowestDuration和slowestHostPR #48518。该汇总数据挂在 TTI 指标上expo.network.requests.*参数对应MetricAttributes.params机制src/types.ts由原生侧的网络请求监控在启动窗口内聚合生成Android 见 NetworkRequestMonitor.ktiOS 见 ios/NetworkRequests/NetworkRequestMonitor.swift。缺陷修复Bug fixes[Android] 修复NetworkRequestObserver在响应被不同线程读取与关闭时发出重复事件PR #49609、#49743。[iOS] 保留日志事件时间戳的毫秒精度PR #49141。[Android] 修复 Android 7.x 上的UnsupportedOperationException与NoSuchMethodErrorPR #48577。[iOS] 在更新状态变化时重试 OTAAppInfo补丁PR #48899当模块注册表在expo-updates分配启动流程之前创建时此前整个会话会沿用嵌入构建的更新归属修复后不再出现该问题。更新监控实现位于 ios/Updates/UpdatesMonitoring.swift。[iOS] 修复 FirebaseAuth 首次刷新 token 时的崩溃PR #48360GTMSessionFetcher 会基于session.delegate的类做分支判断而本模块用于网络观测的 delegate 代理此前未应答对包装 delegate 的类/协议检查。这解释了 ios/NetworkRequests/ 目录下存在NetworkRequestTaskSwizzling.swift等代理式拦截实现的原因。[Android] 显式启用buildFeatures.buildConfigPR #47729AGP 9 下必需。其他Others[iOS] 读取待处理指标与日志行时增加可选上限PR #49121[Android] 准备可观测性负载时仅加载请求的指标与日志行PR #49011——两者都指向 MetricsDatabase / MetricsDatabase.kt 的查询路径属于内存与读取性能优化将无更新时的downloadComplete状态事件重命名为downloadCompleteUnavailablePR #47902对应 UpdatesStateEvent / UpdatesStateEvent.swift 的事件模型[iOS] 以应用启动结束标记为基准测量 JS bundle 加载时间PR #47782以保持对后续 React Native 版本的兼容为私有reportError增加用户代码上报的错误来源PR #47871src/types.ts 中source取值为global | errorBoundary | reportedByUser分别对应全局ErrorUtils处理器、错误边界、用户代码显式上报三条捕获路径内部 APIsetErrorHandlerEnabledPR #48506让已安装的全局错误处理器可以“停止上报但不卸载”。实现见 src/installErrorHandler.ts——它只翻转enabled标志处理器本身保持安装且enabled在每次出错时才检查因为处理器在安装时先于任何配置调用生效。会话共享对象 APIPR #46652Android 侧新增 SessionSharedObject.kt配合 JS 的 src/Session.ts为getMainSession()/getForegroundSession()提供共享对象能力。57.0.0 — 2026-06-25大版本功能落地这是当前 Unpublished 之前的功能大版本完整内容如下。新特性iOS 与 Android 上的 HTTP 请求观测PR #46475通过NetworkRequestObserver类与useNetworkRequestObserverHook 向 JS 暴露请求事件TTI 指标同时携带启动窗口内已完成请求的expo.network.requests.*汇总。原生侧过滤PR #46775NetworkRequestObserver支持按 host 与 method 过滤可在构造时或运行时通过setFilter配置未匹配的请求根本不会跨越到 JS。未处理 JS 错误捕获PR #46923包装 React Native 的global.ErrorUtils处理器按 OpenTelemetry 异常约定记录exception日志事件后经 Unpublished 的 #49594 重命名为js.exception致命错误在进程终止前同步写入磁盘下次启动时摄入。Android 崩溃报告PR #46869。iOS 低内存告警记录PR #47108系统发出低内存告警时记录expo.memory.warning日志事件并附带告警时刻的expo.memory.*内存快照。缺陷修复修复 iOS 上整数指标/日志属性等于0或1时被序列化为布尔值的问题PR #47108修复数据库插入之间的竞态条件PR #46702[tvOS] 修复数据库创建路径PR #46715。其他移除不稳定、仅限开发使用的triggerCrash与simulateCrashReportAPIPR #46924新增私有getForegroundSessionPR #46657。补丁版本节奏Changelog 同时展示了该模块的补丁版本发布节奏这些版本均标注 “This version does not introduce any user-facing changes.”属于跟随 Expo SDK 57 的同步发版版本日期57.0.72026-07-2957.0.62026-07-2257.0.52026-07-1757.0.42026-07-1557.0.32026-07-1557.0.22026-07-0357.0.12026-06-2757.0.02026-06-2556.0.192026-06-15无用户可见变更56.0.182026-06-10含 db inserts 竞态修复PR #46702从源码结构看Android 侧每个核心子系统都配有单元测试android/src/test/ 下的crashreporting/、networkrequests/、storage/等目录iOS 侧对应 ios/Tests/JS 侧则有 src/tests/ 中针对AppMetricsErrorBoundary、AppMetricsRoot与installErrorHandler的 native 测试——这些变更的质量由这套测试网保障。关键实现深挖与 Changelog 条目一一对应JS 异常捕获链installErrorHandler如何工作57.0.0 引入、Unpublished 中多次修复与重命名的异常捕获其 JS 侧实现是 src/installErrorHandler.ts。要点导入即生效src/index.ts 在模块导入时直接调用installErrorHandler()注释说明“capture is live as early as the app pulls the module in”幂等installed标志保证只有首次调用真正安装函数也不对外导出链式调用不破坏 RN 默认行为安装前先取ErrorUtils.getGlobalHandler()新 handler 在finally块中无条件调用原 handler——即使上报本身抛异常也不会影响 React Native 开发模式红框、生产模式终止的默认行为可静默setErrorHandlerEnabled(false)只翻转标志“stop reporting without being uninstalled”即 Unpublished 中 #48506 条目。三条捕获路径与reportError的source取值一一对应source触发路径关键代码global全局ErrorUtils处理器未处理错误installErrorHandler.tserrorBoundaryAppMetricsErrorBoundary渲染阶段错误含组件栈AppMetricsErrorBoundary.tsxreportedByUser用户代码显式上报Unpublished #47871 新增src/types.ts网络请求观测原生过滤是核心设计NetworkRequestObserver的类文档src/types.ts阐明了过滤语义这也是 57.0.0 中 #46775 条目的精确展开过滤在原生侧求值未匹配的请求“never materialize arequestStarted/requestCompletedevent”字段间是 AND、同一字段内是 OR未设置字段不加约束空数组则全部丢弃由于过滤只依赖请求发起时已知的属性同一请求的requestStarted/requestCompleted必然成对出现。React 使用者推荐通过 useNetworkRequestObserver Hook 接入其工程细节值得注意每次挂载通过useReleasingSharedObject分配一个NetworkRequestObserverSharedObject卸载时释放并回收原生 delegate 槽位filter 对象被序列化为顺序稳定的 keyfilterKeyOfuseNetworkRequestObserver.ts避免每次渲染因对象字面量不同而重复应用过滤构造器已应用初始 filter后续变更才通过setFilter推送订阅因此不会丢失。原生侧 Android 实现分布在 android/.../networkrequests/含NetworkRequestInterceptor.kt、OkHttpClientProviderHook.kt——即通过 OkHttp 拦截器捕获请求iOS 实现在 ios/NetworkRequests/含NetworkRequestTaskSwizzling.swift。NetworkRequestCompletedEvent携带状态码、协商协议http/1.1/h2/h3、收发字节数、耗时与完整重定向链src/types.ts。崩溃报告与会话存储Changelog 中反复出现的崩溃与会话条目对应两个数据通路崩溃文件通路Android 的 JVM 崩溃由JvmCrashHandler.kt捕获后经CrashFileWriter.kt写为本地文件下次启动由CrashReportProcessor.kt读取并归属到会话iOS 依赖 MetricKit 的 24 小时诊断窗口src/types.ts 中timestampBegin/timestampEnd的文档明确说明了两端时间窗语义差异。CrashReport类型还说明了平台差异iOS 提供 Mach 异常类型/码等数值字段Android JVM 崩溃的exceptionReason是字符串Throwable.toString()加Caused by:链Android 原生崩溃则只带信号与终止原因且无调用栈。SQLite 会话通路MetricsDatabaseios/Database/MetricsDatabase.swift、android/.../storage/MetricsDatabase.kt持久化会话、指标与日志行Unpublished 中 #49011/#49121 的“按需加载行/读取上限”与 #49547 的“移除插入监听器”都是围绕这张表的性能与正确性优化。调试侧 APIgetInactiveSessions()与getAllCrashReports()仅 Android在 src/types.ts 中标注为 debug-only、不稳定供类似 ObserveTester 这类调试应用检视设备上的历史数据。启动时间指标AppStartupTimessrc/types.ts定义了模块的启动耗时模型loadTimeiOS含动态库加载、C 静态构造、Objective-Cload、coldLaunchTime/warmLaunchTime进程冷/热启动到 RN 根视图创建、bundleLoadTimeJS bundle 求值Unpublished #47782 改以启动结束标记为基准、timeToFirstRender/timeToInteractive。JS 侧通过markFirstRender()/markInteractive()src/types.ts配合原生侧 AppStartupManager.kt 与 ios/AppStartup/ 打点。小结packages/expo-app-metrics/CHANGELOG.md 记录的不只是版本号流水57.0.0 建立了“网络请求观测 JS 异常捕获 崩溃报告 低内存告警”的观测能力基线Unpublished 段落则围绕事件命名规范js.exception、崩溃统一为 fatal 日志、存储查询性能与 iOS 兼容性问题持续打磨。每条条目都能在 packages/expo-app-metrics 的 JS、Kotlin、Swift 三层源码中找到对应实现配合 Android/iOS 各自完整的测试目录这套 changelog 是可验证的、与源码一一对应的演进记录。【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价