漫谈前端监控

976 阅读7分钟

背景

线上应用异常时,第一时间收到反馈,并及时止损

用户访问业务时,整个访问过程大致可以分为三个阶段:页面生产时(服务器端状态)、页面加载时和页面运行时。

服务端的状态由server侧/node进行监控,一般有比较成熟的监控报警机制。而前端要做的就是对页面加载时和页面运行时进行状态监控,主要解决如下几个问题:

  1. 第一时间获取页面异常状态并上报
  2. 完整的重现问题用户的全流程路径,方便开发者复现问题
  3. 详细的错误信息,快速定位解决问题

前端监控主要包含两大块:错误监控和性能监控

错误监控包括业务代码错误,接口错误,框架错误等,错误大多会导致页面功能异常甚至白屏

性能监控包括页面的加载时间,接口响应时间等,会直接影响用户的使用体验

闭环实现

要实现一个线上可用的完整监控方案,大体包含四个阶段:

  1. 日志上报
  2. 日志存储
  3. 统计分析
  4. 数据展示

日志上报

对于前端而言,一般的监控指标都会包含 页面性能、JS异常,资源加载异常;而前端页面通常还需要请求后端服务器数据,因此需要把API请求失败也监控起来,从而覆盖页面访问的全过程

  • 前端异常
异常类型捕获方法
js代码异常window.onerror可以捕获js的全局错误需要写在js脚本的最前面,需要返回true,避免异常继续向上抛,打印到控制台
promise异常catch中单独处理,通过全局的unhandledrejection来监听
框架异常对Vue框架而言,需要使用自带的vue.config.errorHandler处理
静态资源加载异常资源加载的错误不会冒泡到window上,不能被onerror函数捕获,可以通过window.addEventListener来获取
AJAX请求异常重写XMLHttpRequest方法,监听所有请求。但是一般项目中使用的是类似AXIOS的请求库,可以通过拦截器实现监听
跨域Script Error浏览器由于安全原因屏蔽了第三方的错误信息
  • 页面性能

一个页面性能差的话会大大影响用户体验,对于页面性能的采集也尤为重要,常见的方案是通过 performance.timing API 获取;最新的浏览器提供了更高API等级的 performance .getEntriesByType('navigation') API。降级方案则为手动计算关键时间并上报

下图为最新的W3C Navigation Timing 的处理模型: 图片

定义了页面从卸载旧文档、重定向/卸载、应用缓存、DNS 解析、TCP 握手、HTTP 请求处理、HTTP 响应处理、DOM 处理、文档装载完成每个节点的关键时间: 图片

一般比较关注的性能指标是:首字节,白屏时间,首屏时间。基于上述模型,可以得出:

let t = window.performance.timing;

//TTFB 读取页面第一个字节的时间
times.ttfbTime = t.responseStart - t.navigationStart;

//白屏时间 
times.blankTime = (t.domInteractive || t.domLoading) - t.fetchStart;

//首屏时间(domReadyTime)
times.domReadyTime = t.domContentLoadedEventEnd - t.fetchStart;

有了指标,接着就是上报数据,传统的方式是使用img标签进行上报,不存在跨域问题,而且兼容性良好。但是也有一些弊端,如在卸载文档时进行上报,浏览器会延迟卸载以保证图片能正常加载,会影响页面性能,可能会丢失部分日志

  • navigator.sendBeacon

现代浏览器大都支持这一特性,这个方法可以用来发送一些统计和诊断的小量数据,专为上报统计的场景打造。

  1. 数据可靠,浏览器关闭请求也照样能发
  2. 异步执行,不会影响下一页面的加载
  3. API使用简单
window.addEventListener('unload', logData, false);

function logData() {
    navigator.sendBeacon("/log", analyticsData);
}

所以当浏览器支持sendBeacon方法,优先使用该方法,不兼容时使用img方式降级上报。

日志存储

通常前端的日志会通过日志接口上报到服务端进行存储,然后由server进行存储和分析处理。但是在数据上报前,前端需要对日志进行一些处理,常见的有数据的过滤,截断,采样,合并。

比如我们可能会根据业务需要忽略调script error.类型的错误,不进行上报。为减轻服务端压力可以通过采样率对日志进行采样,还可以维护一个队列,对同类日志进行合并后上报

统计分析

对于小应用,可能用数据库单库单表加索引优化就足够了,而一个成规模甚至大流量的应用,需要建设更稳定、高效的日志监控服务。一般使用全文检索搜索引擎Elasticsearch来应对日志的存储和查询,然后我们需要对日志进行多维度的分析:

  • 时间维度
  • 运行环境维度
  • 代码追踪
  • 单用户分析

数据展示

数据经过存储分析之后,就需要直观的展示给开发者,一般都是基于echarts搭建可视化界面进行展示

业界方案

基于公开的资料,主要介绍下美团和阿里在前端监控方面的建设

美团

美团前端监控方案名为:Logan,已在社区开源

Logan包含三大特征:

  • 用户端 SDK(客户端版、Web 版及小程序版):负责存储与上报端上日志
  • 服务器端:负责接收、解析、整合与分析日志。
  • 日志分析平台:提供日志的查询与数据可视化展示。

Logan的特点是比较全,对安卓,苹果,web,小程序都有覆盖,并且有完整的服务端处理机制,提供了全链路的方案实现。我们主要介绍下Logan在前端web监控下的实现。

Logan的前端监控与常规实现的不同点主要为:

  1. 对原生indexDB数据库进行升级,日志由前端进行存储
  2. 基于对称加密和非对称加密对存储的日志进行混合加密
  3. 提供了用户自动上报机制

阿里

阿里的前端监控以阿里云的ARMS为主,ARMS是一套完整监控解决方案,不止前端,还可以对应用,app,容器,业务进行全方位的监控和分析,其中的前端监控主要特点为:

  1. 页面访问速度
  2. 实时监控大屏
  3. JS错误诊断
  4. API请求监控
  5. API请求详情
  6. 自定义统计
  7. 会话追踪

详细的控制台会提供大量的错误信息和全链路的用户路径,ARMS前端监控把页面上发生的各个事件节点定义为用户行为,包括页面加载、路由跳转、页面单击、API请求、控制台输出等信息,按照时间顺序将用户行为串联起来就是用户的行为链路。通过出错时的行为回溯给开发者复现和解决问题提供了很大帮助,并且ARMS是收费的,很多专业能力都需要付费开通

网盘

网盘监控主要基于自研的bad.js和公司级的spy进行前端错误和性能监控,并分别配有错误和性能监控后台提供可视化展示,但信息量相对较少,并配有监控报警平台对问题业务线进行手机和邮件报警,与业界优先方案的对比主要在于:

  1. 没有对日志进行过滤和智能分析
  2. 没有完整的会话追踪
  3. 上报,存储,报警等模块相对独立,没有提供完整的解决方案

前景

前端监控是成熟业务线必备的保障,现阶段主要是对页面的加载性能和JS错误,API请求进行了实时监控,提供了完备的可视化后台对业务信息进行展示,并在异常发生时通知负责人。

未来的监控发力点主要是:

  1. 区分实时、离线数据,并对数据进行整合
  2. 提供最少的堆栈信息,发挥最⼤的作⽤,减轻日志存储压力
  3. 日志后台⾃动分析严重程度、⾃动分析关联性、⾃动过滤噪⾳