2

前端性能监控的基本介绍

 1 year ago
source link: https://www.xiabingbao.com/post/fe/fe-monitor-rqz6kd.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
我们主要介绍下前端性能监控的目的、指标,和一些基本的实现思路。

前端性能监控的基本介绍这是我之前在我们团队中做的一次分享,很多地方写的比较简单,就是抛砖引玉,大致讲解下前端性能监控的基本思路。

1. 性能监控的目的、意义

服务上线,才是万里长征的第一步,我们还要根据收集到性能收据和业务数据,进行后续的调整和优化。

web 的性能一定程度上影响了用户留存率,用户各种情况不确定,诸如网络情况,机型,浏览器版本等,或者项目本身的迭代更新。不可能每一项在本地测试过程中,都能覆盖的到。而且,随着版本的迭代,有的指标会发生变化。若没有监控,线上的一切情况对我们来说就是一个黑盒。

因此这里需要一个性能监控系统,监控和预警页面的性能,并且能在发现瓶颈的时候来进行优化。

我们可转化为三个方面来看:响应速度、页面稳定性、外部服务调用

  1. 关注性能指标,提升用户体验:老说性能优化,那哪个性能有问题,得先知道;

  2. 及早发现错误:内部测试时,受限于用户规模小、机型少等原因,无法覆盖到所有场景;通过该监控,可以及早发现错误并修正;不用等待用户的主动反馈(能主动反馈问题的用户都是忠实用户);

  3. 关注第三方系统指标:比如调用的后端接口、其他第三方接口等,可以排查出是前端问题、还是后端问题等;

2. 监控什么指标?

我们在上面分成了三部分来监控,每项细分的话,主要有:

2.1 性能指标

  1. 各种资源的加载时间,包括 html, js, css, img 等资源;

  2. 首页、首屏、整页的渲染耗时(服务端渲染和客户端渲染);

  3. 慢日志(加载在 10s 以上的资源);

比如首屏渲染耗时的计算,根据渲染方式的不同,计算方法也不一样。若采用服务端渲染的,只需要在恰当的位置打点就行。但若采用的是前端渲染,则计算方法就复杂的多。

  1. 在代码组件中上报,比如 useEffect() 中,这对代码的侵入性比较大;

  2. IntersectionObserver + MutationObserver ,监听节点的变化,判断出现在首屏中的节点,待所有的节点都不再变动,则认为首屏渲染完毕(当然,这里也要考虑到图片等资源的耗时);

2.2 各种错误

  1. 未捕获的错误,如从未定义的变量中获取某属性,未 catch 的 Promise 异常等;

  2. 开发者主动抛出的错误,如 console.error;

  3. 静态资源(如图片等)加载异常;

2.3 第三方系统的数据

  1. 请求接口的成功率(如 200、4xx、5xx 等);

  2. 接口的耗时、code 码等;

2.4 公共指标

  1. 当前页的 url;

  2. 设备尺寸、分辨率、设备像素比等;

  3. 用户标识(openid、uid 等)、设备标识;

3. 怎么监控这些指标

3.1 性能指标

性能指标可以通过 performance 来获取。

html 页面的数据,如 ttfb,白屏时间等,可以通过 performance.timing 来获取。

其他的如 jscssimg 等资源,可以通过 performance.getEntries() 来获取。

performance中的各个指标-蚊子的前端博客

3.2 各种错误

被动捕获的全局错误。

window.addEventListenter("error", (event) => {
  upload("error", event);
});

// 未捕获的 reject 错误
window.addEventListenter("unhandledRejection", (event) => {
  upload("unhandledRejection", event);
});

主动输出的错误:

const originalError = console.error;
console.error = (...rest) => {
  originalError(...rest);

  upload("console.error", ...rest);
};

注意,使用throw抛出的错误,会被 onerror 捕获。

3.3 监控接口的数据

一般是劫持发送请求的方法,然后埋上自己的监控代码。

以 XMLHttpRequest 为例,我们要监听的是他的方法,而不是这个类。

const originalSend = XMLHttpRequest.prototype.send;
const originalOpen = XMLHttpRequest.prototype.open;

