查看原文
其他

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

何瑞 云加社区 2022-06-14


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


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


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

有用户反馈你的网站很慢,然后你立马紧张地在浏览器上打开用户反馈的网站。经过检查,可能你的网站一切正常,也可能你的网站真的很慢,甚至打不开了。
有一天老板问你:咱们的网站性能体验怎么样?你该如何回答?挺好的,很快,这个月没有发生过故障....老板再问:“怎么个好法?” “很快打开”“有多快?” “没统计过....” 然后就没有然后了.....


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


  • 第一时间发现问题

    也许在用户反馈这个问题之前,该问题已经存在多日了,只是一直用户没有反馈。如果有性能方面的监控,可以第一时间去发现问题,及时解决,把影响面、影响时长降到最低。


  • 全面掌握数据,驱动优化性能,提高系统稳定性

    通过监控采集到页面性能、用户使用方面的数据,可以系统、全面地掌握系统运行情况。


  • 提升用户体验

    加快内容显示速度,缩短交互延时。


二、前端性能监控分类


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


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以用户为中心,来衡量页面加载“完成”所用的时间,当页面中最大一块内容被渲染出来时,被认为是页面加载“完成”了。以前,用load\DOMContentLoaded件反应页面加载速度,后来使用了更精准的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。


所以布局偏移分数是:


CLS: 0.75 * 0.25 = 0.1875


  • API 指标关注哪些数据?


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


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


四、前端性能数据采集


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


1. web-vitals库


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

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


如何安装:


npm install web-vitals


使用方法:


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相同。
unloadEventStartunload事件抛出时的时间戳,如果没有上一个文档,这个值会是0。
unloadEventEndunload事件处理完成的时间戳,如果没有上一个文档,这个值会是0。
redirectStart第一个HTTP重定向开始时的时间戳,没有重定向或者重定向中的不同源,这个值会是0。
redirectEnd最后一个HTTP重定向开始时的时间戳,没有重定向或者重定向中的不同源,这个值会是0。
fetchStart浏览器准备好使用HTTP请求来获取文档的时间戳。发送在检查缓存之前。
domainLookupStart域名查询开始的时间戳,如果使用了持续连接或者缓存,则与fetchStart一致。
domainLookupEnd域名查询结束的时间戳,如果使用了持续连接或者缓存,则与fetchStart一致。
connectStartHTTP请求开始向服务器发送时的时间戳,如果使用了持续连接,则与fetchStart一致。
connectEnd浏览器与服务器之间连接建立(所有握手和认证过程全部结束)的时间戳,如果使用了持续连接,则与fetchStart一致。
secureConnectionStart浏览器与服务器开始安全链接握手时的时间戳,如果当前网页不需要安全连接,这个值会是0。‍
requestStart浏览器向服务器发出HTTP请求的时间戳。
responseStart浏览器从服务器收到(或从本地缓存读取)第一个字节时的时间戳。
responseEnd浏览器从服务器收到(或从本地缓存读取)最后一个字节时(如果在此之前HTTP连接已经关闭,则返回关闭时)的时间戳。
domLoading当前网页DOM结构开始解析时的时间戳。
domInteractive当前网页DOM结构解析完成,开始加载内嵌资源时的时间戳。
domContentLoadedEventStart需要被执行的脚本已经被解析的时间戳。
domContentLoadedEventEnd需要立即执行的脚本已经被执行的时间戳。
domComplete‍当前文档解析完成的时间戳。
loadEventStartload事件被发送时的时间戳,如果这个事件还未被发送,它的值将会是0。
loadEventEndload事件结束时的时间戳,如果这个事件还未被发送,它的值将会是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错误信息:


/** * 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错误,例如:

/** * Vue错误捕获 * @param {Object} error 错误对象 */ Vue.config.errorHandler = (error) => { console.log(error); // do something..... };


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


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,即将重磅来袭!

扫码立即参会赢好礼👇


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存