spy-client 2.1.1-alpha.4 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +9 -3
  2. package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/base.css +224 -0
  3. package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/basicSpec.ts.html +740 -0
  4. package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/block-navigation.js +79 -0
  5. package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/checkSpec.ts.html +479 -0
  6. package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/favicon.png +0 -0
  7. package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/headSpec.ts.html +695 -0
  8. package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/index.html +171 -0
  9. package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/markSpec.ts.html +284 -0
  10. package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/metricSpec.ts.html +977 -0
  11. package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/prettify.css +1 -0
  12. package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/prettify.js +2 -0
  13. package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/sort-arrow-sprite.png +0 -0
  14. package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/sorter.js +170 -0
  15. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/base.css +224 -0
  16. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/basicSpec.ts.html +740 -0
  17. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/block-navigation.js +79 -0
  18. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/checkSpec.ts.html +479 -0
  19. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/favicon.png +0 -0
  20. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/headSpec.ts.html +695 -0
  21. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/index.html +171 -0
  22. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/markSpec.ts.html +284 -0
  23. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/metricSpec.ts.html +977 -0
  24. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/prettify.css +1 -0
  25. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/prettify.js +2 -0
  26. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/sort-arrow-sprite.png +0 -0
  27. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/sorter.js +170 -0
  28. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/base.css +224 -0
  29. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/basicSpec.ts.html +740 -0
  30. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/block-navigation.js +79 -0
  31. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/checkSpec.ts.html +479 -0
  32. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/favicon.png +0 -0
  33. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/headSpec.ts.html +695 -0
  34. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/index.html +171 -0
  35. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/markSpec.ts.html +284 -0
  36. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/metricSpec.ts.html +977 -0
  37. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/prettify.css +1 -0
  38. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/prettify.js +2 -0
  39. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/sort-arrow-sprite.png +0 -0
  40. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/sorter.js +170 -0
  41. package/dist/head/base.d.ts +12 -7
  42. package/dist/lib/interface.d.ts +4 -0
  43. package/dist/spy-client-basic.d.ts +4 -1
  44. package/dist/spy-client-basic.esm.js +80 -21
  45. package/dist/spy-client-basic.iife.js +80 -21
  46. package/dist/spy-client-basic.iife.min.js +1 -1
  47. package/dist/spy-client-basic.js +80 -21
  48. package/dist/spy-client-basic.min.js +1 -1
  49. package/dist/spy-client-basic.mjs +80 -21
  50. package/dist/spy-client.d.ts +1 -0
  51. package/dist/spy-client.esm.js +107 -31
  52. package/dist/spy-client.iife.js +107 -31
  53. package/dist/spy-client.iife.min.js +1 -1
  54. package/dist/spy-client.js +107 -31
  55. package/dist/spy-client.min.js +1 -1
  56. package/dist/spy-client.mjs +107 -31
  57. package/dist/spy-head.js +46 -34
  58. package/dist/spy-head.min.js +1 -1
  59. package/dist/spy-local-cache.js +65 -65
  60. package/dist/spy-local-cache.min.js +1 -1
  61. package/example/local-cache.html +77 -15
  62. package/package.json +4 -12
  63. package/src/head/base.ts +37 -4
  64. package/src/head/error.ts +9 -19
  65. package/src/head/whitescreen.ts +14 -14
  66. package/src/lib/huffman.ts +37 -56
  67. package/src/lib/interface.ts +5 -0
  68. package/src/spy-client-basic.ts +92 -23
  69. package/src/spy-client.ts +19 -1
  70. package/src/spy-local-cache.ts +41 -16
@@ -1,16 +1,16 @@
1
1
  /*! *****************************************************************************
2
- Copyright (c) Microsoft Corporation.
2
+ Copyright (c) Microsoft Corporation. All rights reserved.
3
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4
+ this file except in compliance with the License. You may obtain a copy of the
5
+ License at http://www.apache.org/licenses/LICENSE-2.0
3
6
 
4
- Permission to use, copy, modify, and/or distribute this software for any
5
- purpose with or without fee is hereby granted.
7
+ THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8
+ KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
9
+ WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
10
+ MERCHANTABLITY OR NON-INFRINGEMENT.
6
11
 
7
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
12
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13
- PERFORMANCE OF THIS SOFTWARE.
12
+ See the Apache Version 2.0 License for specific language governing permissions
13
+ and limitations under the License.
14
14
  ***************************************************************************** */
15
15
  /* global Reflect, Promise */
16
16
 
@@ -132,7 +132,8 @@ function getxpath(el) {
132
132
  * @author kaivean
133
133
  */
134
134
  var defaultLogServer = 'https://sp1.baidu.com/5b1ZeDe5KgQFm2e88IuM_a/mwb2.gif?';
135
- var isIos = /(iPhone|iPod|iPad)/.test(navigator.userAgent);
135
+ var ver = navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?)_/);
136
+ var isLtIos14 = ver && ver[2] && (+ver[2] < 14);
136
137
  function err(msg) {
137
138
  console.error("[SpyClient_log]" + msg);
138
139
  // throw new Error(msg);
@@ -149,6 +150,9 @@ function stringify(obj) {
149
150
  return encodeURIComponent(key) + '=' + encodeURIComponent(value);
150
151
  }).join('&');
