前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【前端监控】日志池

【前端监控】日志池

作者头像
神仙朱
发布2021-09-09 15:03:00
6530
发布2021-09-09 15:03:00
举报

前端监控系列,SDK,服务、存储 ,会全部总结一遍,写文不易,点个赞吧

前端监控上报数据的时候,是怎么发请求的呢,是每产生一条监控数据就上报一次吗

当然不是了,如果监控点很多,那估计请求都快发爆炸了,请求发得多,不仅会加重服务器压力,数据丢失的概率也大,毕竟10条请求的成功率肯定比 一条请求 的成功率小嘛

所以才会出现日志池,这篇内容不属于前端监控的一部分,属于是其中的一个优化点

不多说了,开始正文

本文其实挺简单的,分为三个部分

1、基本思路

2、具体逻辑

3、代码Demo仓库

基本思路

最简单的说法就是

每次上报数据的时候,不会立即发送,把数据存到一个数组里面

然后设置 setTimeout,定时从数组里面取固定数量的日志(比如20条数据),然后再进行上报

简单画个图,如下

在这个基础上再进行优化

1、错误重试。上报请求发生错误的时候,会进行重试,以免日志就这么丢失,这里在离线日志中有过相关处理

2、页面关闭发送剩余日志。因为我们使用定时发送的方式,可能会存在用户关闭界面的时候,还有缓存的日志没有发送。

所以需要在最后一刻发送一波

下面就来详细说下具体的处理逻辑

具体逻辑

看了上面基本就知道这里就有三个步骤

1、定时发送

2、错误重试

3、监听页面关闭发送日志

1定时发送

1、把所有日志数据都会先缓存到一个数组中,调用上报方法的时候,直接 push 进去

代码语言:javascript
复制
const LOG_CACHE = []
function report(data){
    LOG_CACHE.push(data)
}

2、初始化的时候会设置一个循环定时器,从 日志数组中,取一定数量的数据 进行上报

代码语言:javascript
复制
let timer = null;
const duration = 500;
const limit = 20;
let LOG_CACHE = [];

function init() {
  loop();
}

function loop() {
  timer = setTimeout(() => {
    timer = null;
    LOG_CACHE.length && send();
    loop();
  }, duration);
}

function send() {
  const logs = LOG_CACHE.splice(0, limit);
  if (!logs.length) return;
  fetch("www.test.com/report", {
    body: JSON.stringify(logs),
  });
}

这个 定时器时间单次上报的数量 可以自己定义

时间不能太长,导致积压的数据过多,丢失风险大

数量不能太大,不然请求体太大,响应时间长,丢失的成本大

我们这里设置的是,500ms 单次发送20条数据

2错误重试

当上报请求发生错误的时候,有两种选择

1、直接重试

2、缓存等待重试

直接重试

如果是偶尔的错误,可以直接重试,但是如果是频繁报错,可能是接口服务或者用户网络的问题

所以仍然直接重试没有什么意义

直接重试条件是,如果3s内发生错误没有超过3次,那么就直接重试。

每次报错叠加一次failCount,并且重设定时器,定时器会把错误次数置为0。

重试的做法是,把上报的数据,重新 push 进 数组

缓存等待重试

定时器内超过3次的,会存入本地。

缓存进本地的日志,什么时候会重试?

1、页面初始化时,读取本地数据,push 进数组

2、每次存本地时,会开启一个定时器,从本地读取数据,push 进数组

所以缓存进本地,是为了把数据延迟更久上报,同时保证数据不丢失

看下大概的实现代码

其中操作 indexdb 的代码是我简化写的,实际不是这么操作

更详细的关于存日志到 indexdb 的部分在 离线日志

代码语言:javascript
复制
let failCount = 0; // 上报错误次数

function send() {
  const logs = LOG_CACHE.splice(0, limit);
  if (!logs.length) return;
  fetch("www.test.com/report", {
    body: JSON.stringify(logs),
  }).catch((e) => {
    handlerReportError();
    if (failCount < 3) {
      LOG_CACHE.push(...logs); // 伪代码
    } else {
      saveLogs(logs)
    }
  });
}

let failTimer = 0; // 错误定时器
function handlerReportError() {
  failCount++;
  //  发生错误就重置定时器
  clearTimeout(failTimer);
  failTimer = setTimeout(() => {
    failTimer = null;
    failCount = 0;
  }, 3000);
}

let readTimer = null; // 读取本地数据库定时器
function saveLogs(data) {
  indexDBStore.add("fail_log", data);
  if (!readTimer) return;
  readTimer = setTimeout(() => {
    const logs = indexDBStore.get("fail_log");
    LOG_CACHE.push(...logs); // 伪代码
  }, 3000);
}

3监听页面关闭发送日志

因为定时发送请求的原因,可能存在用户关闭页面,仍然有部分日志没有发送,所以需要监听页面关闭,把剩余日志发送一下

具体处理就是

1、监听页面关闭事件

2、使用 navigator.sendBeacon 发送请求

关于这部分存在的兼容性,我写在另一篇文章了,请看【兼容性】监听页面关闭发送请求

具体代码如下

四个事件都是为了监听页面关闭,但是各端支持程度不一样,所以全部监听,谁生效就用谁

使用一个标志位,只要有事件触发过了,其他事件就不用了

代码语言:javascript
复制
window.addEventListener("beforeunload", sendRemainLogs);
window.addEventListener("pagehide", sendRemainLogs);
window.addEventListener("unload", sendRemainLogs);

// IOS14 之前不会冒泡,只能监听document
document.addEventListener("visibilitychange ", () => {
  if (document.visibilityState !== "visible") {
    sendRemainLogs();
  } else {
    // 如果界面又显示了,说明没有关闭,重置标志位
    sendRemainLogsSuccess = false;
  }
});

let sendRemainLogsSuccess = false;

function sendRemainLogs(data) {
  if (sendRemainLogsSuccess) return;   

  if (!navigator.sendBeacon) {
    indexdbStore.add("fail_logs", data);
    return;
  }

  const logs = LOG_CACHE;
  const result = navigator.sendBeacon(
    "www.test.com/report",
    JSON.stringify(logs)
  );
  if (!result) {
    indexdbStore.add("fail_logs", data);
  }
}

现在所有的处理都说完了

现在来看下这个日志池的流程图

代码demo错误

把大概的实现写了一个demo,可以参考下,相对于上面出现的代码片段,做了一些封装和错误判断,是一个可以走通整个逻辑的

https://gitee.com/hoholove/study-code-snippet/blob/master/LOGGER/pool.js

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-09-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 神仙朱 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
前端性能监控
前端性能监控(Real User Monitoring,RUM)是一站式前端监控解决方案,专注于 Web、小程序等场景监控。前端性能监控聚焦用户页面性能(页面测速,接口测速,CDN 测速等)和质量(JS 错误,Ajax 错误等),并且联动腾讯云应用性能监控实现前后端一体化监控。用户只需要安装 SDK 到自己的项目中,通过简单配置化,即可实现对用户页面质量的全方位守护,真正做到低成本使用和无侵入监控。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档