好好学习,认真工作

监控数据上报异常排查

上报数据方式

1、利用图片不受跨域限制,使用图片的src赋值上报

2、使用ajax上报数据

3、使用sendBeacon上传数据

查阅优劣分析之后:https://blog.csdn.net/a460550542/article/details/127709806

团队采用sendBeacon上报

背景

活动模板每个商品的发出一次询价请求,在运维nginx的数据和前端上报的数据不一致,nginx出现多出一倍的数据,

现网表现为

 

数据量为 308k,远远超过了chrome限制的64k,

解决方式1

对大数据量做切割,每次切30k的数据,代码思路如下

 1 const report = {
 2     ...
 3     spiltData(dataList, limit = 64) {
 4         const sizeArr = dataList.map(v => report.getStringSizeInKB(JSON.stringify(v)));
 5         let prevTotal = 0,
 6             sliceArr = [],
 7             currentArr = [];
 8         sizeArr.forEach((v, i) => {
 9             const currentTotal = prevTotal + v;
10             const currentData = dataList[i];
11             if (v > limit) {
12                 sliceArr.push(currentData)
13                 return
14             }
15             if (prevTotal < limit && currentTotal >= limit) {
16                 sliceArr.push(currentArr.splice(0))
17                 currentArr = [currentData]
18                 prevTotal = v
19             } else {
20                 prevTotal = currentTotal;
21                 currentArr.push(currentData)
22             }
23         })
24         sliceArr.push(currentArr.splice(0))
25         return sliceArr
26     },
27     getStringSizeInKB(str) {
28         var utf8Length = encodeURI(str).split(/%..|./).length - 1;
29         var size = utf8Length / 1024;
30         return parseFloat(size.toFixed(2));
31     },
32 }

由于navigator.sendBeacon并没上报回调,因此采用setTimeout调度请求,每隔500ms发一次数据,代码实现思路如下

 1 const report = {
 2     ...
 3     sendBeacon(url, data) {
 4         if (navigator.sendBeacon) {
 5             // 解决sendBeacon64k限制
 6             const dataList = this.spiltData(data.data, 20);
 7             this.excuteSend(url, dataList)
 8         } else {
 9             this.ajaxPost(url, data)
10         }
11     },
12     peddingDataList: [],
13     excuteSend(url, dataList) {
14         let timeout = null,
15             result = true,
16             errorTimes = 0;
17         report.peddingDataList = [
18             ...report.peddingDataList,
19             ...dataList
20         ];
21 
22         function checkSend() {
23             if (result || errorTimes > 2) {
24                 const dataList = report.peddingDataList.splice(0, 1)[0]
25                 result = navigator.sendBeacon(url, JSON.stringify({
26                     data: [...dataList]
27                 }));
28                 errorTimes = 0;
29             } else {
30                 errorTimes++
31             }
32             timeout = setTimeout(() => {
33                 if (report.peddingDataList.length > 0) {
34                     checkSend();
35                 } else {
36                     clearTimeout(report.timeout)
37                 }
38             }, 1000)
39         }
40         checkSend();
41     },
42 }

部署之后表现并不佳,发现数据依然有很多没完成上报

 

解决方式2

将较大数据量的上报数据使用ajax上报,小的数据则使用navigator.sendBeacon,

考虑到数据可能会太大,分析之后大数据量主要是页面ajax请求相关的数据,在ajax请求模块,在数据量超过60条之后则立刻执行上报,思路如下

 1 function logEntries(entries = []) {
 2   const xhrEntries = entries.filter(i => i.initiatorType === 'xmlhttprequest');
 3   cgiList.forEach((item) => {
 4     if (!item.url) {
 5       return
 6     }
 7     const entry = xhrEntries.find(i => i.name.includes(item.url));
 8     if (!entry) return;
 9     item.runSide = 'client';
10   });
11   if (cgiList.length > 60) {
12     reportCgi()
13   } else {
14     utils.throttle(reportCgi, this, 500);   
15   }
16 }

根据数据分析,在20条数据时候,上报数据约为20K,在粗略分析之后,阈值设置为20条,当数据超过20条之后,则使用ajax上报,否则使用navigator.sendBeacon

实现思路如下

 1 const report = {
 2     ...
 3     sendBeacon(url, data) {
 4         // 解决sendBeacon64k限制,
 5         // 数据量大约1个1K,大于20个则使用ajax,避免sendBeacon失败
 6         this.wafData(data)
 7         if (navigator.sendBeacon && data.data.length < 20) {
 8             navigator.sendBeacon(url, JSON.stringify(data));
 9         } else {
10             this.ajaxPost(url, data)
11         }
12     },
13     ajaxPost(url, data, cb) {
14         const xhr = new XMLHttpRequest();
15         const jsonData = JSON.stringify(data);
16         xhr.onreadystatechange = function() {
17             if (xhr.readyState === 4 && xhr.status === 200) {
18                 const res = JSON.parse(xhr.responseText)
19                 cb && cb(res)
20             }
21         }
22         xhr.open('POST', url);
23         xhr.setRequestHeader("Content-Type", "application/json");
24         xhr.send(jsonData);
25     },
26 }

部署之后表现如下

能够正常上报 

 

posted on 2024-06-25 20:55  peace_1  阅读(1)  评论(0编辑  收藏  举报