超全对照!前端监控的性能指标与数据采集

2021-06-02 13:40:53 浏览数 (1)

导语 | 前端监控可以让你更了解自己的网站,更早地发现和解决存在的问题,再通过优化来提升网站的性能和体验。那么,如何衡量一个网站的好坏?有什么指标?性能数据如何采集?本文围绕这些问题和你一起探讨。

一、为什么要做前端性能监控

可能你也有过这样的经历:

有用户反馈你的网站很慢,然后你立马紧张地在浏览器上打开用户反馈的网站。经过检查,可能你的网站一切正常,也可能你的网站真的很慢,甚至打不开了。

有一天老板问你:“咱们的网站性能体验怎么样?”你该如何回答?“挺好的,很快,这个月没有发生过故障....”老板再问:“怎么个好法?” “很快打开”“有多快?” “没统计过....” 然后就没有然后了.....

如果我们有前端监控,就有能力:

  • 第一时间发现问题 也许在用户反馈这个问题之前,该问题已经存在多日了,只是一直用户没有反馈。如果有性能方面的监控,可以第一时间去发现问题,及时解决,把影响面、影响时长降到最低。
  • 全面掌握数据,驱动优化性能,提高系统稳定性 通过监控采集到页面性能、用户使用方面的数据,可以系统、全面地掌握系统运行情况。
  • 提升用户体验 加快内容显示速度,缩短交互延时。

二、前端性能监控分类

性能监控,可分为两类:合成监控和真实用户监控。

1. 合成监控

模拟一个用户使用场景,提交需要进行分析的页面,再通过一系列的打点、分析去完成一些指标项的数据收集,最后呈现分析报告。例如Google的 Lighthouse,目前最新版的google chrome自带的页面性能分析工具。

调出开发工具(win: F12, mac: fn f12)

Lighthouse主要三个指标:性能、可交互性、最佳实践

在性能方面,具体的指标有:

  • First Contentful Paint 首次内容渲染;
  • Time to Interactive 可交互时间;
  • Speed Index 速度指数;
  • Total Blocking Time 总的阻塞时间;
  • Largest Contentful Paint 最大内容渲染;
  • Cumulative Layout Shift 累积布局偏移;

每一项指标还会给出具体的优化建议,例如性能方面的优化建议:

Lighthouse 系统架构图:

2. 真实用户监控

真实用户监控, 记录的是真实的用户当时访问页面时的真实的数据,在访问结果时把采集到的数据上报到服务器,再经过数据清洗、加工等工作后,在监控平台上呈现监控数据。

3. 合成监控和真实用户监控的区别

合成监控的优缺点:

优点

缺点

使用简单,现有工具

模拟用户场景,无法全部还原真实场景

采集数据丰富,如硬件指标、瀑布图

单次运行,数据不够稳定

不影响真实用户访问性能

数据量少,无法覆盖所有场景

真实用户监控的优缺点:

优点

缺点

采集用户真实使用数据

无法采集到硬件相关信息

样本量大,可以全覆盖,减少统计误差

因需要上报,无法采集完整的资源加载瀑布图

性能数据与其它数据关联产生更大的价值

无法可视化展示页面加载过程

区别:

对比项

合成监控

真实用户监控

实现难度&成本

较低

较高

采集数据丰富度

丰富

基础

采集样本量

适用场景

自有业务,用户量小,定性分析

中台产品,用户量大,定量分析

因为真实用户监控也是在运行时执行,所以这种真实用户监控比较难采集到一些硬件相关的指标,也很难去采集这个页面执行的幻灯片(即逐帧截图)。当然技术上可以用JS把当前页面保存成一个Canvas,做一些逐帧对比,甚至把这些数据回传回去。但是在实践过程中,我们肯定不会这样做,因为这对用户的流量是极大的浪费。介绍完这两种监控方案我们来看它们的对比。

本文要讲的是真实用户监控

三、前端性能如何衡量

1. Google Web Vitals

