前端监控笔记(三)

消息上报机制

常见方案

  • sendBeacon :常用于页面卸载阶段上报,接口简单,不阻塞页面卸载流程;通常存在单次请求体大小限制(常见约 64KB,不同浏览器可能有差异)。
  • fetch keepalive :写法更灵活,可自定义方法、请求头与内容类型;同样受卸载场景下请求体大小限制(常见约 64KB)。

发送时机

在 visibilitychange 事件中,当 document.visibilityState === 'hidden' 时触发上报。

  • 触发时机早于 beforeunload,标签页切后台、最小化、息屏等场景也能触发。
  • beforeunload 可能不会触发,visiblituchange 移动端可能存在兼容问题,beforeunload 可作为兼容兜底实现。
typescript 复制代码
window.addEventListener('visibilitychange', () => {
  if (document.visibilityState !== 'hidden') return;

  const payload = JSON.stringify(pendingEvents);

  // 优先使用 sendBeacon,避免页面卸载时请求被中断。
  const ok = navigator.sendBeacon('/collect', payload);
  if (ok) return;

  // sendBeacon 失败时降级为 keepalive fetch。
  fetch('/collect', {
    method: 'POST',
    keepalive: true, // 允许页面卸载时继续发送请求
    headers: { 'Content-Type': 'application/json' },
    body: payload
  }).catch(() => {
    // 失败后重传,离线缓存处理
  });
});

fetchLater

注册延迟请求,在浏览器在页面离开或 activateAfter 到时后触发发送理解成 fetch + activeAfter 构成的延迟版本)

解决 sendBeacon 和 fetch keepalive 发送时机选择的问题,由浏览器排队处理

但同样有请求体大小限制,兼容性较差。

typescript 复制代码
try {
  fetchLater('/collect', {
    method: 'POST',
    body: JSON.stringify(pendingEvents),
    activateAfter: 60_000 // 最晚约 60s 后触发发送(实际时机由浏览器决定,不指定可能是页面关闭时发送)
  });
} catch (error) {
  // 配额超限或浏览器不支持时,降级 sendBeacon / fetch keepalive
}

指数退避重传

服务端返回 429 Too Many Requests(可结合 Retry-After 响应头)或其他异常时,使用指数退避进行重试。

text 复制代码
delay = baseDelay * 2^attempt * (1 + random(0, 0.5)) // 加入随机抖动

批量合并

上传时,可以通过定时器/maxBatch 批量合并日志消息,在单个请求上传处理

离线缓存

当用户离线或临时网络抖动时,可使用 IndexedDB / 内存维护缓冲队列,待网络恢复后重传。

  1. offline 事件监听到用户网络离线 ,将数据存入缓冲队列
  2. 监听 online 事件,将数据取出并重新执行
typescript 复制代码
// 简化 indexedDB 离线队列
// 如果是内存缓存队列,可以直接在监听 offline 时暂停队列批量发送,同时把发送数据重新推入缓冲队列
class OfflineQueue {
  #dbName = 'sdk-queue'

  async enqueue(event) {
    const db = await this.#openDB()
    await db.add('events', { ...event, timestamp: Date.now() })
  }

  async flush() {
    if (!navigator.onLine) return
    const db = await this.#openDB()
    const events = await db.getAll('events')
    for (const event of events) {
      const ok = await this.#send(event)
      if (ok) await db.delete('events', event.id)
    }
  }
    
  //...
}

// 监听网络恢复,触发重传
window.addEventListener('online', () => queue.flush())

采样发送

原理:通过条件概率减少发送日志,降低存储和请求开销

  • 给定概率值,每次执行发送的时候 random 得到一个随机值
  • 如果随机值在采样概率之内,就将数据发送到后台否则不发送

采样类型:

  • 固定采样:全局固定采样率,永远不变。
  • 确定性采样:通过固定 id 值,比如 userId 取 hash值,然后计算出同个用户/会话的采样率。
  • 动态采样:根据业务接口、用户身份、告警等级等业务规则实现采样,即针对业务进行不同频段的采样。
typescript 复制代码
// 固定采样值
function normalSample(rate: number) {
  return Math.random() < rate;
}

// 确定性采样示例:hash id, 采样值保持不变
function deterministicSample(id: string, rate: number) {
  const hash = simpleHash(id);
  return (hash % 10000) / 10000 < rate;
}
function simpleHash(input: string) {
  let hash = 0;
  for (let i = 0; i < input.length; i += 1) {
    hash = (hash * 31 + input.charCodeAt(i)) >>> 0;
  }
  return hash;
}



// 动态采样:根据业务、接口、以及下发采样配置实现采样
function dynamicSample(context: { url: string; isVip?: boolean }) {
  if (context.url.includes('/checkout')) return 1.0;
  if (context.isVip) return 0.5;
  return 0.1;
}
function dynamicSend(context: { url: string; isVip?: boolean }) {
  const rate = dynamicSample(context);
  return Math.random() < rate;
}

去重机制

通过为每个消息日志,错误信息生成独立指纹进行去重处理,减少重复推送,节省请求成本

消息事件去重:

可组合以下字段生成指纹:

  • 消息类型。
  • 业务指纹(模块、接口、页面标识)。
  • 堆栈摘要(new Error().stack 归一化后摘要)。

异常类型去重:

  1. 判断异常类型和异常值,异常类型是 error 、uncaughtrejection 这种独立类型,值是错误信息
  2. 比较指纹是否一致
  3. 比较堆栈跟踪信息是否一致

总结

  • 发送策略 :优先 visibilitychange + sendBeacon,失败时降级 fetch keepalive,fetchLater 作为尝鲜使用。
  • 数据可靠处理:通过限流重试、采样、去重减少无效上报,离线队列保障弱网场景下的数据补偿。

参考内容

相关推荐
葡萄城技术团队4 小时前
1000 人协同压测的环境瓶颈排查:CPU 争用与 Wi\-Fi
前端
excel5 小时前
Marked 与 Markdown 有什么区别?该怎么选?
前端
Da Da 泓6 小时前
五子棋 Web 端测试用例报告
前端·网络·websocket·网络协议·测试用例·项目
zxcvb1537 小时前
远程查看本地文档:一条轻量 Web 文件服务的工程化链路
前端·远程查看文档
一木 之林7 小时前
Dify学习笔记 03 · RAG检索增强生成:三代范式、评估与落地(第40-45、55-56集)
笔记·小程序·交互·dify
niucloud-admin7 小时前
NIUCLOUD PHP SAAS上门家政使用文档:城市管理
java·前端·php
北岛贰7 小时前
啵啵音乐迎来全新升级!
前端
apple-mapping7 小时前
网络RTK定位学习总结
学习·网络rtk
楚山之石8 小时前
【Lancet Neurology 】多发性硬化认知障碍的 SDMT 筛查、灰质萎缩标志与认知康复循证路径
图像处理·人工智能·学习·mri
hkNaruto9 小时前
【AI】基于大模型的AI游戏地图生成、控制方案:AI Native Game Harness 迁移操作手册
前端·人工智能·游戏