前端监控

145 阅读7分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 14 天,点击查看活动详情

1、什么是监控?监控的流程有哪些?

是指通过网络获得信息。是指通过网络对远程计算机进行操作。

通过获取信息来发现异常,通过远程操作来恢复异常。

常见的监控有:

机器监控(如内存,网卡,CPU, 磁盘等等)
设备监控(如路由器,交换机等等)
容器监控
站点监控(域名,IP监控)
应用监控(日志监控,Trace探针..)
前端监控

监控的流程包括:

graph TD
数据采集 --> 数据存储 --> 数据计算 --> 数据查看 --> 监控报警

2、为什么需要前端监控?

用户访问您的业务时,整个访问过程大致可以分为三个阶段:

1、页面生产时(服务器端状态)
2、页面加载时
3、页面运行时

为了保证线上业务稳定运行,我们会在服务器端对业务的运行状态进行各种监控。现有的服务器端监控系统相对已经很成熟,而页面加载和页面运行时的状态监控一直比较欠缺。

3、前端监控的能力

性能监控:页面访问速度,包括首次渲染时间,首屏时间,DOM ready 时间,资源加载时间等。

异常监控:JS错误诊断,JS错误的基本信息和分布情况,以及回溯用户行为,帮助你快速定位错误位置。

API请求监控:API的调用情况,调用成功率,返回信息,成功或失败的平均耗时。

前后端链路追踪:将API请求从前端发出到后端调用的链路串联起来,真实还原代码执行的完整现场。

4、常见的监控平台

sentry(开源,可自己搭建), webfunny(收费,但也不贵)...

5、监控的三大核心

  • 用户端 SDK(客户端版、Web 版及小程序版) :负责存储与上报端上日志。
  • 服务器端:负责接收、解析、整合与分析日志。
  • 日志分析平台:提供日志的查询与数据可视化展示。

6、前端性能监控

6.1、常见指标

LCP:Largest Contentful Paint,显示最大内容元素所需时间 (衡量网站初次载入速度)

FID:First Input Delay 首次输入延迟时间 (衡量网站互动顺畅程度)

CLS:Cumulative Layout Shift 累计布局位移 (衡量网页元件视觉稳定性)

image.png

除了以上三个主要衡量指标,还有 FCPTTFB

FCP: First Contentful Paint 首次内容绘制,标记浏览器渲染来自 DOM 第一位内容的时间点

TTFB: Time To First Byte 读取页面第一个字节的时间

6.2、performance API

为了帮助开发者更好地衡量和改进前端页面性能,W3C 性能小组引入了 Navigation Timing API,实现了自动、精准的页面性能打点。

performance 能提供哪些时间节点?在浏览器控制台中执行 window.performance.timing,可以得到类似如下输出:

image.png

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

image.png

上图是实时监控性能模型,可以看到我们的页面加载被定义成了很多个阶段。可以大致分为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() 通过在各个地方打点,标记每个点的执行时间点。

6.3、前端性能监控的关键时间点

开始渲染时间(对应首字节)

浏览器开始绘制页面,在此之前页面都是白屏,所以也称白屏时间

优化内容:优化服务器的响应时间;减少HTML的大小,减少头部资源

计算公式:

var t = performance.timing;

var times = {};

times.firstbyte = t.responseStart - t.domainLookupStart;


dom ready时间(对应dom ready)

优化内容:减少 dom 结构复杂度

计算公式:

var t = performance.timing;
var times = {};

//【重要】解析 DOM 树结构的时间
//【原因】反省下你的 DOM 树嵌套是不是太多了!
times.domReady = t.domInteractive - t.responseEnd;

首屏时间

优化建议:页面首屏时间的显示尽量不要依赖 js, js 尽量放到 domready 后执行和加载

首屏外的图片延迟加载;

首屏结构尽量简单,首屏外的css可延迟加载

onload 时间 (对应完全加载)

优化建议:减少资源的请求数和文件大小

将非初始化脚本放到onload之后执行

无需同步的脚本异步加载

计算公式:

var t = performance.timing;
var times = {};

//【重要】执行 onload 回调函数的时间
//【原因】是否太多不必要的操作都放到 onload 回调函数里执行了,考虑过延迟加载、按需加载的策略么?
times.load = t.loadEventStart - t.fetchStart;