评估一个网站的用户体验涉及到多个指标,有些还与网站的内容有关,但还是有一些共性的指标的,而Core Web Vitals体现了最关键的几项指标。此类核心用户体验需求包括页面内容的加载体验、交互性和视觉稳定性,这些方面共同组成 2020 Core Web Vitals 的基础。

  • LCP:Largest Contentful Paint,显示最大内容元素所需时间 (衡量网站初次载入速度);
  • FID:First Input Delay 首次输入延迟时间 (衡量网站互动顺畅程度);
  • CLS:Cumulative Layout Shift 累计布局位移 (衡量网页元件视觉稳定性);

除了以上三个主要衡量指标,还有FCP和TTFB:

  • FCP: First Contentful Paint 首次内容绘制,标记浏览器渲染来自 DOM 第一位内容的时间点;
  • TTFB: Time To First Byte 读取页面第一个字节的时间;

虽然LCP最大内容绘制是最重要的负载指标,但其也高度依赖于首次内容绘制 (FCP) 和首字节响应时间 (TTFB),这些指标对监控和改进均具有非常重要的意义。

2. API耗时

很多时候页面上的数据是通过异步请求后台API后再进行渲染得到的,API耗时直接影响了LCP数据和用户体验。

  • LCP 最大内容渲染

LCP以用户为中心,来衡量页面加载“完成”所用的时间,当页面中最大一块内容被渲染出来时,被认为是页面加载“完成”了。以前,用loadDOMContentLoaded件反应页面加载速度,后来使用了更精准的FCP(首次内容渲染),但是从用户角度出发,只有主要的内容显示出来了才算是加载完成。

其最大指的是实际Element长宽大小,Margin / Padding / Border等CSS大小效果不计入。包含的种类为<img>,url,<video>及包含文字节点的Block或Inline Element,未来可能会再加入<svg>。因为网页上的Element可能持续加载,最大的Element也可能持续改变 (如文字载入完,然后载入图片) ,所以当每一个当下最大的Element载完,浏览器会发出一个PerformanceEntry Metric,直到使用者可以进行Keydown / Scrolling / Tapping等操作,Browser才会停止发送Entry,故只要抓到最后一次Entry,即能判断LCP的持续时间。

如下图所示,绿色区域是LCP不断改变的侦测对象,也能看到FCP与LCP的判断差异。

  • FID 衡量网站互动顺畅程度

如何衡量网站操作的顺畅程度,Google采用FID指标,其定义为在TTI的时间内第一个互动事件的开始时间与浏览器回应事件的时间差,其互动事件为单次事件如Clicks / Taps / Key Presses等,其他连续性事件Scrolling / Zooming则不计,如下图所示:

为什么要取在TTI发生的第一次的操作事件,Google给的理由有以下三点:

1)使用者的第一次互动体验印象相当重要

2)当今网页最大的互动性问题通常发生在一开始载入时,页面载入完后的第二次操作事件延迟,有其他专门的改善解决建议。

3)但是FID的计算有其明显的问题,如当使用者在Main Thread闲置时操作,那FID可能就短,若不操作则FID则无法计算。这对开发者来说,很难去衡量网站的FID符合良好的标准,所以Google给的建议是透过降低TBT的时间来降低FID的值,当TBT越短,其FID就越好。

  • CLS 衡量网页元件视觉稳定性

你可能有过这样的经历, 当你准备点某一个按钮或内容是,它突然移动了,然后你点了另外一个按钮。

例如下图,当你准备点击“确认提交”按钮时,按钮上方加载了一个提示框,导致下面的按钮被往下移动,在你原来要点击的位置的元素由原来的“确认提交”按钮,变成了“放弃申请”按钮。在你点击时,变成了放弃该订单,前面的工作白白被浪费了,这是大家都不愿意看到的,体验非常不好,令人抓狂。

导致这种预料之外的的内容布局移动,可能是因为资源的异步加载、JS对dom元素的动态操作、未知尺寸图片加载等等。对用户来说,这是一种糟糕的用户体验。CLS就是用来衡量此类的体能指标。

什么是一个好的CLS分数?75%以上的用户小于0.1。

  • 布局偏移的具体内容

布局偏移是由Layout Instability API定义的。这个API会在任意时间上报layout-shift的条目,当一个可见元素在两帧之间,改变了它的起始位置(默认的writing mode下指的是top和left属性)。这些元素被当成不稳定元素。

