线上Crash收集工具react-native-sentry

5,484 阅读4分钟

目的

最近公司项目线上环境出现异常崩溃情况,复现步骤都不一样,而且我们本地环境都没有发现问题,导致问题不好排查。之前也集成过Bugly工具,但是Bugly对react-native项目捕捉异常并不是太友好,所以本次添加了react-native-sentry工具,通过bundle文件配合sourcemap来直接定位异常js报错位置。

sourcemap

sourcemap的含义如字面意思,即“源码映射”,他的主要功能是根据转换后的代码反推出所对应的源码的位置,有点类似于iOS中DSYM文件,可以将报错信息符号化得到具体调用方法。

sentry

上边提到sourcemap具有解析转换后代码的功能,而sentry就具备配合bundle+map解析的能力,具体流程为:sentry捕获crash->上报错误到sentry服务端->服务端根据crash应用的id+build number匹配到对应的sourcemap->再根据sentry上报的堆栈信息配合sourcemap定位出错代码。 sentry支持多平台(如下图),并且是开源的,所以公司可以做私有化部署。

avatar

接入步骤

创建对应平台项目

此处选择上图中的React-Native

移动端项目接入原生sdk

avatar

1. npm安装依赖<font color=red>npm install react-native-sentry --save</font> 
    注意:根据rn版本不同需要安装不同版本的sentry,具体可查看https://github.com/getsentry/sentry-react-native
    
2. 将原生依赖添加到项目中
    - 方式一:react-native link react-native-sentry
        注意:使用link的方式默认会将sentry的信息配置成sentry.io,如果使用私有化部署建议手动配置依赖(当前link之后也可以手动更改配置信息但是有点麻烦)
    - 方式二:手动配置
        > iOS:
            1. 将node_modules/react-native-sentry/ios/RNSentry.xcodeproj添加到iOS工程的Libraries
            2. 将libRNSentry.a文件添加到target->Build Phases ->Link Binary With Libraries下
            3. 添加xcode运行脚本:
                1. target->Build Phases ->Bundle React Native coe and images 下运行脚本改为:
                    export SENTRY_PROPERTIES=sentry.properties
                    export NODE_BINARY=node
                    ../node_modules/@sentry/cli/bin/sentry-cli react-native xcode
                    ../node_modules/react-native/scripts/react-native-xcode.sh
                2. target->Build Phases新增一个Run Script并添加脚本
                    export SENTRY_PROPERTIES=sentry.properties
                    ../node_modules/@sentry/cli/bin/sentry-cli upload-dsym
        > Android:
            1. android目录下的setting.gradle添加
                include ':react-native-sentry'
                project(':react-native-sentry').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-sentry/android')
            1. android/app目录下的build.gradle添加
                apply from: "../../node_modules/react-native-sentry/sentry.gradle"
                implementation project(':react-native-sentry')
            2. MainApplication.java对应方法中添加
                import io.sentry.RNSentryPackage;
                protected List<ReactPackage> getPackages() {
                    return Arrays.<ReactPackage>asList(
                        new RNSentryPackage()
                    );
                }
                
3. 项目中添加sentry配置(sentry.properties)
    1. 配置路径分别为:
        - iOS:项目ios目录下
        - Android:项目android目录下
    2. 配置内容
        defaults.url=私有化部署地址(非私有化为https://sentry.io)
        defaults.org=项目组织名
        log.level=日志级别(info)
        defaults.project=项目名称
        auth.token=上传文件所需要的taken(从Sentry Web API下获取)
        cli.executable=本地cli路径(node_modules/@sentry/cli/bin/sentry-cli)
4. js代码配置
    在项目的入口文件index.js(index.ios.js/index.android.js)中配置上报地址
        import { Sentry } from 'react-native-sentry';
        Sentry.config('https://66f8c715cb924ce998383b8248df9b68:93670b64e5d7442695cf465b6e3af14f@sentry.newbanker.cn/17').install();

使用sentry

初尝试

经过以上配置sentry就可以收集到crash信息了,但是收集到的是转换之前的,不好定位具体代码位置,先来看一下此时的crash信息。 在首页的componentDidMount方法中添加一个throw Error('xxx'),运行项目后项目报错,然后到sentry平台看报错信息,此时我们只能粗略看到报错信息如下图所示。

avatar

添加bundle和map文件

1. 打包bundle和生成map文件
    打包代码:
        react-native bundle --entry-file index.ios.js --platform ios --dev false --bundle-output ios/main.jsbundle --assets-dest ios/ --sourcemap-output ios/index.ios.bundle.map

2. 上传资源文件时我们要用的sentry-cli工具,该工具我们在安装react-native-sentry的时候其实已经安装在
node_modules中了,但是为了保证除了这个工程可用,我们可以在全局安装sentry-cli npm -g install @sentry/cli

3. 在电脑根目录(个人喜好)创建全局sentry配置文件sentry.properties,配置内容
    defaults.url=私有化部署地址(非私有化为https://sentry.io)
    defaults.org=项目组织名
    log.level=日志级别
    defaults.project=项目名称
    auth.token=上传文件所需要的taken(从Sentry Web API下获取)
    cli.executable=/xxx(cli安装路径)/sentry-cli
4. 设置环境变量:
    使用的bash就配置.bash_profile,使用的zsh就配置.zshrc,配置内容为:export SENTRY_PROPERTIES=sentry.properties
    保存后在终端执行source .zshrc
5. 上传文件:
    sentry-cli releases files bundleIdentifier-version upload-sourcemaps --dist buildNumber --strip-prefix projectRootDir --rewrite main.jsbundle index.ios.bundle.map
    参数:
        bundleIdentifier-version: 项目id-版本号,如:com.xxx.xx-1.1.1
        buildNumber: 构建号,如:10
        projectRootDir:项目根目录

上传成功后重新运行项目->报错->sentry平台刷新查看上报记录,这次是不是就不一样了,哪一行代码出错清晰可见,如下图所示。

avatar