aegis-rn-sdk 是腾讯云监控团队提供的 React Native 监控 SDK,涵盖了错误监控,接口测速等功能,无需侵入代码,只需引入 SDK 即可自动完成所有监控上报。
使用本 SDK 需要配合使用腾讯云前端性能监控 RUM 平台。
aegis-rn-sdk 是针对 React Native 开发的数据收集和上报 SDK。
在项目支持 NPM 时推荐使用 NPM 安装 Aegis SDK。
$ npm install --save aegis-rn-sdk-ts
本库在官方 aegis-rn-sdk 的基础上做了以下几方面的修改:
官方 aegis-rn-sdk 实际上没有提供 TypeScript 类型定义文件,本库进行了补充。可通过以下方式引入类型声明:
import Aegis, { AegisConfig } from 'aegis-rn-sdk-ts';
const config: AegisConfig = {
id: 'xxxxxxx',
reportApiSpeed: false,
hostUrl: 'https://rumt-zh.com',
env: __DEV__ ? Aegis.environment.development : Aegis.environment.production,
};
const aegis = new Aegis(config);
官方 aegis-rn-sdk 在运行时,内部会抛出异常 ReferenceError: Property 'location' doesn't exist
。本库屏蔽了 LogBox
弹窗,并中断该异常消息的上报。
React Native
有时会自动对 clients3.google.com
发送网络请求,但由于“被墙”导致请求失败,从而触发 Aegis
上报异常消息。本库中断该异常消息的上报。
AsyncStorage
已经过时,将在未来的 React Native
新版本中废弃。因此,本库将 AsyncStorage
替换为 @react-native-async-storage/async-storage
。
使用非常简单,只需要新建一个 Aegis 实例,传入相应的配置即可:
import Aegis from 'aegis-rn-sdk-ts';
const aegis = new Aegis({
id: 'pGUVFTCZyewxxxxx', // 项目上报ID
uin: 'xxx', // 用户唯一 ID(可选)
reportApiSpeed: true, // 接口测速
hostUrl: 'https://rumt-zh.com', // 上报域名,中国大陆 rumt-zh.com
})
::: warning 注意
::: tip 当您做了以上接入工作之后,您已经开始享受 Aegis 提供的以下功能:
1、错误监控:JS执行错误、Promise错误、Ajax请求异常、资源加载失败、retcode异常;
2、测速:接口测速;
3、数据统计和分析:可在 RUM 平台 上查看各个纬度的数据分析;
:::
Aegis SDK 会主动收集用户的一些性能和错误日志,开发者可以根据不同的参数来配置哪些日志需要上报,以及上报的日志具体信息。
全部日志类型如下:
{ logType: 'custom', name: '自定义测速' }
{ logType: 'event', name: '自定义事件' }
{ logType: 'log', name: '日志' }
{ logType: 'pv', name: '页面PV' }
{ logType: 'speed', name: '接口和静态资源测速' }
全部日志等级如下:
{ level: 1, name: '白名单日志' },
{ level: 2, name: '一般日志' },
{ level: 4, name: '错误日志' },
{ level: 8, name: 'Promise 错误' },
{ level: 16, name: 'Ajax 请求异常' },
{ level: 32, name: 'JS 加载异常' },
{ level: 64, name: '图片加载异常' },
{ level: 128, name: 'css 加载异常' },
{ level: 256, name: 'console.error' },
{ level: 512, name: '音视频资源异常' }
{ level: 1024, name: 'retcode 异常' }
{ level: 2048, name: 'aegis report' }
{ level: 4096, name: 'PV' }
{ level: 8192, name: '自定义事件' }
{ level: 16384, name: '小程序 页面不存在' }
{ level: 32768, name: 'websocket错误' }
{ level: 65536, name: 'js bridge错误' }
创建完 Aegis 实例之后,就可以开心的上报日志啦 🥰,日志上报同样简单
aegis.info(
`我是一条白名单上报的信息,只有在白名单中的用户才会上报哟。`
);
aegis.infoAll(
`我是一条普通的信息,如果上报量很大的话请谨慎使用哟。`
);
aegis.report(
new Error('我是一条错误信息,推荐在try..catch或者Promise.reject中使用,另外,我还会参与Aegis评分哟')
);
aegis.error( // aegis.reportError
new Error('我是一条主动上报的JS执行错误,我也会参与Aegis评分哟')
);
info vs infoAll
- 使用 “infoAll ” 所有用户都上报,方便排查问题。但是也会带来一定的上报和存储成本。
- 使用 “info” 白名单上报。出了问题,可能会缺少关键路径日志。需要添加白名单,重新操作收集日志(类似于染色系统操作)。
Aegis SDK 为每个用户设备分配的唯一标示,会存储在 RN 的 aegis 变量里面,用来区分用户,计算 uv 等。
Aegis 实例暴露接口简单实用,目前 Aegis 实例有以下方法供您使用:
setConfig
、 info
、 infoAll
、 report
、 error
、 reportEvent
、 reportTime
、 time
、 timeEnd
、 destroy
该方法用来修改实例配置,比如下面场景:
在实例化 Aegis 时需要传入配置对象
const aegis = new Aegis({
id: 'pGUVFTCZyewxxxxx',
uin: '777'
})
很多情况下,并不能一开始就获取到用户的 uin
,而等获取到用户的 uin
才开始实例化 Aegis 就晚了,这期间发生的错误 Aegis 将监听不到。uin
的设置可以在获取到用户的时候:
const aegis = new Aegis({
id: 'pGUVFTCZyewxxxxx'
})
// 拿到uin之后...
aegis.setConfig({
uin: '777'
})
这三个方法是 Aegis 提供的主要上报手段。
aegis.info('上报一条白名单日志,这两种情况这条日志才会报到后台:1、打开页面的用户在名单中;2、对应的页面发生了错误🤨');
aegis.infoAll('上报了一条日志,该上报与info唯一的不同就在于,所有用户都会上报');
aegis.report(new Error('上报一个错误'));
aegis.error(new Error('主动上报一个JS执行错误'));
该方法可用来上报自定义事件,平台将会自动统计上报事件的各项指标,诸如:PV、UV、平台分布等...
reportEvent 可以支持两种类型上报参数类型,一种是字符串类型
aegis.reportEvent('XXX请求成功');
一种是对象类型,ext1 ext2 ext3 默认使用 new Aegis 的时候传入的参数,自定义事件上报的时候,可以覆盖默认值。
aegis.reportEvent({
name: 'XXX请求成功',
ext1: '额外参数1',
ext2: '额外参数2',
ext3: '额外参数3',
})
注意,额外参数的三个 key 是固定的,目前只支持 ext1 ext2 ext3。
该方法可用来上报自定义测速,例如:
// 假如‘onload’的时间是1s
aegis.reportTime('onload', 1000);
或者如果需要使用额外参数,可以传入对象类型参数,ext1,ext2,ext3 会覆盖默认值:
aegis.reportTime({
name: 'onload', // 自定义测速 name
duration: 1000, // 自定义测速耗时(0 - 60000)
ext1: 'test1',
ext2: 'test2',
ext3: 'test3',
});
onload
可以修改为其他的命名。
该方法同样可用来上报自定义测速,适用于两个时间点之间时长的计算并上报,例如:
aegis.time('complexOperation');
/**
* .
* .
* 做了很久的复杂操作之后。。。
* .
* .
*/
aegis.timeEnd('complexOperation'); /** 此时日志已经报上去了😄**/
complexOperation
同样可以修改为其他的命名。 自定义测速是用户上报任意值,服务端对其进行统计和计算,因为服务端不能做脏数据处理,因此建议用户在上报端进行统计值限制,防止脏数据对整体产生影响。 目前 Aegis 只支持 0-60000 的数值计算,如果大于该值,建议进行合理改造。 高频率的自定义测速上报尽量使用 reportTime。time 和 timeEnd 上报会存在上报值覆盖的问题。比如 aegis.time(aaa), 在调用 aegis.timeEnd(aaa) 之前,又调用了一次 aegis.time(aaa), 则上报的时间为 timeEnd 时间 - 第二次 time 的时间。
该方法用于销毁 sdk 实例,销毁后,不再进行数据上报
aegis.destroy();
白名单功能是适用于开发者希望对某些特定的用户上报更多的日志,但是又不希望太多上报来影响到全部日志数据,并且减少用户的接口请求次数,因为 TAM 设定了白名单的逻辑。
- 白名单用户会上报全部的 API 请求信息,包括接口请求和请求结果。
- 白名单用户可以使用 info 接口信息数据上报。
- info vs infoAll:在开发者实际体验过程中,白名单用户可以添加更多的日志,并且使用 info 进行上报。infoAll 会对所有用户无差别进行上报,因此可能导致日志量上报巨大。
- 通过接口 whitelist 来判断当前用户是否是白名单用户,白名单用户的返回结果会绑定在 aegis 实例上 (aegis.isWhiteList) 用来给开发者使用。
- 用了减少开发者使用负担,白名单用户是团队有效,可以在 应用管理-白名单管理 内创建白名单,则团队下全部项目都生效。
该钩子将会在日志上报前执行,用于对上报数据的拦截和修改,通过返回不同类型的值:
- 拦截:返回false
- 修改:修改入参的值并返回
const aegis = new Aegis({
id: "pGUVFTCZyewxxxxx",
beforeRequest: function(data) {
// 入参 data 的数据结构:{logs: {…}, logType: "log"}
if (data.logType === 'log' && data.logs.msg.indexOf('otheve.beacon.qq.com') > -1) {
// 拦截:日志类型为 log,且内容包含 otheve.beacon.qq.com 的请求
return false;
}
// 入参 data 数据结构:{logs: {}, logType: "speed"}
if (data.logType === 'speed' && data.logs.url.indexOf('otheve.beacon.qq.com') > -1) {
// 拦截:日志类型为 speed,并且接口 url 包含 otheve.beacon.qq.com 的请求
return false;
}
return data;
}
});
其中,msg
将会有以下几个字段:
1.
logs
: 上报的日志内容;
2.
logType
: 日志类型
logType等于custom
时,logs的值如下:
{name: "白屏时间", duration: 3015.7000000178814, ext1: '', ext2: '', ext3: '', from: ''}
logType等于event
时,logs的值如下:
{name: "ios", ext1: "", ext2: "", ext3: ""}
logType等于log
时,logs的值如下:
{ level: '1', msg: '接口请求日志(白名单日志)' } // 具体level信息参考日志等级
logType等于performance
时,logs的值如下:
{contentDownload: 2, dnsLookup: 0, domParse: 501, firstScreenTiming: 2315, resourceDownload: 2660, ssl: 4, tcp: 4, ttfb: 5}
logType等于speed
时,logs的值如下:
// 静态资源
{connectTime: 0, domainLookup: 0, duration: 508.2, nextHopProtocol: "", isHttps: true, method: "get", status: 200, type: "static", url: "https://puui.qpic.cn/xxx", urlQuery: "max_age=1296000"}
// API
{duration: 26, isErr: 0, isHttps: true, method: "GET", nextHopProtocol: "", ret: "0", status: 200, type: "fetch", url: "https://xx.com/cgi-bin/whoami"}
logType等于vitals
时,logs的值如下:
{CLS: 3.365504747991234, FCP: 139.39999997615814, FID: -1, LCP: 127.899}
该钩子函数会在所有请求发出前调用,参数中会传入请求的所有内容,必须返回待发送内容。
function changeURLArg(url,arg,arg_val) {
var pattern=arg+' = ([^&]*)';
var replaceText = arg+'='+arg_val;
if (url.match(pattern)) {
var tmp = '/('+ arg+'=)([^&]*)/gi';
tmp = url.replace(eval(tmp),replaceText);
return tmp;
}
return url;
}
const aegis = new Aegis({
id: 'pGUVFTCZyewxxxxx',
modifyRequest(options) {
if (options.type === 'performance') {
// 页面测速,此时可以修改options内容,如修改页面测速platform
options.url = changeURLArg(options.url, 'platform', type)
}
return options
}
});
该勾子将会在数据上报后被执行,例如:
const aegis = new Aegis({
id: "pGUVFTCZyewxxxxx",
reportApiSpeed: true,
reportAssetSpeed: true,
afterRequest: function(msg) {
// {isErr: false, result: Array(1), logType: "log", logs: Array(4)}
console.log(msg);
}
});
其中,msg
将会有以下几个字段:
1.
isErr
: 请求上报接口是否错误;
2.
result
: 上报接口的返回结果;
3.
logs
: 上报的日志内容;
4.
logType
: 日志类型,有以下值speed:接口和静态资源测速,performance:页面测速,vitals:web vitals,event:自定义事件,custom:自定义测速;
::: warning Aegis 的实例会自动进行以下监控,注意!是 Aegis 实例会进行监控,当您只是引入了 SDK 而没有将其实例化时,Aegis 将什么都不会做。 :::
Aegis通过调用ErrorUtils.setGlobalHandler
函数,在全局注册错误回调函数,用来获取项目中的错误,并自动解析和上报错误。改上报等级为error ,所以,当自动上报的错误达到阈值时,Aegis 将会自动告警,帮助您尽早发现异常。由于上报等级为 error ,自动上报也将影响项目的每日评分。
通过监听 unhandledrejection
事件,捕获到未被 catch
的Promise错误,为了页面的健壮,建议您 catch
住所有的Promise错误哟。
Aegis 将会改写 XMLHttpRequest
对象(请您放心,Aegis很专业),监听每次接口请求,Aegis 认为以下情况是异常情况:
http status
大于等于 400- 请求超时,abort,跨域,cancel
- 请求结束时
http status
仍然是 0,通常发生于请求失败
注意: Aegis SDK 在错误发生的时候,不会主动收集接口请求参数和返回信息,如果需要对进口信息进行上报,可以使用 api 参数里面的 apiDetail 进行开启。
new Aegis({
id: '',
api: {
apiDetail: true,
},
});
同上,Aegis 改写 XMLHttpRequest
对象之后,将获得API返回的内容,并尝试在内容中获取到本次请求的 retcode
。
retcode 的值会从用户返回 response body 的第一层(如果第一层取不到,再取第二层)的 code、ret、retcode、errcode 中获取。 Aegis 默认 retcode 的值为0是正常的,非0都是异常的。当
retcode
发生异常的时候,会上报一个 retcode异常的日志。 用户可以通过 api.retCodeHandler 对这个值和是否异常进行修正。
打开方式:初始化时传入配置
reportApiSpeed: true
Aegis 通过劫持 XHR
及 fetch
进行接口测速,具体代码在 这里
配置 | 描述 |
---|---|
id | 必须,string,默认 无。 开发者平台分配的项目ID |
uin | 建议,string,默认无。 当前用户的唯一标识符,白名单上报时将根据该字段判定用户是否在白名单中,字段仅支持 字母数字@=._- ,正则表达式: /^[@=.0-9a-zA-Z_-]{1,60}$/ |
reportApiSpeed | 可选,boolean 或者 object,默认 false。 是否开启接口测速 |
version | 可选,string,默认 sdk 版本号。 当前上报版本,当页面使用了pwa或者存在离线包时,可用来判断当前的上报是来自哪一个版本的代码,仅支持 字母数字.,:_- ,长度在 60 位以内 /^[0-9a-zA-Z.,:_-]{1,60}$/ |
delay | 可选,number,默认 1000 ms。 上报节流时间,在该时间段内的上报将会合并到一个上报请求中。 |
repeat | 可选,number,默认 5。 重复上报次数,对于同一个错误或者同一个接口测速超过多少次不上报。如果传入 repeat 参数为 0,则不限制。 |
env | 可选,enum,默认 Aegis.environment.production。 当前项目运行所处的环境。| |
api | 可选,object,默认为{}。相关的配置: apiDetail : 可选,boolean,默认false。上报 api 信息的时候,是否上报 api 的请求参数和返回值; retCodeHandler: Function(data: String, url: String, xhr: Object):{isErr: boolean, code: string}, 返回码上报钩子函数。 会传入接口返回数据,请求url和xhr对象; retCodeHandler: Function(data: String, url: String, xhr: Object):{isErr: boolean, code: string}, 返回码上报钩子函数。 会传入接口返回数据,请求url和xhr对象; reqParamHandler: Function(data: any, url: String) 上报请求参数的处理函数,可以对接口的请求参数进行处理,方便用户过滤上报请求参数的信息; resBodyHandler: Function(data: any, url: String) 上报 response 返回 body 的处理函数,可以对接口返回值的 response body 进行处理,只上报关键信息; resourceTypeHandler: Function,请求资源类型修正钩子函数 会传入接口url,返回值为‘static’或‘fetch’。见示例[1] |
hostUrl | 可选,默认是 https://aegis.qq.com 。影响全部上报数据的 host 地址,下面几个 url 地址设置后会覆盖对应的上报地址 | |
url | 可选,string,默认 'https://aegis.qq.com/collect'。 日志上报地址 |
pvUrl | 可选,string, 默认 'https://aegis.qq.com/collect/pv' pv 上报地址 | |
whiteListUrl | 可选,string,默认 'https://aegis.qq.com/collect/whitelist'。 白名单确认接口 如果想要关闭白名单接口请求,可以传空字符串 |
offlineUrl | 可选,string,默认 'https://aegis.qq.com/collect/offline'。 离线日志上报地址 |
eventUrl | 可选,string,默认 'https://aegis.qq.com/collect/events'。 自定义事件上报地址 |
customTimeUrl | 可选,string,默认 'https://aegis.qq.com/speed/custom'。 自定义测速上报地址 |
speedUrl | 可选,string,默认 'https://aegis.qq.com/speed'。 测速日志上报地址 |
ext1 | 可选,string,自定义上报的额外维度,上报的时候可以被覆盖 |
ext2 | 可选,string,自定义上报的额外维度,上报的时候可以被覆盖 |
ext3 | 可选,string,自定义上报的额外维度,上报的时候可以被覆盖 |