背景

近期主要工作内容是进校开放平台(简称开平)相关业务,开平简单来说就是一个可为第三方应用提供接入主端(例如微信、飞书)应用能力的平台,为了让第三方应用稳定可靠地接入开平,需要为其提供一些底层的基础能力,其中应用监控就是其中不可或缺的一环。目前如何在进校开平中做三方应用的监控管理还在初步预研阶段,为此了解了一下前端监控相关背景知识。鉴于我司已有一套非常完善的 APM 平台,因此下文诸多理论和源码参考自我司 APM Web SDK 源码。

监控流程


  1. 数据采集:明确需要采集哪些指标以及采集的方式。

  1. 数据上报:将上一步采集的数据以一定的策略进行上报。

  1. 数据清洗、存储:服务端在接收到上报数据后需要对数据进行清洗和存储。

  1. 数据消费:数据最终会在类似 Slardar Web 这样的监控平台以图、表等形式分类别地进行可视化展示,并提供诸如监控报警等消费能力。

上述流程看似不复杂但每个环节的技术细节都非常多,本文主要关注前端视角下的数据采集和上报环节。

数据采集

做好前端监控的第一步要明确哪些数据是值得我们采集的,前端环境下监控数据从大的维度上可划分成环境信息、异常数据和性能数据:


环境信息

采集的监控数据一般都会设置一些通用的环境信息,这些环境信息可以提供更多的维度以帮助用户发现问题和解决问题。下图列举了一些常见的环境信息:


异常监控

JS 异常

Script Error

先抛开如何采集 JS 异常信息不谈,在采集之前如果连报错信息都不全那么即使采集到了这样的数据也是无效的。巧的是,确实存在这样一个场景:当页面加载自不同域的脚本(例如页面的 JS 托管在 CDN)中发生语法错误时,浏览器基于安全机制考虑,不会给出语法错误的细节,而是简单的 Script error.

因此,如果你希望自己页面的详细报错信息被监控 SDK 捕获你需要为页面中的脚本 script 添加 crossorigin= anonymous 属性,且脚本所在的服务设置 CORS 响应头 Access-Control-Allow-Origin: * ,这是 JS 异常监控的第一项准备工作。

编译时与运行时错误

常见的 JS 错误可分为编译时错误和运行时错误,其中编译时错误在 IDE 层面就会给出提示,一般不会流入到线上,因此编译时错误不在监控范围。

有的同学说在 Slardar 上时常看到 SyntaxError 的字样,这种情况一般都是 JSON.parse 解析出错或浏览器兼容性问题导致,属于运行时错误并非编译时错误。

对于异常监控我们主要关注 JS 运行时错误,多数场景下的处理手段如下:

