监控平台前端SDK开发实践

做者简介:杨婷,美团点评点餐终端团队成员。javascript

监控平台

监控的重要性和必要性没必要多说,这是提升故障处理能力和保障服务质量所必须的一环。
那么监控究竟要作什么呢?简而言之:及时上报错误,收集有效信息,提供故障排查依据。前端

  • 及时上报错误:相信每一个程序员都有这样的经验,发生线上问题后,经由运营或者产品反馈到开发人员,其中流转过程多是几分钟甚至几十分钟,这段时间可能直接致使公司的经济损失。若是有一个监控系统,在线上出现问题时,监控系统可以第一时间报警,而且通知到开发人员,那开发人员就能够第一时间修复上线,直接可使公司损失最小化。
  • 收集有效信息:特别是移动时代,定位一个问题时,须要不少用户信息(如用户手机版本,网络状况,操做流程等)。若是没有监控数据,每每只能靠猜,又或是来回找产品运营甚至出现问题的用户去沟通定位,其中不可避免的会花费大量的时间。可是若是监控系统里记录了设备信息,错误发生时的场景信息,以及用户的操做流等程,咱们就能够直接根据这些信息进行问题定位,在最短期内完成故障修复,减少问题的影响面。
  • 提供故障排查依据:监控前端SDK所上报的错误信息和其余的记录信息,其最终目的都是做为咱们排查故障的依据,为咱们保障服务提供坚实的依靠。

监控分类

因此咱们监控平台须要包括记录型监控和捕捉型监控:java

  • 记录型监控
    • 页面访问记录:用户访问了哪些页面
    • 资源加载记录:页面中加载了哪些资源
    • 用户行为记录:用户在页面上作了哪些操做,目前咱们只记录用户的点击行为
    • 接口调用相关记录:页面调用了哪些接口
  • 捕捉型监控
    • DNS劫持:页面是否被劫持
    • 资源加载错误:哪些资源加载失败了,为了捕获跨域js的错误,须要在相应资源标签上添加crossorigin属性。
    • 页面错误:页面渲染过程当中出现的错误
    • 内部逻辑错误:用户特定操做出现的错误,经过用户行为定位
    • 接口错误:调用接口失败

场景还原法

场景还原是监控面板提供的一个很是有用的功能,它将支撑系统处理过的全部记录和错误按照时间顺序展现。经过场景还原的列表,咱们能够还原出指定用户在浏览页面过程当中发生的全部事情及其前后顺序,从而判断问题发生的时机和环境。node

假设如下场景:webpack

PM:BD反馈用户在购物车刷不出来啦!
RD:什么?我试试!我这里能够看到的呀
PM:商户反馈,店里有的用户能够有的用户不行
RD:别急,告诉我shopId和打不开的用户的帐号,我去监控平台上看一下
PM:xxx
RD在监控面板上使用场景还原功能,调出了该用户的全部信息记录。发现该用户是从菜品详情页进入的购物车,而再查看正常的用户都不是从这个入口进的,定位到是菜品详情页跳购物车的部分有问题,并马上进行了修复程序员

在以上这种用户可能有多种操做的场景中,场景还原法能够针对特定用户,还原其完整的操做路径和页面上发生的全部事情,帮助复现问题。
另外,一些非必现的问题,经常是因为不一样机型或环境引发的,也能够在场景还原中复现问题的发生环境予以判断。
web


监控平台整体分为三部分:

  • 监控前端SDK:收集用户端错误和相关信息,并进行上报
  • 监控web层支撑系统:处理上报的监控信息
  • 监控面板:提供实时查看上报信息的面板,方便监控数据的便捷使用

本文主要介绍监控前端SDK的实践经验,仍有许多须要改进的地方,欢迎你们拍砖,帮助咱们改进。ajax

总体设计


如图所示,整个监控平台分为前端SDK、web层支撑系统和监控面板三大部分,前端SDK运行在前端页面中,收集监控数据上报到支撑系统里,做为监控面板上查询的数据源。

就前端SDK来讲,能够分为数据模块、数据处理模块、上报模块三大部分,其中数据模块包括各具体监控数据模块和环境数据模块:api

  • 数据模块
    • 各监控模块:获取须要上报的具体内容信息(EventData或ErrorData)
      • DNS劫持检测
      • 资源完整性检查
      • 资源加载错误
      • API监控
      • 全局错误
      • 用户交互
      • 自定义上报
    • 环境模块:获取环境数据
  • 数据处理模块:将环境数据和各内容数据,处理成接口对应的格式,并返回标准格式数据
  • 上报模块:从环境模块获取环境数据,再和内容数据一块儿根据不一样监控类型分发到对应的数据处理模块。获取标准数据后发送到node层。
    上报模块先查看本地缓存数据,将本地数据和新产生的数据一块儿上报,若上报失败则存入localStorage

详细设计

SDK里采用单例模式,包括各监控模块、环境模块和上报模块。
每一个具体监控模块获取上报模块实例进行上报,上报模块内部保证同时只会有一个上报请求。
事件的监听都在捕获阶段进行,防止由于事件冒泡被阻止而遗漏信息。跨域