需要注意的是,布局偏移只发生在已经存在的元素改变起始位置的时候。如果一个新的元素被添加到dom上,或者已存在的元素改变它的尺寸,除非改变了其他元素的起始位置,否则都不算布局偏移。

其 CLS 代表的是每个元素非预期位移的累积,而每个位移的算法如下: 元素位移分数 (Layout Shift Score) = 影响范围 (Impact Fraction) * 移动距离 (Distance Fraction)。

上图中,元素在一帧中占了屏幕的一半。下一帧,元素下移了25%的视图高度。红色虚线框起来的部分就是不稳定元素在两帧的占的视图总和(75%),所以影响分数是0.75。

上图,不稳定元素在纵向移动了25%,所以距离分数是0.25。

所以布局偏移分数是:

代码语言:javascript复制
CLS: 0.75 * 0.25 = 0.1875
  • API 指标关注哪些数据?

除了从请求到返回的耗时外,还有请求列队时间、请求发起时间。

如果一个API从发起请求到数据返回很快,但是由于需要列队等待或是依赖其它数据都原因而被推迟发起请求,从用户角色看,这也是一个很慢的接口。所以作为开发者还需要关注API请求是否能够尽快地被发起。

四、前端性能数据采集

通过上面的内容,我们了解了网站性能监控的一些指标,接下来看看这些指标数据是如何获取的。

1. web-vitals库

对于LCP、FID、CLS数据,可以直接安装web-vitals库:

?(https://github.com/GoogleChrome/web-vitals)

如何安装:

代码语言:javascript复制
npm install web-vitals

使用方法:

代码语言:javascript复制
import {getLCP,getFID,getCLS} from'web-vitals';getCLS(console.log);getFID(console.log);getLCP(console.log);

打开页面,在浏览器控制台上就可以看到类似的数据:

实际使用时把console.log替换成你要处理的方法即可。当然,还可以使用getFCP、getTTFB方法来获取相应的数据。

2. performance API

为了帮助开发者更好地衡量和改进前端页面性能,W3C性能小组引入了Navigation Timing API,实现了自动、精准的页面性能打点。performance能提供哪些时间节点?在浏览器控制台中执行window.performance.timing;可以得到类似如下输出:

这些属性和值代表什么呢?之此之前,我们先来看下这张图:

上图是实时监控性能模型,可以看到我们的页面加载被定义成了很多个阶段。可以大致分为5个阶段:

1)开始计时

2)重定向

3)网络连接

4)数据交互

5)页面渲染

各属性对应的意义如下:

属性

说明

navigationStart

同一个浏览器上下文的上一个文档卸载结束时的时间戳,如果没有上一个文档,这个值会和fetchStart相同。

unloadEventStart

unload事件抛出时的时间戳,如果没有上一个文档,这个值会是0。

unloadEventEnd

unload事件处理完成的时间戳,如果没有上一个文档,这个值会是0。

redirectStart

第一个HTTP重定向开始时的时间戳,没有重定向或者重定向中的不同源,这个值会是0。

redirectEnd

最后一个HTTP重定向开始时的时间戳,没有重定向或者重定向中的不同源,这个值会是0。

fetchStart

浏览器准备好使用HTTP请求来获取文档的时间戳。发送在检查缓存之前。

domainLookupStart

域名查询开始的时间戳,如果使用了持续连接或者缓存,则与fetchStart一致。

domainLookupEnd

域名查询结束的时间戳,如果使用了持续连接或者缓存,则与fetchStart一致。

connectStart

HTTP请求开始向服务器发送时的时间戳,如果使用了持续连接,则与fetchStart一致。

connectEnd

浏览器与服务器之间连接建立(所有握手和认证过程全部结束)的时间戳,如果使用了持续连接,则与fetchStart一致。

secureConnectionStart

浏览器与服务器开始安全链接握手时的时间戳,如果当前网页不需要安全连接,这个值会是0。‍

requestStart

浏览器向服务器发出HTTP请求的时间戳。

responseStart

浏览器从服务器收到(或从本地缓存读取)第一个字节时的时间戳。

