前端监控sdk实战|青训营笔记

136 阅读5分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 16 天

关于前端监控

什么是前端监控

采集“输入URL到页面显示的过程”和“用户后续交互”中产出的性能指标与发生的异常事件,并上报平台完成消费

为什么要前端监控

  • 用户遇到的问题

    • 打开慢
    • 交互卡
    • 资源加载失败
    • 页面无法显示
  • 没有监控,无法获得问题发生的原因,无法解决问题

  • 有了监控,可以得知导致问题的地方,优化代码、优化体验

  • 页面性能对业务非常重要,直接和用户数量关联

前端监控要监控什么

  • 性能指标
  • 异常事件
  • 用户行为

概述:前端监控之常用性能指标

web性能标准的发展

  • 早期网页是静态的,没有性能问题
  • 随着网页变为动态,性能开始需要评测
  • 传统性能指标:只关注技术细节,过程+耗时
  • 以用户为中心的性能指标:因为优化加载速度不一定实现提升用户体验,所以需要用户为中心

以用户为中心的性能指标

  • 发生了吗? FP(首次渲染时间),FCP(首次有内容的渲染时间)
  • 内容有用吗? FMP(首次绘制有意义内容时间),SI(页面可视区域加载速度),LCP(最大的内容变得可见的时间点,容易理解计算上报)
  • 内容可用吗? TTI(可靠响应用户交互时间),TBT(加载期间无法响应用户输入的时间,可以量化主线程的繁忙程度)
  • 令人愉悦吗? FID(用户首次与页面交互到浏览器相应交互花费的时间),CLS(页面加载时元素偏移程度)

前端常见异常

静态资源错误

  • 静态资源:html, css, js, 多媒体文件(图片,音频,视频)
  • 静态资源错误:拉取资源的时候发生预期之外的错误,如网络异常,最后导致静态资源无法渲染

请求异常

  • HTTP请求状态码大于等于400,属于请求异常,包括客户端错误和服务端错误
  • fetch异步请求错误也属于请求异常
  • 状态码为0的时候,表明请求被停止

JS错误

  • 有些JS错误会影响页面的渲染和交互
  • 一般在控制台可以看到错误信息
  • 是前端监控的重点

白屏异常

  • 页面上没有信息

  • 没法通过浏览器监听到

  • 可以通过判断DOM树的结构粗略判断

  • 白屏归因

    • JS错误导致关键资源加载失败
    • 请求异常,静态资源加载失败
    • 长时间JS线程繁忙阻塞任务

监控前端性能与异常

性能指标监控

原理

利用浏览器提供的Performance, PerformanceObserver,建议先参考标准文档

监听FP, FCP, LCP, FIP

  • FP, FCP 通过 paint 监听
  • LCP 通过 largest-contentful-paint 监听
  • FIP 通过 first-input 监听

PerformanceObserver监听

  1. 新建Observer,接收参数list
  2. 启动Observer,用要监听的类型组成字符串数组,将数组传入observe函数

performance对象监听

  • window.performance.getEntriesByType()函数
  • 在渲染结束之后调用
  • 对象的属性少于Observer

封装monitor

  • 需求

    • 起名字
    • 监听能力
    • 主动开启(而不是被动开启)
    • 上报能力
  • 写一个函数,将监听作为成员函数

  • 返回名字和监听函数

  • 高阶函数使用上报函数作为参数

  • 在监听成员函数里面调用上报函数

JS错误监控

原理

根节点/window注册监听器,监听error event。unhandledrejection用来监听Promise的异常。

error event监听

  1. 在window上添加监听器
  2. 限制监听error event
  3. 传入处理函数,过滤错误(e.error不为空一般都是JS错误,为空可能是别的错误)

unhandledrejection监听

  1. 在window上添加监听器
  2. 限制监听unhandledrejection监听
  3. 传入处理函数

封装monitor

和上一小节类似

静态资源错误监控

原理

静态资源错误也是error event,用监听器处理

监听

  1. 在window上添加监听器

  2. 限制监听error event

  3. 传入处理函数,过滤错误(e.targete.srcElement不为空的,是静态资源错误)

  4. 进一步筛选,用instanceof进行区分

    • 如HTMLElement就是link和script
    • 要继续细分,可以用target.tagName取出标签名进行判断
  5. 监听器第二个参数置为true

请求异常监控

原理

XHR和fetch函数,通过回调处理错误

XHR错误监听

  1. 写一个简易钩子函数,三个参数:对象、对象属性、自己的逻辑
  2. 返回一个函数,接收属性及参数
  3. 写要hook的方法:将自己的方法挂载到XHR的方法上
  4. 在open方法的钩子上,监听open的参数,然后恢复open执行
  5. 在send方法的钩子上,监听readystatechange,如果状态码status大于等于400就读取,当然也不能干扰原有函数的执行

封装通用SDK

  • SDK主要执行“数据采集”、“组装上报”
  • 服务主要执行“清洗存储”、“数据消费”

实现sdk

  1. 创建函数作为入口,传入参数是上传url
  2. 使用一个数组存储所有的monitor函数
  3. 创建sdk对象,存储sdk自己的属性
  4. 实现report函数,使用navigator.sendBeacon即可
  5. 创建加载monitor的函数,将小的monitor加入数组,返回sdk可以支持链式调用风格
  6. 创建启动monitor的函数,对数组中的所有元素全部传入

让sdk更健壮

  • 监听慢请求
  • 给hook函数增加unhook能力
  • 用户行为监控