XMLHttpRequest.prototype.open = function (method, url, ...rest) {
  originalOpen.call(this, method, url, ...rest);
};
XMLHttpRequest.prototype.send = function (data) {
  this.startTime = Date.now();

  const { onloadend, ontimeout } = this;
  this.onloadend = function () {
    onloadend();
  };
  this.ontimeout = function () {
    ontimeout();
  };

  originSend.call(this, data);
};

fetch 方法同理:

const originalFetch = window.fetch;

window.fetch = function (...rest) {
  const startTime = Date.now();

  return originalFetch(...rest).then((response) => {
    upload("fetch", response);

    return response;
  });
};

4. 上报哪些数据

我们依照的原则是:

  1. 在不侵犯用户隐私的前提下,尽可能多维度的收集信息,来更好地分析和定位问题;

  2. 尽量不漏报数据、不死循环(如自己上报自己的错误、劫持方法没写好);

  3. 通用,与前端使用的框架无关;并且,减少开发者的使用负担(能主动收集的,就不麻烦开发者);

给到开发者的都是一些可选的配置,如:

  1. 用户的标识:每个应用对用户的标识是不一样的,可以让开发者自行定义用户的标识,如有的是 openid,有的是 uid,手 Q 里是 uin 等;

  2. 采样率:有的流量特别大的应用,可以设置采样率(0.01~1),避免上报的数据量过多;

  3. 是否是 spa 应用:

5. 如何上报这些数据

有三种方式,主要是前 2 种。

优点缺点
创建 img 图片方式简单,可跨域,兼容性好数据量有限制
xhr 的 post 请求数据大小没有限制需特殊处理跨域限制
navigator.sendBeacon页面卸载前上报数据避免丢失兼容性一般

其实要说 sendBeacon() 的兼容性,目前也算还可以,大部分主流浏览器都是满足的:sendbeacon 的兼容性

有些 sdk 为了避免多次高频的数据上报,也会先在本地积攒一定的数量或时间后,再统一进行上报。

6. 上报之后

数据上报之后,主要是进行 3 个过程:

  1. 数据清洗;

  2. 敏捷分析;

  3. 展示和告警;

6.1 数据清洗

对一些不规范或缺失的数据,进行补全或剔除。

数据清洗-蚊子的前端博客

6.3 展示和告警

从原始的数据中分析出页面的性能和错误率后,需要在某一个平台上进行展示和过滤,方便我们前端开发者可以定位问题。

某平台中的数据展示-蚊子的前端博客

同时,为了及早发现错误,也需要配置相应的告警机制。告警策略也分很多种,如:

  1. 环比:单位时间内数据曲线比前一个周期有激增或急降(大部分都设置这个);

  2. 同比:与昨日同时间段内的数据波动;

  3. 按照不同的字段,告警的单位也是不一样的,如 pv 数据、错误数据等一般是按照百分比;首页耗时等是按照耗时上下限;http code 有的按照具体的数量,有的按照百分比;

告警提示的样例,随便找了张图:

告警提示-蚊子的前端博客

在实际的实现过程中,就要复杂的很多,要考虑的因素也更多。就现在市面上的各种前端监控系统,着重点也不一样,支持的平台也不一样。

比如我曾经使用过的 RUM(之前叫 Aegis),支持的功能就比较多,更多是在前端领域。我摘抄一下RUM 官方的介绍

前端性能监控(Real User Monitoring,RUM)是一站式前端监控解决方案,专注于 Web、小程序等场景监控。前端性能监控聚焦用户页面性能(页面测速,接口测速,CDN 测速等)和质量(JS 错误,Ajax 错误等),并且联动腾讯云应用性能观测实现前后端一体化监控。用户只需要安装 SDK 到自己的项目中,通过简单配置化,即可实现对用户页面质量的全方位守护,真正做到低成本使用和无侵入监控。

但我后来了解到的 Sentry,它是更聚焦在错误日志收集和全链路追踪上,支持前端 js、Node.js、Python、Go 等各种语言环境。如每条的错误信息,除了一些全局数据(如浏览器版本等),还有收集发生该错误前的一些接口请求、console 日志输出和用户的点击行为等,方便我们可以尽可能的还原现场。同时,还对每条的 xhr 请求添加 trace 等请求头参数,便于追踪该请求的整条链路的处理。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK