一、前言
随着前端的发展和被重视,慢慢的行业内对于前端监控系统的重视程度也在增加。这里不对为什么需要监控再做解释。那我们先直接说说需求。
对于中小型公司来说,可以直接使用三方的监控,比如自己搭建一套免费的sentry就可以捕获异常和上报事件,或者使用阿里云的ARMS,功能比较全面也并不会太贵。类似的开源系统或者付费系统还很多,都能满足我们一定的需求。
假如这个公司逐渐成长,已经成为一个中大型的公司,用户量、业务服务、公司整体架构全部都在升级,这样三方的监控系统可能就慢慢的出现一些不能满足需求的问题。比如企业内部各种系统之间的关系太独立和分散,不能使用内部的统一登陆、不能相互跳转,想要增加一些字段收集并不能很快得到支持等等。这些问题都会导致效率上不能满足企业发展要求。一个内部可控并且能高速响应企业需求的前端监控系统就显得很有必要。
我们在内部的前端监控系统上已经投入了一定的精力和时间,今天分享一下前端监控SDK部分的内容,主要三个方面:
收集哪些数据
客户端SDK(探针)及原理
编写测试用例
二、收集哪些数据前端监控系统最核心的首要是收集客户端的相关数据,我们现在支持的客户端探针有:web、微信小程序、andriod和ios。它们主要收集如图以下信息:
2.1 性能收集页面加载、静态资源、ajax接口等性能信息,指标有加载时间、http协议版本、响应体大小等,这是为业务整体质量提升提供数据支撑,解决慢查询问题等。
2.2 错误收集js报错、静态资源加载错误、ajax接口加载错误,这些常规错误收集都很好理解。下面主要说明一下"业务接口错误(bussiness)":
客户端发送ajax请求后端业务接口,接口都会返回json数据结构,而其中一般都会有errorcode和message两个字段,errorcode为业务接口内部定义的状态码。正常的业务响应内部都会约定比如errorcode==0等,那如果不为0可能是一些异常问题或者可预见的异常问题,这种错误数据就是需要收集的。
由于不同团队或者接口可能约定都不一样,所以我们只会提供一个预设方法,预设方法会在ajax请求响应后调用,业务方自己根据约定和响应的json数据,在预设的方法中编写判断逻辑控制是否上报。像是下面这样:
errcodeReport(res) { if (Object.prototype.toString.call(res) === '[object Object]' && res.hasOwnProperty('errcode') && res.errcode !== 0) { return { isReport: true, errMsg: res.errmsg,code: res.errcode }; } return { isReport: false }; } 2.3 辅助信息除了上面两类硬指标数据,我们还需要很多其它的信息,比如:用户的访问轨迹、用户点击行为、用户ID、设备版本、设备型号、UV/UA标识、traceId等等。很多时候我们要解决的问题并不是那么简单直接就能排查出来,甚至我们需要前端监控和其它系统在某些情况下能够关联上,所以这些软指标信息同样很重要。
在这里专门解释一下traceId:
现在的后端服务都会使用APM(应用性能管理)系统,APM工具会在一次完整请求调用之初生成唯一的id,通常叫做traceId,它会记录整个请求过程服务端的链路细节。如果前端能够获取到它,就能通过它去后端APM系统中查询某次请求的日志信息。只要后端做好相关的配置,后端接口在响应客户端http请求时,可以把traceId返回给客户端,SDK便可以去收集ajax请求的traceId,这样前后端监控就能够关联上了。
2.4 小结收集以上的信息并开发一套管理台,能够达到监控前端性能和异常错误的目的。想象一个场景,当我们收到监控系统的告警或者相关同事的问题反馈时,我们能打开管理台,首先查看到实时的错误,如果发现是js的代码导致的问题,我们能很快找到前端代码错误的地方。如果不是前端的错误,我们通过收集的业务接口错误发现是后端接口的问题,我们也能及时的通知后端同事,在什么时间哪个接口报出errorcode为xx的错误,并且我们还能通过traceId直接查到这次ajax请求的后端链路监控数据。如果实在不是明显就能排查到的问题,我们还能通过收集到的用户轨迹、设备信息和网络请求等数据,多方面的分析还原用户当时的场景,来辅助我们排查代码中的难以复现的bug或者兼容问题。