Anim 日志采集插件
Anim 提供了日志采集能力,可以将用户行为/小程序执行错误/业务接口错误通过本地日志与小程序实时日志的方式采集下来,方便后续开发者定位线上问题。Anim 日志采集插件除了支持原生小程序框架外,还可以支持 Uniapp/Taro 等第三方框架。
使用场景
当用户反馈小程序某些 Bug 的时候,如果没有日志辅助定位排查,可能需要耗费大量的时间。
而实时与本地日志插件可以让开发者通过日志快速定位,用户当时小程序所发生的事件,帮助开发者快速解决线上问题。
特别是在部分特殊场景,比如请求还没到网关和后端的时候,后端根本查不了当前用户的日志,
无法确定是用户本身网络问题,还是域名 DNS 解析有问题等等,
前端日志对于这一类问题可以提供非常关键的信息,比如用户请求失败内容,用户当时网络情况等。
本地日志甚至可以做到用户行为回溯
,可以查看到用户打开了哪些页面,点击了哪些按钮等信息,快速模拟出 Bug 的复现路径。
与 RUM 的关系
在很多场景中,对于错误监控我们还会引入 RUM
前端性能监控。对于 anim-plugin-logger
与 RUM
,我们在实践中认为这两者更多是互补的关系,是需要一起使用来帮助开发者更好的定位问题。
RUM
更多的通用的大盘错误监控与性能监控,但是针对某个人在生产环境下的实时错误日志查询这里,并不能做到很好的闭环。RUM
对用户标识我们在实际业务下,更多的是设置为小程序的 openid,但是每个用户的 openid 对于小程序来说都是不一致的,而且需要通过后台的登录接口去换取该 openid。所以 RUM
实际上无法做到真正快速做到根据某个反馈人的微信账号,就可以快速查询到他在某个时间段的相关日志。一旦遇到类似 DNS 域名解析问题,前置网关问题导致换取 openid 的接口都发生了错误,那对于唯一用户的标识都无法获取,定位具体用户问题的难度就更大了。
所以针对这种情况,我们以往的经验都是基于 RUM
做错误监控大盘告警,基于小程序实时日志做到通过微信号直接查询用户的实时错误日志,结合一起来快速定位和判断线上环境的问题。
接入方式
安装插件
npm install @ssv-lab/anim-plugin-logger --save
注意该 npm 包为 Coding Npm 的私有源,请先确定已经正确配置了 Coding Npm
初始化插件
// app.js
import Anim from '@ssv-lab/anim'
import LoggerPlugin from '@ssv-lab/anim-plugin-logger'
// options 配置会在下面详细阐述
Anim.use(LoggerPlugin, {
reportRequestData: true, // 是否上报请求数据
bisDomains: ["example.com"],
errCodes: [
{
codeKey: "errcode",
// 字符串或数字,按照实际接口返回来确定。
// 这里填写的是正确的返回码,不符合这个返回码的都会被当作错误日志进行上报。
errCode: 0
},
{
codeKey: "code",
// 支持多个返回码
errCode: 200
}
]
})
- 点击开发者工具中的菜单栏:工具 --> 构建 npm
- 点击开发者工具中的菜单栏:设置 --> 项目设置 --> 勾选“使用 npm 模块”选项
- 构建完成后即可使用
当使用 Taro 框架时
// app.js
// React/Vue 同理
import { Component } from 'react'
import Anim from '@ssv-lab/anim'
import LoggerPlugin from '@ssv-lab/anim-plugin-logger'
import CryptoPlugin from '@ssv-lab/anim-plugin-api-encrypt'
import './app.css'
Anim
.use(CryptoPlugin, {
publicKeyUrl: 'https://dev-myheart.ssv.tencent.com/kong/requestEncryption/getPublicKey'
})
.use(LoggerPlugin, {
// Vue,
bisDomains: ["https://dev-myheart.ssv.tencent.com"],
errCodes: [],
})
class App extends Component {}
当使用 Uniapp 框架时
// main.js
import Vue from 'vue'
import App from './App.vue'
import Anim from '@ssv-lab/anim'
import LoggerPlugin from '@ssv-lab/anim-plugin-logger'
Anim.use(LoggerPlugin, {
// 这里需要传入 Vue 构造函数
Vue,
bisDomains: ["dev-myheart.ssv.tencent.com"],
errCodes: [
{
codeKey: "errcode",
errCode: 0
}
],
})
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
## 配置说明
### options.reportRequestData
数据类型:`boolean`
是否在命中业务错误时,将请求中的 Body 数据上报到微信实时日志平台。开启后,可以通过对业务接口的请求参数与返回结果,快速判断生产环境的问题。
### options.bisDomains
数据类型:`string[]`
业务白名单,只有命中该白名单的才会触发网络日志上报。
```js
Anim.use(LoggerPlugin, {
bisDomains: ["https://example.com"]
})
options.errCodes
数据类型:{codeKey: string, errCode: string|number}[]
配置符合规范的接口规范,如果不符合错误码规则则会被当成错误日志进行上报。接口已经默认支持 API3.0 的业务上报规则。
Anim.use(LoggerPlugin, {
// 示例解释:错误码为 0 时或者 200 时上报。具体字段根据实际业务来确定。
errCodes: [
{
codeKey: "errcode",
errCode: 0
},
{
codeKey: "code",
errCode: "200"
},
{
codeKey: 'data.errcode', // 支持多层级
errCode: 0
},
{
codeKey: 'code',
errCode: [0, 1, 2, -1001] // 支持多个错误码
}
]
})
options.restfulApis
数据类型:stirng[]
支持统一的聚合接口配置,可以节省很大的配置量
Anim.use(LoggerPlugin, {
"restfulApis": [
"/authentication/realname-aut/v1/"
]
})
重要!restful 接口聚合说明重要!restful 接口聚合说明重要!restful 接口聚合说明 如果后端接口是拼接了用户参数的,为了避免上报上千万个不同 URL ,可以通过配置 restfulApis
参数,将多个接口聚合成一个。
options.Vue
数据类型:Vue Consturctor
对于 uniapp/Taro 等第三方框架,我们依然可以使用该插件,但是当他们的运行框架是 Vue 的时候,需要传入 Vue 构造函数,以便我们能够正确的获取到 Vue 的实例。
// main.js
import Vue from 'vue'
// uniapp 项目中需要传入 Vue 构造函数
Anim.use(LoggerPlugin, {
Vue: Vue,
bisDomains: ["digital.ssv.tencent.com"],
errCodes: [
{
codeKey: "errcode",
errCode: 0
}
],
})
使用说明
1. 本地日志
如果用户有反馈过问题,可通过小程序管理后台 - 管理 - 用户反馈 选择对应用户的日志进行下载


做到「用户行为回溯」,即查看用户去了哪些页面,点击了哪些按钮,并且有哪些请求是有异常。
2. 实时日志
未反馈过问题的用户,可通过小程序管理后台 - 开发 - 开发管理 根据用户的微信号或者 OpenId 进行实时查询

上报事件和内容
上报事件 | 上报标签 | 线上实时日志 | 本地日志(反馈后上传) |
---|---|---|---|
接口请求失败(超时) | RequestFail | ✅ | ✅ |
接口请求异常(CDN 配置,业务域名) | RequestHttpException RequestBusinessException | ✅ | ✅ |
内存告警 | MemoryWarning | ✅ | ✅ |
初始化设备信息 | ReportSystemInfo | ✅ | ✅ |
JS 代码错误 | Error | ✅ | ✅ |
JS 未处理 Promise 拒绝事件 | Reject | ✅ | ✅ |
页面跳转 | Route | ❌ | ✅ |
点击事件 | Tap | ❌ | ✅ |
主动上报错误事件 | BusinessError | ✅ | ✅ |
1. 接口请求失败
触发时机:当 wx.request
走到 fail
回调函数时会触发,通常在请求超时的时候触发
上报标签:RequestFail
上报内容:
{
// 发起请求参数的信息
"request": {
"url": "https://example.com/ebus/photo/v3"
},
// 请求失败返回的错误信息
"error": { "errno": 5, "errMsg": "request:fail timeout" },
// 用户当前的网络情况
"networkInfo": {
"networkType": "wifi",
"signalStrength": -100
}
}
2. 接口请求异常
触发时机:当 wx.request
返回的「HTTP 状态码」或者「业务状态码」异常的时候触发,由线上 CDN 配置控制
上报标签:RequestHttpException
HTTP 状态码,RequestBusinessException
业务状态码
上报内容:
{
"request": { "url": "https://example.com/ebus/photo/v3" },
"response": {
"data": {
"code": "500",
"message": "fail",
"data": null
},
"statusCode": 500,
// 当前用户请求网络状态评估
// https://developers.weixin.qq.com/miniprogram/dev/framework/performance/network.html
"profile": {
"domainLookup": 0,
"connect": 0,
"SSLconnection": 0,
"request": 457,
"response": 0,
"rtt": 179,
"estimate_nettype": 5,
"httpRttEstimate": 581,
"transportRttEstimate": 55,
"downstreamThroughputKbpsEstimate": 1961,
"throughputKbps": 0,
"peerIP": "10.91.29.118",
"socketReused": true,
"sendBytesCount": 568,
"receivedBytedCount": 635,
"protocol": "http/1.1"
}
},
"networkInfo": {
"networkType": "wifi",
"signalStrength": -100
}
}
3. 内存告警
触发时机:当触发 wx.onMemoryWarning
监听回调函数时上报
相关文档:https://developers.weixin.qq.com/miniprogram/dev/api/device/memory/wx.onMemoryWarning.html
上报标签:MemoryWarning
上报内容:
{
"level": {
"level": 15
},
"route": "pages/xxx/jiankangma/index",
"networkInfo": {
"hasSystemProxy": true,
"errMsg": "getNetworkType:ok",
"networkType": "wifi",
"signalStrength": -100
}
}
4. 初始化设备信息
触发时机:当触发其他上报事件时上报,小程序从启动到最终被销毁(杀掉进程)期间只上报一次
上报标签:ReportSystemInfo
上报内容:
{
"SDKVersion": "2.24.3",
"benchmarkLevel": -1,
"brand": "iPhone",
"language": "zh_CN",
"model": "iPhone 12<iPhone13,2>",
"platform": "ios",
"system": "iOS 15.4.1",
"version": "8.0.20"
}
5. JS 代码错误
触发时机:当碰到 JS 代码报错时上报,通过 wx.onError
函数进行监听
上报标签:Error
上报内容:
{
"error": "MiniProgramError\nundefined is not a function (near '...s.forEach...')\nTypeError: undefined is not a function (near '...s.forEach...')\nat forEach (pages/my/index/index.js:489:16)\nat success (utils/rateLimit.js:2192:30)\nat call (miniprogram_npm/aegis-mp-sdk/index.js:17:26336)\nat successHandler (miniprogram_npm/aegis-mp-sdk/index.js:17:27209)\nat (WASubContext.js:2:103485)\nat a (WASubContext.js:2:103689)\nat (WAServiceMainContext.js:2:2360195)\nat AX (WAServiceMainContext.js:2:1958874)\nat success (WAServiceMainContext.js:2:1960580)\nat <api request success callback function>\nat D (WAServiceMainContext.js:2:704105)\nat (WAServiceMainContext.js:2:904657)\nat <NetworkRequest930success callback function>\nat (WAServiceMainContext.js:2:882905)\nat forEach (native code)\nat emit (WAServiceMainContext.js:2:882800)\nat Vd (WAServiceMainContext.js:2:905547)\nat (WAServiceMainContext.js:2:906985)\nat (WAServiceMainContext.js:2:705120)\nat k (WAServiceMainContext.js:2:73065)\nglobal code@",
"path": "pages/my/index/index"
}
6. JS 未处理 Promise 拒绝事件
触发时机:当碰到 JS 未处理 Promise 拒绝事件时上报,通过 wx.onUnhandledRejection
函数进行监听
上报标签:Reject
上报内容:
{
"reason": "ReferenceError: Can't find variable: sfasdf",
"path": "pages/xxx/jiankangma/index"
}
7. 页面跳转
触发时机:当用户进行了路由页面跳转时上报
上报标签:Route
上报内容:
{
"openType": "redirectTo",
"path": "pages/xxx/jiankangma/index"
}
8. 点击事件
触发时机:当用户触发了点击事件时上报
上报标签:Tap
相关文档:https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html#事件对象
上报内容:
{
"type": "tap",
"timeStamp": 795451,
"target": { "id": "", "offsetLeft": 116, "offsetTop": 152, "dataset": {} },
"currentTarget": { "id": "", "offsetLeft": 0, "offsetTop": 0, "dataset": {} },
"mark": {},
"detail": { "x": 120, "y": 167 },
"touches": [
{
"identifier": 996689290,
"pageX": 120,
"pageY": 167,
"clientX": 120,
"clientY": 167,
"force": 0
}
],
"mut": false,
"_userTap": true
}
其他用法
1. 手动上报错误日志 reportError
可使用 Anim.$logger.reportError(err)
上报错误日志,示例如下:
import Anim from '@ssv-lab/anim'
request({
url: 'https://mock.cc/api'
})
.then(res => {
// ... 业务逻辑代码
})
.catch(err => {
// ... 错误逻辑代码
Anim.$logger.reportError(err)
})
上报后,在实时日志上可根据 BusinessError
标签来筛选手动上报的错误日志
2. 日志实例
可使用 Anim.$logger.localLog
上报「本地」日志,示例如下:
import Anim from '@ssv-lab/anim'
// 如果你挂载到了全局可以使用这种方式
// const rateLimit = getApp().rateLimit
Page({
onLoad() {
const localLog = Anim.$logger.localLog
localLog.log('log log log')
localLog.info('hello test hahaha')
localLog.warn('warn')
localLog.error('error')
}
})
可使用 rateLimit.ReportErrorLog.realtimeLog
上报「实时」日志,示例如下:
import Anim from '@ssv-lab/anim'
Page({
onLoad() {
const realtimeLog = Anim.$logger.realtimeLog
realtimeLog.info('hello test hahaha')
realtimeLog.warn('warn')
realtimeLog.error('error')
realtimeLog.setFilterMsg('filterkeyword')
realtimeLog.addFilterMsg('addfilterkeyword')
}
})
信息安全说明
前端日志 SDK 主要上报用户在使用小程序遇到错误的情况下的第三方平台 API 请求信息,目的是为了帮助第三方开发者快速排查缺陷原因,快速修复线上问题。
不会上报请求时用户的输入参数,且错误时请求响应内容也仅包含错误的请求信息,不涉及用户个人信息。
存储上报信息的平台是微信小程序官方的管理后台,没有单独平台另存用户信息,因此不会对用户造成不良影响。