onBeforeRequest
这个钩子函数会在所有请求发送之前被调用,所有请求内容都会传入它的参数中,必须返回待发送的内容。
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', onBeforeRequest(log) { if (log.type === 'performance') { // Page speed test. Here, you can modify the content of `log`; for example, you can modify the `platform` for page speed test log.url = changeURLArg(log.url, 'platform', type) } return log } });// SEND_TYPE {// LOG = 'log', // Log// SPEED = 'speed', // API and static resource speed test// PERFORMANCE = 'performance', // Page speed test// OFFLINE = 'offline', // Offline log upload// WHITE_LIST = 'whiteList', // Allowlist// VITALS = 'vitals', // Web Vitals// PV = 'pv', // Custom PV// EVENT = 'event', // Custom event// CUSTOM = 'custom', // Custom speed test// SDK_ERROR = 'sdkError', // SDK error// }
beforeReport
1. 该钩子将在日志报告之前执行(对应上报接口为
/collect?
),例如:const aegis = new Aegis({id: 'pGUVFTCZyewxxxxx',beforeReport(log) {// Listen on the reported error belowconsole.log(log); // {level: "4", msg: "An error occurred."}return log;}});throw new Error('An error occurred.');
注意:
上述日志将具有以下字段:
level:日志级别。例如,'4'表示错误日志。
msg:日志内容。
日志级别如下:
{ level: '1', name: 'API请求日志(允许的日志)' }
{ level: '2', name: '通用日志(aegis.info或aegis.infoAll)' }
{ level: '4', name: 'JavaScript执行错误' }
{ level: '8', name: 'Promise错误' }
{ level: '16', name: 'Ajax请求异常' }
{ level: '32', name: 'JavaScript加载异常' }
{ level: '64', name: '图像加载异常' }
{ level: '128', name: 'CSS加载异常' }
{ level: '256', name: 'console.error(保留)' }
{ level: '512', name: '音/视频资源异常' }
{ level: '1024', name: '返回码异常' }
{ level: '2048', name: 'aegis报告' }
{ level: 4096, name: 'PV' }
{ level: 8192, name: '自定义事件' }
{ level: 16384, name: '小程序页面不存在' }
{ level: 32768, name: 'websocket 错误' }
{ level: 65536, name: 'js bridge 错误' }
2. 如果该钩子返回 false,则不会报告日志。该功能可用于过滤掉不需要上报的错误,例如:
const aegis = new Aegis({id: 'pGUVFTCZyewxxxxx',beforeReport(log) {if (log.level === '4' && log.msg && log.msg.indexOf('An error that doesn't need to be reported') !== -1) {return false}return log;}});throw new Error('An error that doesn't need to be reported'); // This error will not be reported
在上面的示例代码中,如果错误内容包含关键字
An error that doesn't need to be reported
,则不会报告给 RUM 后端。onReport
该 hook 在日志上报成功后执行,用法与 beforeReport 类似。它们唯一的区别是,该 hook 接收到的参数都是已经上报的日志,而 beforeReport 接收到的参数是待上报的日志。
beforeReportSpeed
1. 该钩子将在速度测试数据报告之前(
/speed?
)被执行,例如:const aegis = new Aegis({id: 'pGUVFTCZyewxxxxx',reportApiSpeed: true,reportAssetSpeed: true,beforeReportSpeed(msg) {console.log(msg); // {url: "https://localhost:3001/example.e31bb0bc.js", method: "get", duration: 7.4, status: 200, type: "static"}return msg}});
注意:
上面的 msg 将具有以下字段:
url:资源的请求地址。
type:资源类型。
fetch:Aegis 将把该资源报告为 API 请求;
static:Aegis 将把该资源报告为静态资源。
duration:资源请求持续时间。
method:在请求资源时使用的 HTTP 方法。
status:服务器返回的状态码。
payload:向您提供的完整资源请求信息(此字段不会被报告给 Aegis 后端,您可以操纵它)
完整的数据结构如下:
payload.type: 资源请求类型,用于区分原始请求类型。有效值:'fetch'和'xhr'。
payload.sourceURL: 完整的 URL 请求连接。
payload.status: 请求状态码。
payload.headers: 所有请求头,其值都是字符串。
payload.data: 完整的请求资源,您可以自定义它。如果请求类型为 fetch,则为响应对象;如果请求类型为 xhr,则为 XMLHttpRequest 对象。
在上面的示例代码中,每当 Aegis 收集到资源的加载详细信息后,将会使用这些详细信息(即 msg上面返回的)作为参数来调用
beforeReportSpeed
钩子。2. 如果您配置了该钩子,Aegis 最终的上报内容将以钩子的执行结果为准。例如:
const aegis = new Aegis({id: 'pGUVFTCZyewxxxxx',reportApiSpeed: true,reportAssetSpeed: true,beforeReportSpeed(msg) {msg.type = 'static';return msg;}});
上面的代码中,将所有的 msg.type 设置为 static,这意味着所有的资源都将被当成静态资源进行上报,API 请求也将被报至静态资源中。
3. 您可以使用此钩子来纠正 Aegis 类型并判断错误的请求。
如果您有一个 API
https://example.com/api
,其响应标头 Content-Type 为 text/html。正常情况下,RUM 会将此 API 报告为静态资源。但在您的业务中,必须报告为 API 请求,您可以使用以下钩子配置 Aegis 进行修正:const aegis = new Aegis({id: 'pGUVFTCZyewxxxxx',reportApiSpeed: true,reportAssetSpeed: true,beforeReportSpeed(msg) {if (msg.url === 'https://example.com/api') {msg.type = 'fetch';}}});
4. 您还可以屏蔽某些资源的测速上报,例如:
const aegis = new Aegis({id: 'pGUVFTCZyewxxxxx',reportApiSpeed: true,reportAssetSpeed: true,beforeReportSpeed(msg) {// Speed test logs for resources whose address contains `https://example.com/api` will not be reportedif (msg.url.indexOf('https://example.com/api') !== -1) {// If `false` is returned, the reporting of the speed test log will be blockedreturn false}}});
beforeRequest
该钩子将会在所有的数据上报前执行,来帮助用户在数据上报前对其进行屏蔽和修改,当 beforeRequest 返回 false 就可以不上报该条日志,返回修改过后的 data 就可以实现对上报数据的修改,例如:
注意
SDK 版本应大于等于1.24.44。
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;}if (data.logType === 'performance') {// 修改:将性能数据的首屏渲染时间改为2sdata.logs.firstScreenTiming = 2000;}return data;}});
其中,data 将会有以下几个字段:
logType:日志类型,有以下值:
custom:自定义测速
event:自定义事件
log:日志
performance:页面测速
pv:页面 PV
speed:接口和静态资源测速
vitals:web vitals
logs:上报的日志内容:
当 logType 为 'custom' 时,logs 数据类型为
{name: "白屏时间", duration: 3015.7000000178814, ext1: '', ext2: '', ext3: ''}
当 logType 为 'event' 时,logs 数据类型为
{name: "ios", ext1: "", ext2: "", ext3: ""}
当 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, isHttps: true, method: "get", status: 200, type: "static", url: "https://xxxxxx", urlQuery: "max_age=1296000"}
当 logType 为 'vitals' 时,logs 数据类型为
{delta: 1100, entries: [PerformancePaintTiming], id: "v1-1629344653118-4916457684758", name: "LCP", value: 1100}
当 logType 为 'log' 时,logs 数据类型为
{msg: "日志详情", level: '4', ext1: '', ext2: '', ext3: '', trace: ''}
说明
其中 level 枚举值如下:
{ level: '1', name: '接口请求日志(白名单日志)' }
{ level: '2', name: '一般日志(aegis.info 或者 aegis.infoAll)' }
{ level: '4', name: 'JS 执行错误' }
{ 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 错误'}
该钩子返回 false 时,本条日志将不会进行上报,该功能可用来过滤某些不需要上报的错误,可以用来过滤不希望上报的日志。
afterRequest
该钩子将会在测速数据上报后被执行,例如:
注意
SDK 版本应大于等于1.24.44。
const aegis = new Aegis({id: "pGUVFTCZyewxxxxx",afterRequest: function(data) {// {isErr: false, result: Array(1), logType: "log", logs: Array(4)}console.log(data);}});
其中,data 将会有以下几个字段:
isErr:请求上报接口是否错误
result:上报接口的返回结果
logs:上报的日志内容
logType:日志类型,同 beforeRequest 中的 logType。