【前端监控系统】埋点数据上报的3种方式

前言

首先,我们先对前端监控做一些简单的描述:

前端监控的目的?

  1. 提升用户体验
  2. 更快的发现发现异常、定位异常、解决异常
  3. 了解业务数据,指导产品升级——数据驱动的思想
    它指的是通过一定的手段来获取用户行为以及跟踪产品在用户端的使用情况,并以监控数据为基础,为产品优化指明方向,为用户提供更加精确、完善的服务。

前端监控的方向?

一般来说,前端监控无非就是从以下三个角度进行监控:

  • 数据监控(监控用户行为)
  • 性能监控(监控网页性能)
  • 异常监控(监控代码异常)

前端监控的流程?

采集数据>>上报数据>>分析数据>>报警通知

很显然,前端监控首要的步骤就是前端埋点和数据上报,也就是数据的收集阶段,而数据收集的丰富性和准确性会影响对产品线上效果的判别结果。

那么,下文主要给大家讲下第一步数据收集阶段-埋点数据上报的相关知识。

埋点上报

埋点,它的学名是事件追踪(Event Tracking),主要是针对特定用户行为或业务过程进行捕获、处理和发送的相关技术及实施过程。埋点是数据领域的一个专业术语,也是互联网领域的一个俗称。埋点是产品数据分析的基础,一般用于推荐系统的反馈、用户行为的监控和分析、新功能或者运营活动效果的统计分析等。埋点包含两个重要概念:事件(event),属性(param)。

埋点主流方案包括无痕埋点(全埋点),代码埋点,可视化埋点。这里就不做过多赘述了,可以自行百度。
传送门

上报数据的三种方法

1. 直接发请求上报

我们可以直接将数据通过 ajax 发送到后端,以 axios 为例。

axios.post(url, data);

问题:
但这种方法有一个问题,就是在页面卸载或刷新时进行上报的话,请求可能会在浏览器关闭或重新加载前还未发送至服务端就被浏览器 cancel 掉,导致数据上报失败。

我们可以将 ajax 请求改为同步方法,这样就能保证请求一定能发送到服务端。由于 fetchaxios 都不支持同步请求,所以需要通过 XMLHttpRequest 发送同步请求。

示例:

const syncReport = (url, { data = {}, headers = {} } = {}) => {
  const xhr = new XMLHttpRequest();
  xhr.open('POST', url, false);
  xhr.withCredentials = true;
  Object.keys(headers).forEach((key) => {
    xhr.setRequestHeader(key, headers[key]);
  });
  xhr.send(JSON.stringify(data));
};

2. 利用图片上报

第二种方式就是利用图片的src属性发送请求进行数据上报,因为大部分浏览器会延迟卸载(unload)文档以加载图像(只是大多数浏览器,还是存在兼容性的),所以用图片上报就可以解决第一种方法的漏洞。

用图片上报还有以下优点:

  1. 图片请求方式不会出现跨域问题,因为打点域名经常不是当前域名;
  2. 防止阻塞页面加载,影响用户体验;
  3. 一般采用1*1像素的透明 gif 进行上报,因为gif图片格式体积小(最小的BMP文件需要74个字节,PNG需要67个字节,而合法的GIF,只需要43个字节)

示例:

new Image().src = 'https://example.com/aaa?name=hester&num='+Math.random() 

3. sendBeacon

同样为了解决页面卸载时,数据不能完成上报等问题,web底层新增了sendBeacon方法。MDN说明

这个方法主要用于满足统计和诊断代码的需要,这些代码通常尝试在卸载(unload)文档之前向 Web 服务器发送数据。过早的发送数据可能导致错过收集数据的机会。然而,对于开发者来说保证在文档卸载期间发送数据一直是一个困难。

使用 sendBeacon() 方法会使用户代理(浏览器)在有机会时异步地向服务器发送数据,同时不会延迟页面的卸载或影响下一导航的载入性能,这意味着:

  1. 数据发送是可靠的。
  2. 数据异步传输。
  3. 不影响下一个页面的载入。

示例:

navigator.sendBeacon(url, data);

常用的埋点上报处理方式

为了防止因sendBeacon兼容性导致的上报错误问题,可以优先使用sendBeacon的方式,Image方式作为fallback。

function sendLog(url: string, params: object) {
    if(navigator.sendBeacon) {
        sendBeacon(url, params)
    } else {
        sendImage(url, params)
    }

我是阿彬,期待你的关注!

猜你喜欢

转载自blog.csdn.net/qq_38974163/article/details/128448094
今日推荐