responseEnd

浏览器从服务器收到(或从本地缓存读取)最后一个字节时(如果在此之前HTTP连接已经关闭,则返回关闭时)的时间戳。

domLoading

当前网页DOM结构开始解析时的时间戳。

domInteractive

当前网页DOM结构解析完成,开始加载内嵌资源时的时间戳。

domContentLoadedEventStart

需要被执行的脚本已经被解析的时间戳。

domContentLoadedEventEnd

需要立即执行的脚本已经被执行的时间戳。

domComplete‍

当前文档解析完成的时间戳。

loadEventStartload

事件被发送时的时间戳,如果这个事件还未被发送,它的值将会是0。

loadEventEnd

load事件结束时的时间戳,如果这个事件还未被发送,它的值将会是0。

通过以上时间点,我们就可以计算出如下的前端性能指标,如:

重定向耗时

redirectEnd - redirectStart

DNS 解析耗时

domainLookupEnd - domainLookupStart

TCP 连接耗时

connectEnd - connectStart

SSL 安全连接耗时

connectEnd - secureConnectionStart

网络请求耗时 (TTFB)

responseStart - requestStart

数据传输耗时

responseEnd - responseStart

DOM 解析耗时

domInteractive - responseEnd

资源加载耗时

loadEventStart - domContentLoadedEventEnd

首包时间

responseStart - domainLookupStart

白屏时间‍

responseEnd - fetchStart

首次可交互时间

domInteractive - fetchStart

DOM Ready 时间

domContentLoadEventEnd - fetchStart

首屏加载时间

domComplete - navigationStart

除performance.timming外,performance API 还有一些方法帮助你获取到更多有用的信息,例如:

  • performance.getEntries()

获取到每个资源、xmlhttpRequest的相关参数,例如发起时间,资源地址,耗时等。

点击放大

  • performance.getEntriesByType(type)

根据资源类型来查看某种类型的资源耗时等信息。

  • performance.getEntriesByName(name, type)

根据名称和资源来源来获取相关信息。

  • Performance.now()

可用于记录当前代码执行的时间点,不同于new Date().getTime()。

Date().getTime()

毫秒,当前时间戳,受系统时间的影响,距离 1970 的时间;如:1619014021294

performance.new()

微秒(百万分之一秒),时间是以恒定速率递增,不受系统程序执行阻塞的影响,相对于 performance.timing.navigationStart(页面初始化) 的时间。如:3956.404999946244

  • Performance.mark()

通过在各个地方打点,标记每个点的执行时间点。

3. js错误、vue错误、api错误的采集

通过window.onerror可以捕获JS错误信息:

代码语言:javascript复制
  /**   * JS 错误捕获   * @param {String} msg 错误消息   * @param {String} url 引发错误的脚本的URL   * @param {Number} lineNo 发生错误的行号   * @param {Number} columnNo 发生错误的行的列号   * @param {Object} error 错误对象   */  window.onerror = (msg, url, lineNo, columnNo, error) => {   console.log(error.stack);   // do something.....  } ;

vue错误不能使用window.onerror来捕获,vue提供了Vue.config.errorHandler方法来捕获vue错误,例如:

代码语言:javascript复制
  /**   * Vue错误捕获   * @param {Object} error 错误对象   */  Vue.config.errorHandler = (error) => {    console.log(error);   // do something.....  };

如果你使用axios来处理API,在axios发送请求后,使用catch,或在Axios拦截器统一处理,例如:

代码语言:javascript复制
new Promise((resolve, reject) => {axios.post(url, data).then((response) => {}).catch(function(error){console.log(error);// do something.....})})



// 或在Axios拦截器统一处理Axios.interceptors.response.use(  (response) => {  },  (error) => {console.log(error);// do something.....  },);

以上就是关于前端性能监控方面的一些衡量指标、数据采集方法,为下一步的性能优化提供了方向和数据支持。


作者简介

何瑞,腾讯AB实验平台前端开发工程师。


6月5日,Techo TVP 开发者峰会 ServerlessDays China 2021,即将重磅来袭!

扫码立即参会赢好礼?

0 人点赞