环境模块

环境模块收集如下环境信息:项目配置信息、web环境数据、jsbridge环境数据
其余的一些诸如UA、isp等web层能够获取的信息由web层获取。
该模块暴露init和getEnv方法

  • init接收用户配置的环境参数
  • getEnv更新页面url,再返回当前env对象freeze的一个副本

上报模块

采起单请求上报的方式,每一个用户同时只会有一条上报请求,每次将当前记录到的监控信息列表一块儿上报,成功后再继续上报。

上报结束以前的新上报记录都存在localstorage,收到成功消息后删除已上报数据,继续上报,不成功的记录保留在localstorage。此处需注意对localstorage存储的上限作好控制。

在当前没有数据正在上报的状况下触发上报,尝试将当前localstorage的数据和新数据所有上报,若上报记录过多,则分条发送。所有发送完或上报失败,本次上报结束。

各具体监控模块

DNS劫持

HTTPS页面被劫持后页面资源没法获取,劫持者无利可图的状况下会下降劫持的动力。
若仍被劫持,前端资源未到达本地,也没法完成上报,只能从网络层去监控。
因为我司已经全量切了HTTPS,所以该模块不在本监控系统中。
不过以前本团队作过对HTTP域下的劫持检测,其检测思路为请求Node层指定域名下的样本HTML或JS资源,对比返回结果是否符合预期。

资源完整性检查

资源完整性检查模块的任务是记录页面加载了哪些资源,并进行上报。
当咱们排查问题时,能够查看当前页面已经加载成功了哪些资源及其加载顺序,排除由于某些资源没有加载或者加载顺序不当而引发错误的状况。


资源加载完整性检查的上报时机分四类,每次将开始监听到触发上报之间全部记录到的已加载资源一块儿上报,减小上报请求数:

  1. onload:window.onload时触发
  2. onload_timeout: onload超时(5秒)时触发
  3. async:window.onload后必定延时(5秒)触发,上报后中止监听
  4. hash_change:onhashchange开始监听,必定延时(5秒)触发上报,上报后中止监听

内存中维护一个已加载资源的数组,每次上报后删除已上报的资源记录。

资源加载错误监控

window上error事件代理,过滤window自己的error
根据标签类型判断资源类型,src或href为资源地址
为了捕获跨域js的错误,须要在相应资源标签上添加crossorigin属性。

API错误监控

一样采用XMLHttpRequest加hook方式实现。
open时记录接口url,send后根据status判断,接口调用失败时进行上报。

XMLHttpRequest.prototype.open = function open(method, url, bool) {
    monitor.originXHR.open.apply(this, [method, url, bool]);
    // get something...
    // this.ajaxUrl = url;
}

XMLHttpRequest.prototype.send = function send(_data) {
    const self = this;

    this.addEventListener('readystatechange', () => {
        if (self.readyState === 4) {
            if (self.status !== 200 && self.status !== 304 && this.ajaxUrl !== REPORT_URL) { // filter urls
                // report error info
                // ...
                // monitor.reporter.report(dataTypes.API_ERROR, error);
            }
        }
    }, false);

    monitor.originXHR.send.apply(this, [_data]);
};复制代码

过滤掉sdk自己的上报地址(防止上报失败引发循环上报)和一些其余须要忽略的接口地址。

敲黑板,接口访问url时多是一个相对路径,建议补全协议和domain

全局错误监控

监听window上的error事件,过滤事件代理的error。

用户交互监控

监听window上捕获阶段的click事件,记录点击相关数据。

业务代码中能够为比较关注的元素添加data属性,每次点击将会上报被点击元素的指定属性、附加信息和domPath帮助定位该元素。

记录用户交互信息能够明确问题发生时,该场景下用户的具体操做路径,结合环境数据、资源加载记录和错误数据,整个问题场景就一目了然了。

接入方式

sdk的接入方式分为如下两种:

  1. 先加载sdk
    • 优势:能够记录页面加载完成前的状况,加载的资源,以及发生的错误
    • 缺点:影响页面加载速度,直接拷贝在head中,对业务接入不友好
  2. 后加载sdk
    • 优势:不影响页面性能
    • 缺点:只能监控加载成功的页面,但咱们须要关心页面加载失败的场景

为了知足功能须要,当前监控平台v1的引入方式是将压缩后的sdk代码直接引入到被监控页面的head中,并由业务代码初始化配置项目名称等。该步操做能够借助webpack的插件来帮助完成,减轻业务组接入的复杂度。

后续改进方向考虑采用:核心基础库+loaders/plugins 的方式,将必须先加载的sdk代码引入在head中,其他代码等页面加载完成后再异步添加。

以上就是咱们终端团队监控平台前端SDK部分的实践分享啦,欢迎你们批评指正,有好的建议也但愿能提出来帮助咱们改进。咱们后续将不断优化,也将继续与你们保持讨论。耐心看到这里的读者,表示十二万分的感谢~~

相关文章
相关标签/搜索