错误场景 如何上报
场景一:自行感知的同步运行时异常 try-catch 后进行错误上报
场景二:没有手动 catch 的运行时异常(包括异步但不包括 promise 异常 通过 window.onerror进行监听
场景三:自行感知的 promise 异常 promise catch 进行捕获后进行错误上报
场景四:没有手动 catch 的 promise 异常 监听 window 对象的 unhandledrejection 事件

整体来看,监控 SDK 会在全局帮助用户去捕获他们没有自行感知的异常并上报,对于自行捕获的异常一般会提供手动上报接口进行上报。

SourceMap

假设现在已经采集到页面目前存在的 JS 异常并做了上报,最终消费时你我们当然希望看到的是错误的初始来源和调用堆栈,但实际发生报错的 JS 代码都经过各种转换混淆压缩,早已面目全非了,因此这里需要借助打包阶段生成的 SourceMap 做一个反向解析得到原始报错信息的上下文。

以 Sentry (Slardar 也有用到 Sentry)为例大致流程如下:

  1. 采集侧收集错误信息发送到监控平台服务端。

  1. 接入的业务方自行上传 SourceMap 文件到监控平台服务端,上传完成后删除本地的 SourceMap文件,且打包后的 js 文件末尾不需要 SourceMap URL,最大程度避免 SourceMap 泄漏。

  1. 服务端通过 source-map 工具结合 SourceMap 和原始错误信息定位到源码具体位置。

静态资源加载异常

静态资源加载异常的捕获存在两种方式:

  1. 在出现静态资源加载异常的元素的 onerror 方法中处理。

  1. 资源加载异常触发的error事件不会冒泡,因此使window.addEventListener('error', cb, true) 在事件捕获阶段进行捕获。

第一种方式侵入性太强,不够优雅,目前主流方案均采用第二种方式进行监控:

捕获静态资源加载异常

APM 平台一般会有所有静态资源加载的明细,其原理是通过 PerformanceResourceTiming API 来采集静态资源加载的基本情况,这里不做展开。

请求异常

业务中的 AJAX 请求或者 Fetch 请求在不同的网络环境或者客户端环境会有不稳定的表现,这些不稳定的情况我们很难通过本地测试的途径进行测试或者感知得到,所以我们需要对 HTTP 请求进行线上监控,通过将 HTTP 请求异常上报的方式对错误日志进行采集,然后进行一系列的分析和监控。

请求异常通常泛指 HTTP 请求失败或者 HTTP 请求返回的状态码非 20X。

那么请求异常监控怎么做呢?普遍采用的方式是对原生的 XMLHttpRequest 对象和 fetch 方法进行重写,从而在代理对象中实现状态码的监听和错误上报:

重写 XMLHttpRequest 对象

重写 fetch 方法

当然了,重写上述方法后除了异常请求可以被监控到之外,正常响应的请求状态自然也能被采集到,比如 Slardar 会将对所有上报请求的持续时间进行分析从而得出慢请求的占比:

PS:如果通过 XHR 或 fetch 来上报监控数据的话,上报请求也会被被拦截,可以有选择地做一层过滤处理。

卡顿异常

卡顿指的是显示器刷新时下一帧的画面还没有准备好,导致连续多次展示同样的画面,从而让用户感觉到页面不流畅,也就是所谓的掉帧,衡量一个页面是否卡顿的指标就是我们熟知的 FPS。

如何获取 FPS

Chrome DevTool 中有一栏 Rendering 中包含 FPS 指标,但目前浏览器标准中暂时没有提供相应 API ,只能手动实现。这里需要借助 requestAnimationFrame 方法模拟实现,浏览器会在下一次重绘之前执行 rAF 的回调,因此可以通过计算每秒内 rAF 的执行次数来计算当前页面的 FPS

通过 rAF 计算 FPS

如何上报“真实卡顿”

从技术角度看 FPS 低于 60 即视为卡顿,但在真实环境中用户很多行为都可能造成 FPS 的波动,并不能无脑地把 FPS 低于 60 以下的 case 全部上报,会造成非常多无效数据,因此需要结合实际的用户体验重新定义“真正的卡顿”,这里贴一下司内 APM 平台的上报策略

  1. 页面 FPS 持续低于预期:当前页面连续 3s FPS 低于 20。

  1. 用户操作带来的卡顿:当用户进行交互行为后,渲染新的一帧的时间超过 16ms + 100ms。

崩溃异常

Web 页面崩溃指在网页运行过程页面完全无响应的现象,通常有两种情况会造成页面崩溃:

  1. JS 主线程出现无限循环,触发浏览器的保护策略,结束当前页面的进程。

  1. 内存不足

发生崩溃时主线程被阻塞,因此对崩溃的监控只能在独立于 JS 主线程的 Worker 线程中进行,我们可以采用 Web Worker 心跳检测的方式来对主线程进行不断的探测,如果主线程崩溃,就不会有任何响应,那就可以在 Worker 线程中进行崩溃异常的上报。这里继续贴一下 Slardar 的检测策略:

  • JS 主线程:

    • 固定时间间隔(2s)向 Web Worker 发送心跳

  • Web Worker:

    • 定期(2s)检查是否收到心跳。

    • 超过一定时间(6s)未收到心跳,则认为页面崩溃。

    • 检测到崩溃后,通过 http 请求进行异常上报。

崩溃检测

性能监控

性能监控并不只是简单的监控“页面速度有多快”,需要从用户体验的角度全面衡量性能指标。(就是所谓的 RUM 指标)目前业界主流标准是 Google 最新定义的 Core Web Vitals:

  • 加载(loading)LCP

  • 交互(interactivity)FID

  • 视觉稳定(visual stability)CLS

可以看到最新标准中,以往熟知的 FP、FCP、FMP、TTI 等指标都被移除了,个人认为这些指标还是具备一定的参考价值,因此下文还是会将这些指标进行相关介绍。(谷歌的话不听不听

【Web技术】1274- 深入浅出前端监控相关推荐

  1. 【Web技术】1444- 中高级前端工程师都需要熟悉的前端缓存知识

    前言 web缓存是高级前端工程师必修技能.是我们变成大牛过程中绕不开的知识点. 文章会尽量用通俗易懂的言语来细说web缓存的概念和用处. 本期文章的大纲是 什么是web缓存(前端缓存) 缓存可以解决什 ...

  2. 饿了么ui组件中分页获取当前选中的页码值_【Web技术】314 前端组件设计原则

    点击上方"前端自习课"关注,学习起来~ 译者:@没有好名字了译文:https://github.com/lightningminers/article/issues/36,http ...

  3. 【Web技术】1189- 你不知道的前端音视频知识

    Web 音视频的发展史 刀耕火种的年代--早期 HTML 在早期的 HTML,由于带宽.技术等各种因素限制,网页主要以简单的静态内容为主,只支持一些文字图片内容和简单的排版,不支持在线观看音视频. ( ...

  4. 【Web技术】1161- 你不知道的前端音视频知识

    Web 音视频的发展史 刀耕火种的年代--早期 HTML 在早期的 HTML,由于带宽.技术等各种因素限制,网页主要以简单的静态内容为主,只支持一些文字图片内容和简单的排版,不支持在线观看音视频. ( ...

  5. 【Web技术】1431- 总结前端主题切换的思考和现代前端样式的解决方案落地

    关于本文 来自:codercao https://juejin.cn/post/7106702604024938503 demo在线体验地址:https://hongqingcao.github.io ...

  6. 【Web技术】948- 生成前端海报的 N 种方案和优劣

    一.背景 工作中做了很多生成海报的功能,不同需求,不同场景,使用了几种方案,各有优劣.一直想要整理一下,但这个过程中的思考和遇到的问题没有记录下来,比如图片的跨域问题,文字的问题,做完没有记录,无迹可 ...

  7. 【Web技术】1106- 浅析前端异常及降级处理

    一.导读 "异常"一词出自<后汉书.卷一.皇后纪上.光烈阴皇后纪>,表示非正常的,不同于平常的.在我们现实生活中同样处处存在着异常,比如小县城里的路灯年久失修...,上 ...

  8. 【Web技术】剖析前端异常及降级处理

    一.导读 "异常"一词出自<后汉书.卷一.皇后纪上.光烈阴皇后纪>,表示非正常的,不同于平常的.在我们现实生活中同样处处存在着异常,比如小县城里的路灯年久失修...,上 ...

  9. 【Web技术】943- 对前端路由的一些理解

    来自:掘金,作者:尼克陈 链接:https://juejin.cn/post/6917523941435113486 一篇文章,不可能做的面面俱到,全部受众.希望大家带着发散思维去看文章,将文章涉及的 ...

最新文章

  1. senfile函数实例的运行过程截图
  2. 刘强东宣布: 未来京东将减员50%,每天工作3小时!无人公司来了……
  3. 太原理工软件学院c语言2020,太原理工软件工程C语言实验报告 数组.doc
  4. 设计模式之控制反转和依赖注入的使用小结
  5. win10禁用驱动程序强制签名_图文细说 win10系统未检测到第三个监视器的途径 -win10使用教程...
  6. python基于dict、defaultdict、Counter的累加器
  7. iQOO Neo6双色官方图公布:云阶三摄 辨识度十足
  8. 即时通讯学习笔记003---Tigase代码框架解读
  9. WEB小知识学习集锦
  10. webstorm的下载以及React环境搭建
  11. PHP报错 Fatal error: Cannot use object of type stdClass as array
  12. Jmeter教程(图文版)
  13. php 回车符替换,php怎么替换回车符
  14. luogu P4315 月下“毛景树”
  15. 自然语言处理实战——巧用 Amazon Comprehend 分析社交媒体数据
  16. linux 之 Deamon进程
  17. qt——widget
  18. Linux-软件安装管理
  19. WSL 2 installation is incomplete.【BUG解决】【Docker之云原生基石】
  20. 小甲鱼课后作业_教学常规聚养料,润物无声花更艳 ——记长小教师一日教学常规点滴工作...

热门文章

  1. 唐太宗大喝一声:来人,给朕上云!
  2. ZooKeeper各个版本下载
  3. 基于ROS的qbo机器人
  4. 03基础自绘-18手机通讯录-telwidget
  5. 【C语言程序】编写登录函数,函数有两个形式函数:账号名和密码。如果账号名为“张三”,密码为“123”,则登陆成功,否则登录失败。
  6. 用CSS定义每段首行缩进2个字符
  7. 【小沐学Android】Android手机上基于Termux实现Web服务器(Python、node.js、C/C++)
  8. (热门)智慧社区助力实现社区数字化转型
  9. PaperFree-论文查重
  10. 腾讯QQ的验证码,很黄很暴力