美文网首页React我爱编程
react-native线上错误分析定位实践

react-native线上错误分析定位实践

作者: jetzhliu | 来源:发表于2018-05-22 13:35 被阅读633次

    最近在处理App项目中的错误上报、错误分析工作,由于项目主要使用react-native开发,这里总结下如何上报RN的错误、奔溃,以及如何定位到源码位置。

    有发布过生产环境的朋友应该清楚,无论是客户端还是web,上线前都是需要经过混淆这一步的,经过混淆,不仅可以减少用户下载的体积,还可以提高破解成本。但混淆过的代码可读性很差,调试困难,对应错误堆栈也很难定位到源码的报错位置。为了解决这个问题,这时候就要请出本文的主角之一“sourcemap”了。

    sourcemap

    sourcemap如字面含义所示:“源码映射”,它的功能是根据转换后的代码位置反推出源码的对应位置。上面说的混淆就是转换之一,其他例如typescript的转译、ES6的转译也属于其中。功能有点类似Android中的mapping.txt或者iOS下的dSYM文件。更详细的介绍可以网上搜索sourcemap,这里就不多做介绍了。

    Sentry

    有了sourcemap这个得力助手,那项目中具体该怎么使用呢?对于线上的应用,错误分析的流程应该是这样子的:捕获代码的错误、异常 --> 上报服务端 --> 根据上报信息中的App版本找到对应的sourcemap文件 --> 根据错误堆栈的行列号信息和sourcemap文件,定位到源码位置。整个流程比较复杂,全部自研稍有成本。经过调研,项目选择了Sentry这个平台用于客户端错误上报及分析。选择 Sentry 主要基于以下考虑:

    • 提供了完善的客户端SDK,Android、iOS、react-native、web全平台支持。各端只需配置上报地址,其余SDK全搞定;
    • 支持上传sourcemap进行源码定位。由于RN运行在客户端中,与普通运行在浏览器的js相比错误堆栈有自己的特点。Sentry是目前调研中唯一一个默认支持react-native错误分析的平台。
    • Sentry从SDK到后端服务都开源,可以私有化部署

    有了Sentry这把瑞士军刀,下面整理下App接入sentry的流程:

    创建项目站点

    image.png

    原生接入react-native-sentry

    # 安装原生依赖,用于上报和手机客户端信息
    npm install react-native-sentry --save
    # 若使用sentry.io的账号,可以用下方命令一键引入原生依赖和初始化
    # react-native link react-native-sentry
    # 若使用自己架设的sentry后端服务,需要手动引入依赖和初始化
    

    Android

    // android/setting.gradle
    include ':react-native-sentry'
    project(':react-native-sentry').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-sentry/android')
    
    // android/app/build.gradle
    // 若项目结构和RN初始化出来的一致,可以使用以下命令在每次构建时上次sourcemap,本项目不使用该方式
    // apply from: "../../node_modules/react-native-sentry/sentry.gradle"
    // 加入依赖
    dependencies {
        compile project(':react-native-sentry')
    }
    
    // android/app/src/main/java/com/reactnativedemo/MainApplication.java
    import io.sentry.RNSentryPackage;
    public class MainApplication extends Application implements ReactApplication {
      private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        @Override
        protected List<ReactPackage> getPackages() {
          return Arrays.asList(
            new MainReactPackage(),
            // 插入下方代码
            new RNSentryPackage(MainApplication.this)
          );
        }
      };
    }
    
    

    iOS

    参考添加其他RN依赖的操作,把node_modules/react-native-sentry/ios/RNSentry.xcodeproj拖到xcode中,并添加libRNSentry.so。

    react-native配置上报地址

    1. 获取上报地址
    image.png
    1. 在入口文件index.js中配置上报地址
    // index.js
    import { Sentry } from "react-native-sentry";
    Sentry.config("上图中的DSN地址").install();
    

    上传sourcemap文件

    通过上述配置,已经可以完成错误上报、统计工作。为了便于定位出错的源码位置,可以考虑上传sourcemap。下图展示了上传sourcemap前后的堆栈信息展示区别:

    image.png

    很明显,得到右边的信息对于解决crash是很关键的

    1. 获取上传文件必须的Auth Token,进入平台/api/路径下,复制已有的或新建一个token;
    image.png
    1. 把配置写到文件.sentry.properties
    # .sentry.properties
    defaults.url=自己的后端服务地址
    defaults.org=项目所在组织
    defaults.project=项目名
    auth.token=上一步复制的token
    cli.executable=/usr/local/bin/sentry-cli
    
    1. 打包时生成sourcemap文件
    react-native bundle \
        --platform android \
        --dev false \
        --entry-file index.js \
        --bundle-output path/to/index.android.bundle \
        --assets-dest path/to/asset \
        --sourcemap-output path/to/index.android.map
    
    1. 安装sentry-cli
    npm -g install sentry-cli
    
    1. 上传sourcemap
    export SENTRY_PROPERTIES=.sentry.properties
    
    sentry-cli releases \
        files RELEASE_NAME \
        upload-sourcemaps \
        --dist DISTRIBUTION_NAME \
        --strip-prefix /path/to/project/root \
        --rewrite \
        path/to/index.android.bundle path/to/index.android.map
    

    RELEASE_NAME: 包名-版本号,如com.example.myapp-1.0.0
    DISTRIBUTION_NAME: 构建号,如52,在Android或iOS项目中设置

    至此,RN版本的sentry集成已完成,web版的线上错误分析定位同样可以借助强大的sentry轻松完成,就不赘述了。以后可能会专门写篇web的sentry集成实践。

    常见问题

    sourcemap上传了,但没有解析出源码位置

    原因1:没有集成原生代码,可以检查上报信息中的SDK信息,确保是通过sentry-react-native上传的:


    image.png

    原因2:版本号没对应上,可以检查上报信息中的APP信息,确保和上传sourcemap时填的一致:


    image.png

    相关文章

      网友评论

      • db7db44889c9:npm -g install sentry-cli时显示TypeError: log.newItem is not a function,难道是node版本问题?
      • JsLin_:link之后打开网站报这个

        Please wait while we load an obnoxious amount of JavaScript.

        You may need to disable adblocking extensions to load Sentry.
        jetzhliu:看我的说明,除非是你打算上报到sentry的官网而不是自己搭的后台,不然不要用react-native link。
        用link命令会自动打开浏览器并且让你填你在sentry官网注册的账号密码,需要准备好梯子。
      • JsLin_:回去研究下
      • Songlcy521:大佬,怎么上传sourcemap呢?ios没有sourcemap,那上传哪个文件呢?
        jetzhliu:很少上简书,回复不及时,抱歉
        sourcemap是js的,和iOS无关。在打包jsbundle的时候带上参数就可以。
        如果是用默认的工程的话,需要修改 `node_modules/react-native/scripts/react-native-xcode.sh` 中打包 js 的那条语句,添加上 --sourcemap-output 参数。
      • 泣之物语:你好,请问我按照sentry官网一步步集成后android的异常找不到SourceCode,请问楼主有类似问题的解决经验吗?artifactis没有相应的map文件,我自己用sentry-cli上传了一个map,但也解析失败,没有任何效果~~
        泣之物语:@jetzhliu 多谢回复~~
        Songlcy521:大佬,怎么上传sourcemap呢?ios没有sourcemap,那上传哪个文件呢?
        jetzhliu:首先确认一下你说的“Android的异常”是指Android上的js异常还是原生的异常。原生的异常不在这里展示。如果是js的异常并且手动上传sourcemap后还是解析失败,参考下我列的两个常见问题。

      本文标题:react-native线上错误分析定位实践

      本文链接:https://www.haomeiwen.com/subject/bqmfjftx.html