实现前端监控,第一步确定是将咱们要监控的事项(数据)给收集起来,再提交给后台进行入库,最后再给数据分析组进行数据分析,最后处理好的数据再同步给运营或者是产品。
数据收集的丰富性和准确性会直接影响到咱们作前端监控的质量,由于咱们会以此为基础,为产品的将来发展指引方向。

如今常见的埋点上报方法有三种:

  • 手动埋点
  • 可视化埋点
  • 无埋点

手动埋点

手动埋点,也叫代码埋点,即纯手动写代码,调用埋点 SDK 的函数,在须要埋点的业务逻辑功能位置调用接口,上报埋点数据,像[友盟][百度统计]等第三方数据统计服务商大都采用这种方案。

手动埋点让使用者能够方便地设置自定义属性、自定义事件;因此当你须要深刻下钻,并精细化自定义分析时,比较适合使用手动埋点。

手动埋点的缺陷就是,项目工程量大,须要埋点的位置太多,并且须要产品开发运营之间相互反复沟通,容易出现手动差错,若是错误,从新埋点的成本也很高。

单纯在某个地方埋点而已,不必太纠结概念。

数据采集

本质其实就是用 JS 代码拿到一些基本信息,然后在特定的时机返回给服务端。

采集什么信息呢,比如下面这种

  1. const { domain, URL, title } = document
  2. const {
  3. availHeight, // 浏览器窗口在屏幕上可占用的垂直空间,即最大高度
  4. availWidth, // 返回浏览器窗口可占用的水平宽度
  5. availLeft, // 返回浏览器可用空间左边距离屏幕(系统桌面)左边界的距离
  6. availTop, // 浏览器窗口在屏幕上的可占用空间上边距离屏幕上边界的像素值
  7. width, // 返回屏幕的宽度
  8. height, // 返回屏幕的高度
  9. colorDepth, // 返回屏幕的颜色深度
  10. pixelDepth, // 返回屏幕的位深度/色彩深度
  11. orientation: { // 返回屏幕当前的方向,
  12. angle, // 角度
  13. onchange, // 方向改变时,触发的回调
  14. type // landscape-primary | landscape-secondary | portrait-secondary | portrait-primary
  15. }
  16. } = window.screen
  17. const { language, userAgent, deviceMemeory, hardwareConcurrency } = navigator
  1. const {
  2. navigation: {
  3. type, // 1 代表该页面刷新,0 代表页面是搜索加载来的
  4. redirectCount // 重定向次数
  5. },
  6. timeOrigin, // perfomance 开始记录性能的起始时间
  7. timing // 包含延迟相关的性能信息
  8. } = performance
  9. const {
  10. timing // 包含延迟相关的性能信息
  11. } = performance
  12. // dns 解析时间
  13. const dnsTime = timing.domainLookupEnd - timing.domainLookupStart
  14. // tcp 建立连接的时间
  15. const tcpTime = timing.connectEnd - timing.connectStart
  16. // 卸载页面的时间
  17. const unloadTime = timing.unloadEventEnd - timing.unloadEventStart
  18. // 【重要】解析 DOM 树结构的时间
  19. // 【反省】DOM 树嵌套是不是太多了
  20. const parserDOMTime = timing.domComplete - timing.domInteractive
  21. // 【重要】重定向的时间
  22. // 【反省】拒绝重定向!比如,http://example.com/ 不该写成 http:example.com
  23. const redirectTime = timing.redirectEnd - timing.redirectStart
  24. // 【重要】客户端发起 HTTP 请求到客户端拿到资源的时间
  25. // 【反省】可以理解为用户拿到你的资源过程中,占用的时间。加异地机房了么,加CDN 处理了么?加带宽了么?加 CPU 运算速度了么?
  26. // 维基百科:https://en.wikipedia.org/wiki/Time_To_First_Byte
  27. const timeToFirstByte = timing.responseStart - timing.fetchStart
  28. // 【重要】执行 onload 回调函数的时间
  29. // 【反省】是否执行太多不必要的操作了?考虑过延迟加载、按需加载的策略么?
  30. const onloadTime = timing.loadEventEnd - timing.loadEventStart

数据上报

在合适的时机,发送请求,可以使用 GET 一个 gif 对其进行上报,或者直接发送 XMLHTTPRequest。

为什么使用 1 x 1 的 gif?
1、没有跨域问题
2、发 GET 请求之后不需要获取和处理数据、服务器也不需要发送数据
3、不会携带当前域名 cookie!
4、不会阻塞页面加载,影响用户的体验,只需 new Image 对象
5、相比于 BMP/PNG 体积最小,可以节约 41% / 35% 的网络资源小

可视化埋点

经过可视化交互的手段,代替上述的代码埋点。将业务代码和埋点代码分离,提供一个可视化交互的页面,输入为业务代码,经过这个可视化系统,能够在业务代码中自定义的增长埋点事件等等,最后输出的代码耦合了业务代码和埋点代码。

可视化埋点的缺陷就是能够埋点的控件有限,不能手动定制。

无埋点

无埋点则是前端自动采集全部事件,上报埋点数据,由后端来过滤和计算出有用的数据。
优点是前端只要一次加载埋点脚本,缺点是流量和采集的数据过于庞大,服务器性能压力山大。

在合适的时机,发送请求,可以使用 GET 一个 gif 对其进行上报,或者直接发送 XMLHTTPRequest。

为什么使用 1 x 1 的 gif?
1、没有跨域问题
2、发 GET 请求之后不需要获取和处理数据、服务器也不需要发送数据
3、不会携带当前域名 cookie!
4、不会阻塞页面加载,影响用户的体验,只需 new Image 对象
5、相比于 BMP/PNG 体积最小,可以节约 41% / 35% 的网络资源小

参考资料

《为什么大厂前端监控都在用GIF做埋点?》