前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >超全对照!前端监控的性能指标与数据采集

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

作者头像
腾讯云开发者
发布2021-06-02 13:40:53
3.1K0
发布2021-06-02 13:40:53
举报

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

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

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

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

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

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

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

二、前端性能监控分类

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

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。

所以布局偏移分数是:

代码语言: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,即将重磅来袭!

扫码立即参会赢好礼?

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯云开发者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
日志服务
日志服务(Cloud Log Service,CLS)是腾讯云提供的一站式日志服务平台,提供了从日志采集、日志存储到日志检索,图表分析、监控告警、日志投递等多项服务,协助用户通过日志来解决业务运维、服务监控、日志审计等场景问题。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档