微信小程序> AOP方式捕获和处理微信小程序前端全局异常

AOP方式捕获和处理微信小程序前端全局异常

浏览量:1994 时间: 来源:milugloomy

原因

这几天,公司开发的小程序有部分用户用户打开咨询列表页显示空白,我们查后台日志没有错误。最让人头疼的是,这种前端显示不正确,只是在某些机型上才出现,我们的测试人员无法复现该问题。无法复现,又没有错误日志记录,这种问题咋解决?

方案1

思前想后,我们需要将小程序端所有的错误日志记录下来,并上传给后台。因为小程序的特性,除了App.js,所有其他的逻辑都在Page函数中,我们只需要处理Page函数中所有的方法,结合之前的一篇《微信小程序重写Page函数,实现全局日志记录》,我们可以在那基础上继续改写Page函数,使用try catch捕获所有函数的异常,然后将捕获的异常信息上传到服务端。

微信小程序最近推出了小程序的实时日志,结合小程序的实时日志后,我们不需要写相关的后端代码,可将异常信息上传到小程序的平台。(点击链接可查看实时日志详情和使用方式,这里不在多描述)

function init(_data) {  data = _data  // 重写page函数,增加阿里云监控  let oldPage = Page  Page = function(obj) {    // 对Page的传参obj对象的所有函数进行异常捕捉    for (let key in obj) {      let oldFunction = obj[key]      if (typeof oldFunction === 'function') {        obj[key] = function() {          try {            // 日志埋点            if (['onShow', 'onHide'].includes(key)) {              log.info('执行了' + this.__route__ + '的' + key + '方法')              key === 'onShow' ? enterPageLog() : leavePageLog()            }            return oldFunction.call(this, ...arguments)          } catch (e) {            // 上传信息到小程序实时日志            var log = wx.getRealtimeLogManager ? wx.getRealtimeLogManager() : null            log || log.error.call(log, '发生了错误!页面:' + this.__route__ + ',方法:' + key + ',错误信息:' + e.message)            throw e          }        }      }    }    return oldPage(Monitor.hookPage(obj))  }}

这样就通过实时日志功能上传了错误日志到微信小程序的管理后台,通过https://mp.weixin.qq.com登录小程序管理端,就能看到实时日志,通过openid筛选就能查看到对应用户的错误日志,从而排查问题了。

方案2

但微信小程序的错误日志感觉不全,微信那边应该是做了流控或是采样,有些错误没有抓到,造成排查问题的困难。

还是自己动手吧,将错误信息上传到后端。代码如下,只修改了上面上传日志的那一部分

function init(_data) {  data = _data  // 重写page函数,增加阿里云监控  let oldPage = Page  Page = function(obj) {    // 对Page的传参obj对象的所有函数进行异常捕捉    for (let key in obj) {      let oldFunction = obj[key]      if (typeof oldFunction === 'function') {        obj[key] = function() {          try {            // 日志埋点            if (['onShow', 'onHide'].includes(key)) {              log.info('执行了' + this.__route__ + '的' + key + '方法')              key === 'onShow' ? enterPageLog() : leavePageLog()            }            return oldFunction.call(this, ...arguments)          } catch (e) {            const errInfo = '发生了错误!页面:' + this.__route__ + ',方法:' + key + ',错误信息:' + e.message            console.error(errInfo)            // 上传信息到服务端            wx.request({              url: host + '/addWebLog',              method: 'POST',              data: {                errInfo: errInfo              }            })            throw e          }        }      }    }    return oldPage(Monitor.hookPage(obj))  }}

上传到服务器的错误信息包含当前用户、报错页面、报错方法和错误信息,这样我们在服务端就能查看到前端的异常了。

后端处理

新建一个controller来接收这个请求,用于接收前端上传的数据。

@RestControllerpublic class LogController {    private Logger logger = LoggerFactory.getLogger(LogController.class);    private LinkedBlockingQueueWebLog queue;    private Integer Queue_Capacity = 1000; //队列的容量    @Autowired    private JdbcTemplate jdbcTemplate;    @PostConstruct    public void init() {        queue = new LinkedBlockingQueue(Queue_Capacity);        Thread thread = new Thread(() - {            while (true) {                try {                    // 从队列末尾取,取不到则阻塞                    WebLog webLog = queue.take();                    logger.info("前端出错:" + JSONObject.toJSONString(webLog));                    // 数据库操作                    jdbcTemplate.update("insert into web_log(err_info) values(?)", webLog.getErrInfo());                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        });        thread.start();    }    @PostMapping("/addWebLog")    public MonoVoid addWebLog(WebLog webLog) {        // 到达capacity则抛出异常        try {            queue.add(webLog);        } catch (IllegalStateException e) {            System.out.println("队列达到上限:" + queue.size());        }        return Mono.empty();    }    public class WebLog {        private String errInfo;        public String getErrInfo() {            return errInfo;        }        public void setErrInfo(String errInfo) {            this.errInfo = errInfo;        }    }}

为了防止某个功能有bug、大批量出错造成服务器压力,这里添加了一个队列来异步处理请求。Controller收到请求只是将请求丢到队列里,另外一个线程中队列在一个一个取出请求进行处理。队列长度为1000,超过1000的请求直接丢弃。

结语

微信虽然提供了小程序实时日志

其实微信提供了一种错误查询,在微信公众平台小程序可以查看到,但是和小程序实时日志一样有点不好用,我感觉这俩都是对错误进行采样,不是抓取全部错误。例如:开头我描述的那个错误就没找到。

还是自己动手,重写Page函数,catch所有异常,将错误上传给后台比较好排查问题。

 

 

 

 

小程序

版权声明

即速应用倡导尊重与保护知识产权。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至197452366@qq.com ,我们将及时处理。本站文章仅作分享交流用途,作者观点不等同于即速应用观点。用户与作者的任何交易与本站无关,请知悉。

产品经理

手机 : 13312967497

擅长 : 小程序流量变现

扫码领取礼包

最新资讯

热门模板

  • 头条
  • 搜狐
  • 微博
  • 百家
  • 一点资讯
  • 知乎