151
152
  }
153
+ function isArray(arr) {
154
+ return Object.prototype.toString.call(arr) === '[object Array]';
155
+ }
152
156
  var SpyClient$1 = /** @class */ (function () {
153
157
  function SpyClient(option) {
154
158
  this.sample = {};
@@ -161,38 +165,93 @@ var SpyClient$1 = /** @class */ (function () {
161
165
  lid: option.lid,
162
166
  check: option.check !== false,
163
167
  sample: option.sample,
168
+ localCache: option.localCache,
164
169
  logServer: option.logServer || defaultLogServer,
165
170
  };
166
171
  }
167
- SpyClient.prototype.send = function (query) {
168
- if (!this.check(query)) {
172
+ SpyClient.prototype.fetch = function (url, data) {
173
+ if (!window.fetch) {
169
174
  return;
170
175
  }
171
- // 当前api设置了抽样,
172
- if (typeof query.sample === 'number') {
173
- if (Math.random() > query.sample) {
174
- return;
175
- }
176
+ fetch(url, {
177
+ method: 'POST',
178
+ credentials: 'include',
179
+ headers: {
180
+ 'Content-Type': 'application/json',
181
+ },
182
+ body: JSON.stringify(data),
183
+ });
184
+ };
185
+ SpyClient.prototype.sendPost = function (data) {
186
+ var logItems = isArray(data) ? data : [data];
187
+ var first = logItems[0];
188
+ // 需要在页面暴漏出来pid等基本信息,方式调试查看基本信息与兼容目前的监控
189
+ var query = {
190
+ pid: first.pid,
191
+ type: first.type,
192
+ group: first.group,
193
+ };
194
+ var url = this.option.logServer + stringify(query);
195
+ if (!(!isLtIos14
196
+ && navigator.sendBeacon
197
+ && navigator.sendBeacon(url, JSON.stringify(data)))) {
198
+ this.fetch(url, data);
176
199
  }
177
- else if (typeof this.option.sample === 'number' && Math.random() > this.option.sample) { // 否则,用全局抽样
200
+ };
201
+ SpyClient.prototype.handle = function (logItem) {
202
+ if (!this.check(logItem)) {
178
203
  return;
179
204
  }
180
- query = assign({
205
+ logItem = assign({
181
206
  pid: this.option.pid,
182
207
  lid: this.option.lid,
183
208
  ts: Date.now(),
184
209
  group: 'common',
185
- }, query);
186
- delete query.sample;
187
- var url = this.option.logServer + stringify(query);
188
- // 目前服务器端支持sendBeacon的post请求,可以优先采用,该api可以降低打点丢失率
189
- // 但是ios有些问题:在webkit浏览内核环境下,beacon requests的请求方式存在证书验证的bug.
190
- // 修复说明在如下链接中:https://bugs.webkit.org/show_bug.cgi?id=193508
191
- // 但是目前为止,在iOS12.2版本中该问题依旧存在
192
- if (!(!isIos
193
- && navigator.sendBeacon
194
- && navigator.sendBeacon(url))) {
195
- (new Image()).src = url;
210
+ }, logItem);
211
+ if (this.option.localCache) {
212
+ this.option.localCache.addLog(logItem);
213
+ }
214
+ // 当前api设置了抽样,
215
+ if (typeof logItem.sample === 'number') {
216
+ if (Math.random() > logItem.sample) {
217
+ return;
218
+ }
219
+ }
220
+ else if (typeof this.option.sample === 'number' && Math.random() > this.option.sample) { // 否则,用全局抽样
221
+ return;
222
+ }
223
+ delete logItem.sample;
224
+ return logItem;
225
+ };
226
+ SpyClient.prototype.send = function (data, post) {
227
+ if (post === void 0) { post = false; }
228
+ var logItems = isArray(data) ? data : [data];
229
+ var postData = [];
230
+ for (var _i = 0, logItems_1 = logItems; _i < logItems_1.length; _i++) {
231
+ var logItem = logItems_1[_i];
232
+ logItem = this.handle(logItem);
233
+ if (!logItem) {
234
+ continue;
235
+ }
236
+ postData.push(logItem);
237
+ // 期望通过post方式上传日志
238
+ if (post) {
239
+ continue;
240
+ }
241
+ var url = this.option.logServer + stringify(logItem);
242
+ // 目前服务器端支持sendBeacon的post请求,可以优先采用,该api可以降低打点丢失率
243
+ // 但是ios有些问题:在webkit浏览内核环境下,beacon requests的请求方式存在证书验证的bug,发送失败但返回正确.
244
+ // 修复说明在如下链接中:https://bugs.webkit.org/show_bug.cgi?id=193508
245
+ // 但是目前为止,在iOS12.2版本中该问题依旧存在
246
+ // 2021-11-11: 发现ios 14可以送,故小于14的不发送
247
+ if (!(!isLtIos14
248
+ && navigator.sendBeacon
249
+ && navigator.sendBeacon(url))) {
250
+ (new Image()).src = url;
251
+ }
252
+ }
253
+ if (post) {
254
+ this.sendPost(postData);
196
255
  }
197
256
  };
198
257
  SpyClient.prototype.check = function (query) {
@@ -1307,8 +1366,25 @@ var SpyClient = /** @class */ (function (_super) {
1307
1366
  document.addEventListener('visibilitychange', _this.visibilitychangeCB);
1308
1367
  window.addEventListener('beforeunload', _this.leave, false);
1309
1368
  window.addEventListener('unload', _this.leave, false);
1369
+ _this.handleHead();
1310
1370
  return _this;
1311
1371
  }
1372
+ SpyClient.prototype.handleHead = function () {
1373
+ var _this = this;
1374
+ if (this.option.localCache) {
1375
+ var spyHead = window.__spyHead;
1376
+ if (spyHead && spyHead.winerrors) {
1377
+ for (var index = 0; index < spyHead.winerrors.length; index++) {
1378
+ var obj = spyHead.winerrors[index];
1379
+ this.option.localCache.addLog(obj);
1380
+ }
1381
+ // Head发送的异常,也保存一份到本地,主要是JS错误和资源加载异常
1382
+ spyHead.interceptor = function (obj) {
1383
+ _this.option.localCache.addLog(obj);
1384
+ };
1385
+ }
1386
+ }
1387
+ };
1312
1388
  SpyClient.prototype.listenFID = function (cb) {
1313
1389
  this.invoke('listenFID', cb);
1314
1390
  };
package/dist/spy-head.js CHANGED
@@ -87,11 +87,32 @@
87
87
  init: function (conf) {
88
88
  this.conf = conf;
89
89
  },
90
- send: function (obj, logServer) {
91
- obj.type = obj.type || 'except';
90
+ addError: function (obj) {
91
+ // 有些错误一下出现很多次,都聚合都一个错误,加上次数
92
+ if (this.winerrors.length > 0) {
93
+ var lastObj = this.winerrors[this.winerrors.length - 1];
94
+ if (obj.info.msg === lastObj.info.msg) {
95
+ lastObj.info.count += (lastObj.info.count || 0);
96
+ return;
97
+ }
98
+ }
99
+ if (this.winerrors.length < 1000) {
100
+ this.winerrors.push(obj);
101
+ }
102
+ },
103
+ send: function (obj, isSend, logServer) {
92
104
  var conf = this.conf;
105
+ obj.type = obj.type || 'except';
106
+ obj.pid = conf.pid;
107
+ obj.lid = conf.lid;
108
+ obj.ts = Date.now();
109
+ this.addError(obj);
110
+ this.interceptor && this.interceptor(obj);
111
+ if (isSend === false) {
112
+ return;
113
+ }
93
114
  logServer = logServer || conf.logServer;
94
- var logUrl = logServer + "?pid=" + conf.pid + "&lid=" + conf.lid + "&ts=" + Date.now()
115
+ var logUrl = logServer + "?pid=" + obj.pid + "&lid=" + obj.lid + "&ts=" + obj.ts
95
116
  + ("&type=" + obj.type + "&group=" + obj.group + "&info=" + encodeURIComponent(JSON.stringify(obj.info)));
96
117
  if (obj.dim) {
97
118
  logUrl += '&dim=' + encodeURIComponent(JSON.stringify(obj.dim));
@@ -147,18 +168,18 @@
147
168
  }
148
169
  // 历史错误
149
170
  var historys = [];
150
- for (var index = 0; index < spyHead.winerrors.length; index++) {
151
- var item = spyHead.winerrors[index];
152
- var prefix = item.count > 1 ? "(" + item.count + ")" : '';
153
- historys.push(prefix + item.msg);
171
+ for (var index = 0; index < winerrors.length; index++) {
172
+ var item = winerrors[index];
173
+ var prefix = item.info.count > 1 ? "(" + item.info.count + ")" : '';
174
+ historys.push(prefix + item.info.msg);
154
175
  }
155
176
  info.hisErrors = historys.join('----');
156
177
  var allow = true;
157
178
  if (jsError.handler) {
158
179
  allow = jsError.handler(obj);
159
180
  }
160
- if (allow !== false && isSendJserror) {
161
- spyHead.send(obj);
181
+ if (allow !== false) {
182
+ spyHead.send(obj, isSendJserror);
162
183
  }
163
184
  }
164
185
  // 资源错误
@@ -178,20 +199,11 @@
178
199
  if (resourceError.handler) {
179
200
  allow = resourceError.handler(obj);
180
201
  }
181
- if (allow !== false && isSendResource) {
182
- spyHead.send(obj);
202
+ if (allow !== false) {
203
+ spyHead.send(obj, isSendResource);
183
204
  }
184
205
  resourceErrorCount++;
185
206
  }
186
- // 有些错误一下出现很多次,都聚合都一个错误,加上次数
187
- if (winerrors.length > 0) {
188
- var lastInfo = winerrors[winerrors.length - 1];
189
- if (info.msg === lastInfo.msg) {
190
- lastInfo.count += (lastInfo.count || 0);
191
- return;
192
- }
193
- }
194
- winerrors.push(info);
195
207
  }
196
208
  catch (e) {
197
209
  console.error(e);
@@ -200,7 +212,7 @@
200
212
  window.addEventListener('error', spyListenError, true);
201
213
  spyHead.errorDestroy = function () {
202
214
  window.removeEventListener('error', spyListenError, true);
203
- spyHead.winerrors = null;
215
+ spyHead.winerrors = [];
204
216
  };
205
217
  }
206
218
 
@@ -270,8 +282,8 @@
270
282
  var errors = spyHead.winerrors;
271
283
  var historys = [];
272
284
  for (var i = 0; i < errors.length; i++) {
273
- var stack = (errors[i].stack || '').split('\n')[0];
274
- historys.push("(" + i + ")" + (stack || errors[i].msg));
285
+ var stack = (errors[i].info.stack || '').split('\n')[0];
286
+ historys.push("(" + i + ")" + (stack || errors[i].info.msg));
275
287
  }
276
288
  return historys.join(';;');
277
289
  }
@@ -301,25 +313,25 @@
301
313
  }
302
314
  return false;
303
315
  }
304
- if (isSend) {
316
+ if (selector) {
305
317
  setTimeout(function () {
306
- var obj = {
307
- group: whiteScreenError.group,
308
- info: {
309
- msg: '',
310
- netTime: getNetTime(),
311
- hisErrors: getHisError(),
312
- deviceInfo: getDeviceInfo(),
313
- },
314
- };
315
318
  if (isWhiteScreen()) {
319
+ var obj = {
320
+ group: whiteScreenError.group,
321
+ info: {
322
+ msg: '',
323
+ netTime: getNetTime(),
324
+ hisErrors: getHisError(),
325
+ deviceInfo: getDeviceInfo(),
326
+ },
327
+ };
316
328
  obj.info.msg = 'WhiteScren Error';
317
329
  var allow = true;
318
330
  if (handler) {
319
331
  allow = handler(obj);
320
332
  }
321
333
  if (allow !== false && obj.info.msg) {
322
- spyHead && spyHead.send(obj);
334
+ spyHead && spyHead.send(obj, isSend);
323
335
  }
324
336
  }
325
337
  }, timeout);
@@ -1 +1 @@
1
- !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e="undefined"!=typeof globalThis?globalThis:e||self).__spyHead=n()}(this,function(){"use strict";function E(e){var n=function(e){if(URL){e=new URL(e);if(void 0!==e.host)return{protocol:e.protocol,host:e.host,pathname:e.pathname,ext:""}}}(e);n||((r=document.createElement("a")).href=e,n={protocol:r.protocol,host:r.host||location.host,pathname:r.pathname,ext:""});var r=n.pathname.split(".");return n.ext=r[r.length-1],n}function n(e){return+e.toFixed(1)}var S={conf:{},winerrors:[],errorDestroy:function(){},observerDestroy:function(){},entryMap:{},init:function(e){this.conf=e},send:function(e,n){e.type=e.type||"except";var r=this.conf,r=(n=n||r.logServer)+"?pid="+r.pid+"&lid="+r.lid+"&ts="+Date.now()+"&type="+e.type+"&group="+e.group+"&info="+encodeURIComponent(JSON.stringify(e.info));e.dim&&(r+="&dim="+encodeURIComponent(JSON.stringify(e.dim)));var t=new Image;t.src=r,t.onload=t.onerror=function(){t=null}}};function r(e){var h=e.resourceError||{},g=e.jsError||{},v=Math.random()<(g.sample||0),w=Math.random()<(h.sample||0),y=S.winerrors,T=0;function n(e){try{var n=e.target,r={info:{},dim:{},group:""},t=r.info,o=e.srcElement,i=navigator.connection||{};if(t.downlink=i.downlink,t.effectiveType=i.effectiveType,t.rtt=i.rtt,t.deviceMemory=navigator.deviceMemory||0,t.hardwareConcurrency=navigator.hardwareConcurrency||0,o===window){r.group=g.group;var a,s=e.error||{};t.msg=e.message,t.file=e.filename,t.ln=e.lineno,t.col=e.colno,t.stack=(s.stack||"").split("\n").slice(0,3).join("\n"),-1===t.msg.indexOf("MODULE_TIMEOUT")||(a=t.msg.match(/^.*Hang:(.*); Miss:(.*)/))&&a[2]&&(t.msg="MODULE_TIMEOUT for miss:"+a[2]);for(var c=[],d=0;d<S.winerrors.length;d++){var f=S.winerrors[d],u=1<f.count?"("+f.count+")":"";c.push(u+f.msg)}t.hisErrors=c.join("----");var p=!0;!1!==(p=g.handler?g.handler(r):p)&&v&&S.send(r)}else{r.group=h.group,r.dim.type=o.tagName.toLowerCase();var l=o.src||o.href;t.msg=l||"unknown load eror",r.dim.host=E(l).host,n&&"IMG"===n.tagName&&(t.xpath=function(e){if(!e)return{xpath:""};for(var n=[];e&&1===e.nodeType&&e!==e.parentNode;){var r=e.tagName.toLowerCase();if(e.getAttribute("id")?r+="[#"+e.getAttribute("id")+"]":e.classList&&e.classList.length&&(r+="[."+e.classList[e.classList.length-1]+"]"),n.push(r),e===document.body)break;e=e.parentNode}return{xpath:n.join("<")}}(n).xpath),T&&(t.hisErrCount=T);p=!0;!1!==(p=h.handler?h.handler(r):p)&&w&&S.send(r),T++}if(0<y.length){var m=y[y.length-1];if(t.msg===m.msg)return void(m.count+=m.count||0)}y.push(t)}catch(e){console.error(e)}}window.addEventListener("error",n,!0),S.errorDestroy=function(){window.removeEventListener("error",n,!0),S.winerrors=null}}function t(e){var r=e.whiteScreenError||{},t=r.handler,o=r.selector,i=r.subSelector,e=r.timeout||6e3;function a(){if(!window.performance)return!1;var e,e={wait:n((e=window.performance.timing).domainLookupStart-(e.navigationStart||e.fetchStart||e.startTime)),dns:n(e.domainLookupEnd-e.domainLookupStart),connect:n(e.connectEnd-e.connectStart),req:n(e.responseStart-e.requestStart),res:n(e.responseEnd-e.responseStart)};return"&wait="+e.wait+"&dns="+e.dns+"&connect="+e.connect+"&requestTime="+e.req+"&resoneTime="+e.res}Math.random()<(r.sample||0)&&setTimeout(function(){var e,n,e={group:r.group,info:{msg:"",netTime:a(),hisErrors:function(){if(!S.winerrors)return!1;for(var e=S.winerrors,n=[],r=0;r<e.length;r++){var t=(e[r].stack||"").split("\n")[0];n.push("("+r+")"+(t||e[r].msg))}return n.join(";;")}(),deviceInfo:(n={},e=navigator.connection||{},n.downlink=e.downlink,n.effectiveType=e.effectiveType,n.rtt=e.rtt,n.deviceMemory=navigator.deviceMemory||0,n.hardwareConcurrency=navigator.hardwareConcurrency||0,n)}};(n=document.querySelector(o))&&n.querySelector(i)&&!(n.clientHeight<2*window.innerHeight/3)||(n=!0,!(e.info.msg="WhiteScren Error")!==(n=t?t(e):n)&&e.info.msg&&S&&S.send(e))},e)}return S.init=function(e){e.logServer||(e.logServer="https://sp1.baidu.com/5b1ZeDe5KgQFm2e88IuM_a/mwb2.gif"),r(this.conf=e),function(){if(window.PerformanceObserver){var e=new window.PerformanceObserver(function(e){for(var n=S.entryMap,r=e.getEntries(),t=0;t<r.length;t++){var o=r[t];n[o.entryType]||(n[o.entryType]=[]),n[o.entryType].push(o)}});S.observerDestroy=function(){e.disconnect()};try{e.observe({entryTypes:["longtask","layout-shift","first-input","largest-contentful-paint"]})}catch(e){}}}(),t(e)},window.__spyclientConf&&S.init(window.__spyclientConf),S});
1
+ !function(e,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define(r):(e="undefined"!=typeof globalThis?globalThis:e||self).__spyHead=r()}(this,function(){"use strict";function E(e){var r=function(e){if(URL){var r=new URL(e);if(void 0!==r.host)return{protocol:r.protocol,host:r.host,pathname:r.pathname,ext:""}}}(e);if(!r){var n=document.createElement("a");n.href=e,r={protocol:n.protocol,host:n.host||location.host,pathname:n.pathname,ext:""}}var t=r.pathname.split(".");return r.ext=t[t.length-1],r}function c(e){return+e.toFixed(1)}var T={conf:{},winerrors:[],errorDestroy:function(){},observerDestroy:function(){},entryMap:{},init:function(e){this.conf=e},addError:function(e){if(0<this.winerrors.length){var r=this.winerrors[this.winerrors.length-1];if(e.info.msg===r.info.msg)return void(r.info.count+=r.info.count||0)}this.winerrors.length<1e3&&this.winerrors.push(e)},send:function(e,r,n){var t=this.conf;if(e.type=e.type||"except",e.pid=t.pid,e.lid=t.lid,e.ts=Date.now(),this.addError(e),this.interceptor&&this.interceptor(e),!1!==r){var o=(n=n||t.logServer)+"?pid="+e.pid+"&lid="+e.lid+"&ts="+e.ts+"&type="+e.type+"&group="+e.group+"&info="+encodeURIComponent(JSON.stringify(e.info));e.dim&&(o+="&dim="+encodeURIComponent(JSON.stringify(e.dim)));var i=new Image;i.src=o,i.onload=i.onerror=function(){i=null}}}};function r(e){var h=e.resourceError||{},m=e.jsError||{},g=Math.random()<(m.sample?m.sample:0),v=Math.random()<(h.sample?h.sample:0),w=T.winerrors,y=0;function r(e){try{var r=e.target,n={info:{},dim:{},group:""},t=n.info,o=e.srcElement,i=navigator.connection||{};if(t.downlink=i.downlink,t.effectiveType=i.effectiveType,t.rtt=i.rtt,t.deviceMemory=navigator.deviceMemory||0,t.hardwareConcurrency=navigator.hardwareConcurrency||0,o===window){n.group=m.group;var a=e.error||{};if(t.msg=e.message,t.file=e.filename,t.ln=e.lineno,t.col=e.colno,t.stack=(a.stack||"").split("\n").slice(0,3).join("\n"),-1!==t.msg.indexOf("MODULE_TIMEOUT")){var s=t.msg.match(/^.*Hang:(.*); Miss:(.*)/);s&&s[2]&&(t.msg="MODULE_TIMEOUT for miss:"+s[2])}for(var c=[],f=0;f<w.length;f++){var d=w[f],u=1<d.info.count?"("+d.info.count+")":"";c.push(u+d.info.msg)}t.hisErrors=c.join("----");var p=!0;m.handler&&(p=m.handler(n)),!1!==p&&T.send(n,g)}else{n.group=h.group,n.dim.type=o.tagName.toLowerCase();var l=o.src||o.href;t.msg=l||"unknown load eror",n.dim.host=E(l).host,r&&"IMG"===r.tagName&&(t.xpath=function(e){if(!e)return{xpath:""};for(var r=[];e&&1===e.nodeType&&e!==e.parentNode;){var n=e.tagName.toLowerCase();if(e.getAttribute("id")?n+="[#"+e.getAttribute("id")+"]":e.classList&&e.classList.length&&(n+="[."+e.classList[e.classList.length-1]+"]"),r.push(n),e===document.body)break;e=e.parentNode}return{xpath:r.join("<")}}(r).xpath),y&&(t.hisErrCount=y);p=!0;h.handler&&(p=h.handler(n)),!1!==p&&T.send(n,v),y++}}catch(e){console.error(e)}}window.addEventListener("error",r,!0),T.errorDestroy=function(){window.removeEventListener("error",r,!0),T.winerrors=[]}}function n(e){var n=e.whiteScreenError||{},t=n.handler,o=n.selector,i=n.subSelector,r=n.timeout||6e3,a=Math.random()<(n.sample?n.sample:0);function s(){if(!window.performance)return!1;var e=function(e){return{wait:c(e.domainLookupStart-(e.navigationStart||e.fetchStart||e.startTime)),dns:c(e.domainLookupEnd-e.domainLookupStart),connect:c(e.connectEnd-e.connectStart),req:c(e.responseStart-e.requestStart),res:c(e.responseEnd-e.responseStart)}}(window.performance.timing);return"&wait="+e.wait+"&dns="+e.dns+"&connect="+e.connect+"&requestTime="+e.req+"&resoneTime="+e.res}o&&setTimeout(function(){if(function(){var e=document.querySelector(o);return!e||(!e.querySelector(i)||e.clientHeight<2*window.innerHeight/3)}()){var e={group:n.group,info:{msg:"",netTime:s(),hisErrors:function(){if(!T.winerrors)return!1;for(var e=T.winerrors,r=[],n=0;n<e.length;n++){var t=(e[n].info.stack||"").split("\n")[0];r.push("("+n+")"+(t||e[n].info.msg))}return r.join(";;")}(),deviceInfo:function(){var e={},r=navigator.connection||{};return e.downlink=r.downlink,e.effectiveType=r.effectiveType,e.rtt=r.rtt,e.deviceMemory=navigator.deviceMemory||0,e.hardwareConcurrency=navigator.hardwareConcurrency||0,e}()}};e.info.msg="WhiteScren Error";var r=!0;t&&(r=t(e)),!1!==r&&e.info.msg&&T&&T.send(e,a)}},r)}return T.init=function(e){e.logServer||(e.logServer="https://sp1.baidu.com/5b1ZeDe5KgQFm2e88IuM_a/mwb2.gif"),r(this.conf=e),function(){if(window.PerformanceObserver){var e=new window.PerformanceObserver(function(e){for(var r=T.entryMap,n=e.getEntries(),t=0;t<n.length;t++){var o=n[t];r[o.entryType]||(r[o.entryType]=[]),r[o.entryType].push(o)}});T.observerDestroy=function(){e.disconnect()};try{e.observe({entryTypes:["longtask","layout-shift","first-input","largest-contentful-paint"]})}catch(e){}}}(),n(e)},window.__spyclientConf&&T.init(window.__spyclientConf),T});
@@ -5,18 +5,18 @@
5
5
  }(this, (function () { 'use strict';
6
6
 
7
7
  /*! *****************************************************************************
8
- Copyright (c) Microsoft Corporation.
8
+ Copyright (c) Microsoft Corporation. All rights reserved.
9
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
10
+ this file except in compliance with the License. You may obtain a copy of the
11
+ License at http://www.apache.org/licenses/LICENSE-2.0
9
12
 
10
- Permission to use, copy, modify, and/or distribute this software for any
11
- purpose with or without fee is hereby granted.
13
+ THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
15
+ WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
16
+ MERCHANTABLITY OR NON-INFRINGEMENT.
12
17
 
13
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
18
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19
- PERFORMANCE OF THIS SOFTWARE.
18
+ See the Apache Version 2.0 License for specific language governing permissions
19
+ and limitations under the License.
20
20
  ***************************************************************************** */
21
21
  /* global Reflect, Promise */
22
22
 
@@ -74,9 +74,9 @@
74
74
  * @return 返回的就是list形式
75
75
  */
76
76
  function getNodes(bytes) {
77
- //创建一个list
77
+ // 创建一个list
78
78
  var list = [];
79
- //counts 统计每一个byte出现的次数
79
+ // counts 统计每一个byte出现的次数
80
80
  var counts = {};
81
81
  for (var _i = 0, bytes_1 = bytes; _i < bytes_1.length; _i++) {
82
82
  var b = bytes_1[_i];
@@ -110,7 +110,7 @@
110
110
  var parent_1 = new HuffmanNode(null, leftNode.weight + rightNode.weight);
111
111
  parent_1.left = leftNode;
112
112
  parent_1.right = rightNode;
113
- //将新的二叉树,加入到nodes
113
+ // 将新的二叉树,加入到nodes
114
114
  nodes.unshift(parent_1);
115
115
  }
116
116
  }
@@ -140,33 +140,32 @@
140
140
  string2.push(code);
141
141
  if (node != null) { // 如果node == null不处理
142
142
  // 判断当前node是叶子节点还是非叶子节点
143
- if (node.data == null) { //非叶子节点
143
+ if (node.data == null) { // 非叶子节点
144
144
  // 递归处理
145
145
  // 向左递归
146
146
  getCodes(node.left, '0', string2);
147
147
  // 向右递归
148
148
  getCodes(node.right, '1', string2);
149
149
  }
150
- else { //说明是一个叶子节点
150
+ else { // 说明是一个叶子节点
151
151
  // 就表示找到了某个叶子节点的最后
152
152
  huffmanCodes[node.data] = string2.join('');
153
153
  }
154
154
  }
155
155
  }
156
- getCodes(root, "", strings);
156
+ getCodes(root, '', strings);
157
157
  return huffmanCodes;
158
158
  }
159
- //编写一个方法,将字符串对应的bytes数组,通过生成的赫夫曼编码表,返回一个赫夫曼编码压缩后的byte数组
160
159
  /**
161
- *
160
+ * 编写一个方法,将字符串对应的bytes数组,通过生成的赫夫曼编码表,返回一个赫夫曼编码压缩后的byte数组
162
161
  * @param {原始的字符串对应的bytes数组} bytes
163
162
  * @param {生成的赫夫曼编码表} huffmanCodes
164
163
  * @return 返回的是字符串对应的一个byte数组
165
164
  */
166
165
  function zip(bytes, huffmanCodes) {
167
- //1.利用huffmanCodes将bytes转成赫夫曼编码对应的字符串
166
+ // 1.利用huffmanCodes将bytes转成赫夫曼编码对应的字符串
168
167
  var string = [];
169
- //遍历数组
168
+ // 遍历数组
170
169
  for (var _i = 0, bytes_2 = bytes; _i < bytes_2.length; _i++) {
171
170
  var b = bytes_2[_i];
172
171
  string.push(huffmanCodes[b]);
@@ -174,10 +173,10 @@
174
173
  return string;
175
174
  }
176
175
  function huffStringToByte(strs) {
177
- //计算赫夫曼编码字符串的长度
176
+ // 计算赫夫曼编码字符串的长度
178
177
  var str = strs.join('');
179
178
  var len = Math.ceil(str.length / 8);
180
- //创建存储压缩后的byte数组
179
+ // 创建存储压缩后的byte数组
181
180
  var huffmanCodeByte = new Array(len + 1);
182
181
  var index = 0;
183
182
  var strByte = ''; // 记录是第几个byte
@@ -222,7 +221,7 @@
222
221
  * @returns 是byte对应的二进制字符串
223
222
  */
224
223
  function huffByteToString(flag, byte) {
225
- //如果是
224
+ // 如果是
226
225
  if (flag) {
227
226
  byte |= 256;
228
227
  }
@@ -230,13 +229,10 @@
230
229
  if (flag) {
231
230
  return str.substring(str.length - 8);
232
231
  }
233
- else {
234
- return str;
235
- }
232
+ return str;
236
233
  }
237
- //编写一份方法,完成对压缩数据的解码
238
234
  /**
239
- *
235
+ * 编写一份方法,完成对压缩数据的解码
240
236
  * @param {赫夫曼编码表} huffmanCodes
241
237
  * @param {赫夫曼编码得到的二进制数组} huffmanBytes
242
238
  */
@@ -244,7 +240,7 @@
244
240
  // 1.先得到二进制字符串 形式11001111111011......
245
241
  var heffmanStrArr = [];
246
242
  for (var i = 0; i < huffmanBytes.length - 1; i++) {
247
- //判断是不是最后一个字节
243
+ // 判断是不是最后一个字节
248
244
  var flag = (i !== huffmanBytes.length - 2);
249
245
  heffmanStrArr.push(huffByteToString(flag, huffmanBytes[i]));
250
246
  }
@@ -274,15 +270,15 @@
274
270
  break;
275
271
  }
276
272
  b = map[key];
277
- if (!b) { //没有匹配到
273
+ if (!b) { // 没有匹配到
278
274
  count++;
279
275
  }
280
276
  else {
281
- //匹配到
277
+ // 匹配到
282
278
  flag = false;
283
279
  }
284
280
  }
285
- list.push(parseInt(b));
281
+ list.push(parseInt(b, 10));
286
282
  i += count;
287
283
  }
288
284
  // 当for循环结束后,list中就存放了所有的字符
@@ -309,31 +305,14 @@
309
305
  var _a = huffmanZip(bytes), result = _a.result, codes = _a.codes;
310
306
  return {
311
307
  codes: codes,
312
- result: byteToString(result)
308
+ result: byteToString(result),
313
309
  };
314
310
  }
315
311
  function huffmanDecode(codes, str) {
316
312
  var bytes = stringToByte(str);
317
313
  var data = decode(codes, bytes);
318
314
  return byteToString(data);
319
- }
320
- // For test
321
- // let content = JSON.stringify({
322
- // type: 3,
323
- // fm: 'disp',
324
- // data: [{"base":{"size":{"doc":{"w":360,"h":4875},"wind":{"w":360,"h":640},"scr":{"w":360,"h":640}},"vsb":"visible","num":16},"t":1629773746698,"path":"/s"}],
325
- // qid: 10991431029479106376,
326
- // did: '8dd09c47c7bc90c9fd7274f0ad2c581e',
327
- // q: '刘德华',
328
- // t: 1629773746698
329
- // });
330
- // console.log('压缩前的字符串', content, '其长度:', content.length);
331
- // const res = huffmanEncode(content);
332
- // console.log('压缩后的字符串长度', res.result.length);
333
- // console.log('压缩后的字符串', res.result);
334
- // const out = huffmanDecode(res.codes, res.result);
335
- // console.log('解压后的字符串', out, '其长度:', out.length);
336
- // console.log('解压后的数据', JSON.stringify(JSON.parse(out)));
315
+ }
337
316
 
338
317
  var Storage = /** @class */ (function () {
339
318
  function Storage() {
@@ -587,6 +566,10 @@
587
566
  interval: 500,
588
567
  maxRecordLen: 30,
589
568
  onFlush: function () { },
569
+ onSave: function () { },
570
+ onAdd: function () {
571
+ return true;
572
+ },
590
573
  storage: IndexedDB.isSupport()
591
574
  ? 'indexedDB'
592
575
  : LS.isSupport()
@@ -620,6 +603,11 @@
620
603
  };
621
604
  SpyLocalCache.prototype.addLog = function (info) {
622
605
  var _this = this;
606
+ if (this.option.onAdd) {
607
+ if (!this.option.onAdd(info)) {
608
+ return;
609
+ }
610
+ }
623
611
  info = JSON.stringify(info);
624
612
  this.tmpList.push(info);
625
613
  // 控制写日志频率
@@ -662,27 +650,39 @@
662
650
  };
663
651
  SpyLocalCache.prototype.save = function () {
664
652
  var _this = this;
653
+ var st = Date.now();
665
654
  this.getData(function (list) {
666
655
  // 只保留最近的maxRecordLen条日志
667
656
  var reserveLen = _this.option.maxRecordLen - 1;
668
657
  var originList = list.length > reserveLen ? list.slice(list.length - reserveLen, list.length) : list;
669
- var content = originList.concat(_this.tmpList).join('\n');
670
- var data = _this.zip(content);
671
- var codesStr = '';
672
- if (data.codes) {
673
- codesStr = JSON.stringify(data.codes);
674
- _this.storage.set(_this.option.key + 'Codes', codesStr);
675
- }
676
- else {
677
- _this.storage.rm(_this.option.key + 'Codes');
658
+ var newList = originList.concat(_this.tmpList);
659
+ var content = newList.join('\n');
660
+ var error = null;
661
+ var len = 0;
662
+ try {
663
+ var data = _this.zip(content);
664
+ var codesStr = '';
665
+ if (data.codes) {
666
+ codesStr = JSON.stringify(data.codes);
667
+ _this.storage.set(_this.option.key + 'Codes', codesStr);
668
+ }
669
+ else {
670
+ _this.storage.rm(_this.option.key + 'Codes');
671
+ }
672
+ _this.storage.set(_this.option.key, data.result);
673
+ len = data.result.length;
678
674
  }
679
- var startTime = performance.now();
680
- _this.storage.set(_this.option.key, data.result);
681
- var costTime = ((performance.now() - startTime) * 100).toFixed(0);
682
- if (_this.option.costTime) {
683
- _this.option.costTime(costTime);
675
+ catch (e) {
676
+ error = e;
677
+ console.error(e);
684
678
  }
685
679
  _this.tmpList = [];
680
+ _this.option.onSave && _this.option.onSave({
681
+ cost: Date.now() - st,
682
+ length: len / 1024,
683
+ list: newList,
684
+ error: error,
685
+ });
686
686
  });
687
687
  };
688
688
  SpyLocalCache.prototype.flushLog = function () {