监控系统数据上报 | 青训营笔记

135 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的第2天

项目简介

这次参加字节青训营,大项目选择的是前端监控系统。前端监控系统可以自动收集、上报、存储Web页面关键数据。今天这篇文章主要是配置上报方法。

上报方法

navigator.sendBeacon()  方法可用于通过HTTP POST将少量数据 异步传输到 Web 服务器。

  • 语法
navigator.sendBeacon(url, data);
  • 参数

url 参数表明 data 将要被发送到的网络地址。

data 参数是将要发送的 ArrayBufferArrayBufferViewBlobDOMStringFormData 或 URLSearchParams 类型的数据。

上报时机

网站通常希望在用户完成页面浏览后向服务器发送分析或诊断数据,最可靠的方法是在 visibilitychange 事件发生时发送数据:

document.addEventListener('visibilitychange', function logData() {
  if (document.visibilityState === 'hidden') {
    navigator.sendBeacon('/report', data);
  }
});
  • 避免使用 unloadbeforeunload

过去,许多网站使用 unload 或 beforeunload 事件以在会话结束时发送统计数据。然而这是不可靠的,在许多情况下(尤其是移动设备)浏览器不会产生 unloadbeforeunload 或 pagehide 事件。下面列出了一种不触发上述事件的情况:

  1. 用户加载了网页并与其交互。
  2. 完成浏览后,用户切换到了其它应用程序,而不是关闭选项卡。
  3. 随后,用户通过手机的应用管理器关闭了浏览器应用。

上报格式

sendBeacon支持的参数类型里面不包含json格式,这意味着我们要使用其他的类型进行数据上报。

在这里则需要保证 Content-Type 为以下三种之一:

  • application/x-www-form-urlencoded

如果用 Blob 发送数据,这时需要我们手动设置 Blob 的 type,一般设置为 application/x-www-form-urlencoded

const reportData = (url, data) => {
  const blob = new Blob([JSON.stringify(data), {
    type: 'application/x-www-form-urlencoded',
  }]);
  navigator.sendBeacon(url, blob);
};
  • text/plain

如果数据类型是 string,则可以直接上报,此时该请求会自动设置请求头的 Content-Typetext/plain

const reportData = (url, data) => {
  navigator.sendBeacon(url, data);
};
  • multipart/form-data

可以直接创建一个新的 Formdata,此时该请求会自动设置请求头的 Content-Typemultipart/form-data

const reportData = (url, data) => {
  const formData = new FormData();
  Object.keys(data).forEach((key) => {
    let value = data[key];
    if (typeof value !== 'string') {
      // formData只能append string 或 Blob
      value = JSON.stringify(value);
    }
    formData.append(key, value);
  });
  navigator.sendBeacon(url, formData);
};

由于我们需要上传的类型,有数组、对象,所以我们使用text/plain,通过JSON.stringify操作,把所有数据转换成文本类型,交给后端进行处理。