spy-client 2.1.2 → 2.1.8

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 (64) hide show
  1. package/README.md +8 -3
  2. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/basicSpec.ts.html +1 -1
  3. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/checkSpec.ts.html +1 -1
  4. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/headSpec.ts.html +1 -1
  5. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/index.html +1 -1
  6. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/markSpec.ts.html +1 -1
  7. package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/metricSpec.ts.html +1 -1
  8. package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/base.css +224 -0
  9. package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/basicSpec.ts.html +740 -0
  10. package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/block-navigation.js +79 -0
  11. package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/checkSpec.ts.html +479 -0
  12. package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/favicon.png +0 -0
  13. package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/headSpec.ts.html +695 -0
  14. package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/index.html +171 -0
  15. package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/markSpec.ts.html +284 -0
  16. package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/metricSpec.ts.html +977 -0
  17. package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/prettify.css +1 -0
  18. package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/prettify.js +2 -0
  19. package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/sort-arrow-sprite.png +0 -0
  20. package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/sorter.js +170 -0
  21. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/base.css +224 -0
  22. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/basicSpec.ts.html +740 -0
  23. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/block-navigation.js +79 -0
  24. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/checkSpec.ts.html +479 -0
  25. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/favicon.png +0 -0
  26. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/headSpec.ts.html +695 -0
  27. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/index.html +171 -0
  28. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/markSpec.ts.html +284 -0
  29. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/metricSpec.ts.html +977 -0
  30. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/prettify.css +1 -0
  31. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/prettify.js +2 -0
  32. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/sort-arrow-sprite.png +0 -0
  33. package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/sorter.js +170 -0
  34. package/dist/head/base.d.ts +12 -7
  35. package/dist/lib/interface.d.ts +4 -0
  36. package/dist/spy-client-basic.d.ts +3 -2
  37. package/dist/spy-client-basic.esm.js +55 -46
  38. package/dist/spy-client-basic.iife.js +55 -46
  39. package/dist/spy-client-basic.iife.min.js +1 -1
  40. package/dist/spy-client-basic.js +55 -46
  41. package/dist/spy-client-basic.min.js +1 -1
  42. package/dist/spy-client-basic.mjs +55 -46
  43. package/dist/spy-client.d.ts +1 -0
  44. package/dist/spy-client.esm.js +72 -46
  45. package/dist/spy-client.iife.js +72 -46
  46. package/dist/spy-client.iife.min.js +1 -1
  47. package/dist/spy-client.js +72 -46
  48. package/dist/spy-client.min.js +1 -1
  49. package/dist/spy-client.mjs +72 -46
  50. package/dist/spy-head.js +46 -34
  51. package/dist/spy-head.min.js +1 -1
  52. package/dist/spy-local-cache.js +28 -41
  53. package/dist/spy-local-cache.min.js +1 -1
  54. package/example/index.html +2 -0
  55. package/example/local-cache.html +77 -15
  56. package/package.json +3 -3
  57. package/src/head/base.ts +37 -4
  58. package/src/head/error.ts +9 -19
  59. package/src/head/whitescreen.ts +14 -14
  60. package/src/lib/huffman.ts +37 -56
  61. package/src/lib/interface.ts +5 -0
  62. package/src/spy-client-basic.ts +65 -58
  63. package/src/spy-client.ts +19 -1
  64. package/src/spy-local-cache.ts +12 -2
@@ -33,7 +33,8 @@
33
33
  * @author kaivean
34
34
  */
35
35
  var defaultLogServer = 'https://sp1.baidu.com/5b1ZeDe5KgQFm2e88IuM_a/mwb2.gif?';
36
- var ver = navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?)_/);
36
+ // 基础版本兼容非浏览器环境
37
+ var ver = navigator && navigator.userAgent ? navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?)_/) : '';
37
38
  var isLtIos14 = ver && ver[2] && (+ver[2] < 14);
38
39
  function err(msg) {
39
40
  console.error("[SpyClient_log]" + msg);
@@ -66,42 +67,23 @@
66
67
  lid: option.lid,
67
68
  check: option.check !== false,
68
69
  sample: option.sample,
70
+ localCache: option.localCache,
69
71
  logServer: option.logServer || defaultLogServer,
70
72
  };
71
73
  }
72
- SpyClient.prototype.fetch = function (url, data) {
73
- if (!window.fetch) {
74
- return;
75
- }
76
- fetch(url, {
77
- method: 'POST',
78
- credentials: 'include',
79
- headers: {
80
- 'Content-Type': 'application/json'
81
- },
82
- body: JSON.stringify(data)
83
- });
84
- };
85
- SpyClient.prototype.sendPost = function (data) {
86
- var logItems = isArray(data) ? data : [data];
87
- var first = logItems[0];
88
- // 需要在页面暴漏出来pid等基本信息,方式调试查看基本信息与兼容目前的监控
89
- var query = {
90
- pid: first.pid,
91
- type: first.type,
92
- group: first.group,
93
- };
94
- var url = this.option.logServer + stringify(query);
95
- if (!(!isLtIos14
96
- && navigator.sendBeacon
97
- && navigator.sendBeacon(url, JSON.stringify(data)))) {
98
- this.fetch(url, data);
99
- }
100
- };
101
74
  SpyClient.prototype.handle = function (logItem) {
102
75
  if (!this.check(logItem)) {
103
76
  return;
104
77
  }
78
+ logItem = assign({
79
+ pid: this.option.pid,
80
+ lid: this.option.lid,
81
+ ts: Date.now(),
82
+ group: 'common',
83
+ }, logItem);
84
+ if (this.option.localCache) {
85
+ this.option.localCache.addLog(logItem);
86
+ }
105
87
  // 当前api设置了抽样,
106
88
  if (typeof logItem.sample === 'number') {
107
89
  if (Math.random() > logItem.sample) {
@@ -111,12 +93,6 @@
111
93
  else if (typeof this.option.sample === 'number' && Math.random() > this.option.sample) { // 否则,用全局抽样
112
94
  return;
113
95
  }
114
- logItem = assign({
115
- pid: this.option.pid,
116
- lid: this.option.lid,
117
- ts: Date.now(),
118
- group: 'common',
119
- }, logItem);
120
96
  delete logItem.sample;
121
97
  return logItem;
122
98
  };
@@ -136,16 +112,7 @@
136
112
  continue;
137
113
  }
138
114
  var url = this.option.logServer + stringify(logItem);
139
- // 目前服务器端支持sendBeacon的post请求,可以优先采用,该api可以降低打点丢失率
140
- // 但是ios有些问题:在webkit浏览内核环境下,beacon requests的请求方式存在证书验证的bug,发送失败但返回正确.
141
- // 修复说明在如下链接中:https://bugs.webkit.org/show_bug.cgi?id=193508
142
- // 但是目前为止,在iOS12.2版本中该问题依旧存在
143
- // 2021-11-11: 发现ios 14可以送,故小于14的不发送
144
- if (!(!isLtIos14
145
- && navigator.sendBeacon
146
- && navigator.sendBeacon(url))) {
147
- (new Image()).src = url;
148
- }
115
+ this.request(url);
149
116
  }
150
117
  if (post) {
151
118
  this.sendPost(postData);
@@ -290,6 +257,48 @@
290
257
  SpyClient.prototype.clearAllMark = function () {
291
258
  this.markCache = {};
292
259
  };
260
+ // send(data, true) 也能以post发送,但是会有严格校验
261
+ // sendPost能以post发送,但没有校验
262
+ SpyClient.prototype.sendPost = function (data) {
263
+ var logItems = isArray(data) ? data : [data];
264
+ var first = logItems[0];
265
+ // 需要在页面暴漏出来pid等基本信息,方式调试查看基本信息与兼容目前的监控
266
+ var query = {
267
+ pid: first.pid,
268
+ type: first.type,
269
+ group: first.group,
270
+ };
271
+ var url = this.option.logServer + stringify(query);
272
+ this.request(url, data);
273
+ };
274
+ // 有data时,意味着要用post发送请求
275
+ SpyClient.prototype.request = function (url, data) {
276
+ if (!(!isLtIos14
277
+ && navigator
278
+ && navigator.sendBeacon
279
+ && navigator.sendBeacon(url, data ? JSON.stringify(data) : undefined))) {
280
+ if (data) {
281
+ this.fetch(url, data);
282
+ }
283
+ else {
284
+ (new Image()).src = url;
285
+ }
286
+ }
287
+ };
288
+ SpyClient.prototype.fetch = function (url, data) {
289
+ if (!fetch) {
290
+ err('Global fetch method doesn\'t exist');
291
+ return;
292
+ }
293
+ fetch(url, {
294
+ method: 'POST',
295
+ credentials: 'include',
296
+ headers: {
297
+ 'Content-Type': 'application/json',
298
+ },
299
+ body: JSON.stringify(data),
300
+ });
301
+ };
293
302
  return SpyClient;
294
303
  }());
295
304
 
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).SpyClient=t()}(this,function(){"use strict";function o(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return(Object.assign||function(e){for(var t=void 0,n=1,o=arguments.length;n<o;n++)for(var r in t=arguments[n])Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e}).apply(this,e)}var e=navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?)_/),a=e&&e[2]&&+e[2]<14;function h(e){console.error("[SpyClient_log]"+e)}function p(n){return Object.keys(n).map(function(e){var t=n[e];return void 0===t?t="":"string"!=typeof t&&(t=JSON.stringify(t)),encodeURIComponent(e)+"="+encodeURIComponent(t)}).join("&")}function c(e){return"[object Array]"===Object.prototype.toString.call(e)}function t(e){if(this.sample={},this.markCache={},!e.pid)throw new Error("pid is required");this.option={pid:e.pid,lid:e.lid,check:!1!==e.check,sample:e.sample,logServer:e.logServer||"https://sp1.baidu.com/5b1ZeDe5KgQFm2e88IuM_a/mwb2.gif?"}}return t.prototype.fetch=function(e,t){window.fetch&&fetch(e,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})},t.prototype.sendPost=function(e){var t=(c(e)?e:[e])[0],n={pid:t.pid,type:t.type,group:t.group},o=this.option.logServer+p(n);!a&&navigator.sendBeacon&&navigator.sendBeacon(o,JSON.stringify(e))||this.fetch(o,e)},t.prototype.handle=function(e){if(this.check(e)){if("number"==typeof e.sample){if(Math.random()>e.sample)return}else if("number"==typeof this.option.sample&&Math.random()>this.option.sample)return;return delete(e=o({pid:this.option.pid,lid:this.option.lid,ts:Date.now(),group:"common"},e)).sample,e}},t.prototype.send=function(e,t){void 0===t&&(t=!1);for(var n=[],o=0,r=c(e)?e:[e];o<r.length;o++){var i=r[o];if((i=this.handle(i))&&(n.push(i),!t)){var s=this.option.logServer+p(i);!a&&navigator.sendBeacon&&navigator.sendBeacon(s)||((new Image).src=s)}}t&&this.sendPost(n)},t.prototype.check=function(e){if(!this.option.check)return!0;var t=["perf","except","dist","count"];if(-1===t.indexOf(e.type))return h("type only is one of "+t.join(", ")),!1;if(e.group&&30<e.group.length)return h("group length execeeds 30"),!1;var n=/^[a-zA-Z0-9-_]{0,30}$/;if("except"===e.type){if("string"!=typeof e.info.msg||!e.info.msg.length)return h("info.msg field must be not empty and is String"),!1}else for(var o=0,r=Object.keys(e.info);o<r.length;o++){var i=r[o];if(!n.test(i))return h("info."+i+" is unexpected. Length must be not more than 30. Supported chars: a-zA-Z0-9-_"),!1;var s=e.info[i];if("dist"===e.type){if(30<s.length)return h("info."+i+" value length execeeds 30 when type == 'dist'"),!1}else if("number"!=typeof s)return h("info."+i+" value must be number"),!1}if(e.dim)for(var a=0,p=Object.keys(e.dim);a<p.length;a++){var c=p[a];if(!n.test(c))return h("dim key ["+c+"] is unexpected. Length must be not more than 30. Supported chars: a-zA-Z0-9-_"),!1;var f=e.dim[c];if(!/^[a-zA-Z0-9\-_\*\.\s\/#\+@\&\u4e00-\u9fa5]{0,30}$/.test(f))return h("dim."+c+" value ["+f+"] is unexpected. Length must be not more than 30. Supported chars: a-zA-Z0-9-_*. /#+@& and Chinese"),!1}return!0},t.prototype.sendPerf=function(e){this.send(o({type:"perf"},e))},t.prototype.sendExcept=function(e){this.send(o({type:"except"},e))},t.prototype.sendDist=function(e){this.send(o({type:"dist"},e))},t.prototype.sendCount=function(e){this.send(o({type:"count"},e))},t.prototype.sendExceptForError=function(e,t){var n=o({},t);n.info=o({},t.info||{},{msg:e.message,stack:e.stack}),this.sendExcept(n)},t.prototype.startMark=function(e){this.markCache[e]={start:Date.now()}},t.prototype.endMark=function(e){return this.markCache[e]?(this.markCache[e].total=Date.now()-this.markCache[e].start,this.markCache[e].total):0},t.prototype.clearMark=function(e){this.markCache[e]&&delete this.markCache[e]},t.prototype.getAllMark=function(){for(var e={},t=0,n=Object.keys(this.markCache);t<n.length;t++){var o=n[t];e[o]=this.markCache[o].total}return e},t.prototype.clearAllMark=function(){this.markCache={}},t});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).SpyClient=t()}(this,function(){"use strict";function o(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return(Object.assign||function(e){for(var t=void 0,n=1,o=arguments.length;n<o;n++)for(var r in t=arguments[n])Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e}).apply(this,e)}var e=navigator&&navigator.userAgent?navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?)_/):"",n=e&&e[2]&&+e[2]<14;function f(e){console.error("[SpyClient_log]"+e)}function a(n){return Object.keys(n).map(function(e){var t=n[e];return void 0===t?t="":"string"!=typeof t&&(t=JSON.stringify(t)),encodeURIComponent(e)+"="+encodeURIComponent(t)}).join("&")}function p(e){return"[object Array]"===Object.prototype.toString.call(e)}function t(e){if(this.sample={},this.markCache={},!e.pid)throw new Error("pid is required");this.option={pid:e.pid,lid:e.lid,check:!1!==e.check,sample:e.sample,localCache:e.localCache,logServer:e.logServer||"https://sp1.baidu.com/5b1ZeDe5KgQFm2e88IuM_a/mwb2.gif?"}}return t.prototype.handle=function(e){if(this.check(e)){if(e=o({pid:this.option.pid,lid:this.option.lid,ts:Date.now(),group:"common"},e),this.option.localCache&&this.option.localCache.addLog(e),"number"==typeof e.sample){if(Math.random()>e.sample)return}else if("number"==typeof this.option.sample&&Math.random()>this.option.sample)return;return delete e.sample,e}},t.prototype.send=function(e,t){void 0===t&&(t=!1);for(var n=[],o=0,r=p(e)?e:[e];o<r.length;o++){var i=r[o];if((i=this.handle(i))&&(n.push(i),!t)){var s=this.option.logServer+a(i);this.request(s)}}t&&this.sendPost(n)},t.prototype.check=function(e){if(!this.option.check)return!0;var t=["perf","except","dist","count"];if(-1===t.indexOf(e.type))return f("type only is one of "+t.join(", ")),!1;if(e.group&&30<e.group.length)return f("group length execeeds 30"),!1;var n=/^[a-zA-Z0-9-_]{0,30}$/;if("except"===e.type){if("string"!=typeof e.info.msg||!e.info.msg.length)return f("info.msg field must be not empty and is String"),!1}else for(var o=0,r=Object.keys(e.info);o<r.length;o++){var i=r[o];if(!n.test(i))return f("info."+i+" is unexpected. Length must be not more than 30. Supported chars: a-zA-Z0-9-_"),!1;var s=e.info[i];if("dist"===e.type){if(30<s.length)return f("info."+i+" value length execeeds 30 when type == 'dist'"),!1}else if("number"!=typeof s)return f("info."+i+" value must be number"),!1}if(e.dim)for(var a=0,p=Object.keys(e.dim);a<p.length;a++){var c=p[a];if(!n.test(c))return f("dim key ["+c+"] is unexpected. Length must be not more than 30. Supported chars: a-zA-Z0-9-_"),!1;var h=e.dim[c];if(!/^[a-zA-Z0-9\-_\*\.\s\/#\+@\&\u4e00-\u9fa5]{0,30}$/.test(h))return f("dim."+c+" value ["+h+"] is unexpected. Length must be not more than 30. Supported chars: a-zA-Z0-9-_*. /#+@& and Chinese"),!1}return!0},t.prototype.sendPerf=function(e){this.send(o({type:"perf"},e))},t.prototype.sendExcept=function(e){this.send(o({type:"except"},e))},t.prototype.sendDist=function(e){this.send(o({type:"dist"},e))},t.prototype.sendCount=function(e){this.send(o({type:"count"},e))},t.prototype.sendExceptForError=function(e,t){var n=o({},t);n.info=o({},t.info||{},{msg:e.message,stack:e.stack}),this.sendExcept(n)},t.prototype.startMark=function(e){this.markCache[e]={start:Date.now()}},t.prototype.endMark=function(e){return this.markCache[e]?(this.markCache[e].total=Date.now()-this.markCache[e].start,this.markCache[e].total):0},t.prototype.clearMark=function(e){this.markCache[e]&&delete this.markCache[e]},t.prototype.getAllMark=function(){for(var e={},t=0,n=Object.keys(this.markCache);t<n.length;t++){var o=n[t];e[o]=this.markCache[o].total}return e},t.prototype.clearAllMark=function(){this.markCache={}},t.prototype.sendPost=function(e){var t=(p(e)?e:[e])[0],n={pid:t.pid,type:t.type,group:t.group},o=this.option.logServer+a(n);this.request(o,e)},t.prototype.request=function(e,t){!n&&navigator&&navigator.sendBeacon&&navigator.sendBeacon(e,t?JSON.stringify(t):void 0)||(t?this.fetch(e,t):(new Image).src=e)},t.prototype.fetch=function(e,t){fetch?fetch(e,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}):f("Global fetch method doesn't exist")},t});
@@ -27,7 +27,8 @@ function assign() {
27
27
  * @author kaivean
28
28
  */
29
29
  var defaultLogServer = 'https://sp1.baidu.com/5b1ZeDe5KgQFm2e88IuM_a/mwb2.gif?';
30
- var ver = navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?)_/);
30
+ // 基础版本兼容非浏览器环境
31
+ var ver = navigator && navigator.userAgent ? navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?)_/) : '';
31
32
  var isLtIos14 = ver && ver[2] && (+ver[2] < 14);
32
33
  function err(msg) {
33
34
  console.error("[SpyClient_log]" + msg);
@@ -60,42 +61,23 @@ var SpyClient = /** @class */ (function () {
60
61
  lid: option.lid,
61
62
  check: option.check !== false,
62
63
  sample: option.sample,
64
+ localCache: option.localCache,
63
65
  logServer: option.logServer || defaultLogServer,
64
66
  };
65
67
  }
66
- SpyClient.prototype.fetch = function (url, data) {
67
- if (!window.fetch) {
68
- return;
69
- }
70
- fetch(url, {
71
- method: 'POST',
72
- credentials: 'include',
73
- headers: {
74
- 'Content-Type': 'application/json'
75
- },
76
- body: JSON.stringify(data)
77
- });
78
- };
79
- SpyClient.prototype.sendPost = function (data) {
80
- var logItems = isArray(data) ? data : [data];
81
- var first = logItems[0];
82
- // 需要在页面暴漏出来pid等基本信息,方式调试查看基本信息与兼容目前的监控
83
- var query = {
84
- pid: first.pid,
85
- type: first.type,
86
- group: first.group,
87
- };
88
- var url = this.option.logServer + stringify(query);
89
- if (!(!isLtIos14
90
- && navigator.sendBeacon
91
- && navigator.sendBeacon(url, JSON.stringify(data)))) {
92
- this.fetch(url, data);
93
- }
94
- };
95
68
  SpyClient.prototype.handle = function (logItem) {
96
69
  if (!this.check(logItem)) {
97
70
  return;
98
71
  }
72
+ logItem = assign({
73
+ pid: this.option.pid,
74
+ lid: this.option.lid,
75
+ ts: Date.now(),
76
+ group: 'common',
77
+ }, logItem);
78
+ if (this.option.localCache) {
79
+ this.option.localCache.addLog(logItem);
80
+ }
99
81
  // 当前api设置了抽样,
100
82
  if (typeof logItem.sample === 'number') {
101
83
  if (Math.random() > logItem.sample) {
@@ -105,12 +87,6 @@ var SpyClient = /** @class */ (function () {
105
87
  else if (typeof this.option.sample === 'number' && Math.random() > this.option.sample) { // 否则,用全局抽样
106
88
  return;
107
89
  }
108
- logItem = assign({
109
- pid: this.option.pid,
110
- lid: this.option.lid,
111
- ts: Date.now(),
112
- group: 'common',
113
- }, logItem);
114
90
  delete logItem.sample;
115
91
  return logItem;
116
92
  };
@@ -130,16 +106,7 @@ var SpyClient = /** @class */ (function () {
130
106
  continue;
131
107
  }
132
108
  var url = this.option.logServer + stringify(logItem);
133
- // 目前服务器端支持sendBeacon的post请求,可以优先采用,该api可以降低打点丢失率
134
- // 但是ios有些问题:在webkit浏览内核环境下,beacon requests的请求方式存在证书验证的bug,发送失败但返回正确.
135
- // 修复说明在如下链接中:https://bugs.webkit.org/show_bug.cgi?id=193508
136
- // 但是目前为止,在iOS12.2版本中该问题依旧存在
137
- // 2021-11-11: 发现ios 14可以送,故小于14的不发送
138
- if (!(!isLtIos14
139
- && navigator.sendBeacon
140
- && navigator.sendBeacon(url))) {
141
- (new Image()).src = url;
142
- }
109
+ this.request(url);
143
110
  }
144
111
  if (post) {
145
112
  this.sendPost(postData);
@@ -284,6 +251,48 @@ var SpyClient = /** @class */ (function () {
284
251
  SpyClient.prototype.clearAllMark = function () {
285
252
  this.markCache = {};
286
253
  };
254
+ // send(data, true) 也能以post发送,但是会有严格校验
255
+ // sendPost能以post发送,但没有校验
256
+ SpyClient.prototype.sendPost = function (data) {
257
+ var logItems = isArray(data) ? data : [data];
258
+ var first = logItems[0];
259
+ // 需要在页面暴漏出来pid等基本信息,方式调试查看基本信息与兼容目前的监控
260
+ var query = {
261
+ pid: first.pid,
262
+ type: first.type,
263
+ group: first.group,
264
+ };
265
+ var url = this.option.logServer + stringify(query);
266
+ this.request(url, data);
267
+ };
268
+ // 有data时,意味着要用post发送请求
269
+ SpyClient.prototype.request = function (url, data) {
270
+ if (!(!isLtIos14
271
+ && navigator
272
+ && navigator.sendBeacon
273
+ && navigator.sendBeacon(url, data ? JSON.stringify(data) : undefined))) {
274
+ if (data) {
275
+ this.fetch(url, data);
276
+ }
277
+ else {
278
+ (new Image()).src = url;
279
+ }
280
+ }
281
+ };
282
+ SpyClient.prototype.fetch = function (url, data) {
283
+ if (!fetch) {
284
+ err('Global fetch method doesn\'t exist');
285
+ return;
286
+ }
287
+ fetch(url, {
288
+ method: 'POST',
289
+ credentials: 'include',
290
+ headers: {
291
+ 'Content-Type': 'application/json',
292
+ },
293
+ body: JSON.stringify(data),
294
+ });
295
+ };
287
296
  return SpyClient;
288
297
  }());
289
298
 
@@ -7,6 +7,7 @@ import { Module, SpyClientOption, FIDCB, LCPCB, LayoutShiftCB, PageLongtaskCB, L
7
7
  export default class SpyClient extends SpyClientBasic {
8
8
  private readonly modules;
9
9
  constructor(option: SpyClientOption);
10
+ handleHead(): void;
10
11
  listenFID(cb: FIDCB): void;
11
12
  listenLayoutShift(cb: LayoutShiftCB): void;
12
13
  listenLCP(cb: LCPCB): void;
@@ -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 ver = navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?)_/);
135
+ // 基础版本兼容非浏览器环境
136
+ var ver = navigator && navigator.userAgent ? navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?)_/) : '';
136
137
  var isLtIos14 = ver && ver[2] && (+ver[2] < 14);
137
138
  function err(msg) {
138
139
  console.error("[SpyClient_log]" + msg);
@@ -165,42 +166,23 @@ var SpyClient$1 = /** @class */ (function () {
165
166
  lid: option.lid,
166
167
  check: option.check !== false,
167
168
  sample: option.sample,
169
+ localCache: option.localCache,
168
170
  logServer: option.logServer || defaultLogServer,
169
171
  };
170
172
  }
171
- SpyClient.prototype.fetch = function (url, data) {
172
- if (!window.fetch) {
173
- return;
174
- }
175
- fetch(url, {
176
- method: 'POST',
177
- credentials: 'include',
178
- headers: {
179
- 'Content-Type': 'application/json'
180
- },
181
- body: JSON.stringify(data)
182
- });
183
- };
184
- SpyClient.prototype.sendPost = function (data) {
185
- var logItems = isArray(data) ? data : [data];
186
- var first = logItems[0];
187
- // 需要在页面暴漏出来pid等基本信息,方式调试查看基本信息与兼容目前的监控
188
- var query = {
189
- pid: first.pid,
190
- type: first.type,
191
- group: first.group,
192
- };
193
- var url = this.option.logServer + stringify(query);
194
- if (!(!isLtIos14
195
- && navigator.sendBeacon
196
- && navigator.sendBeacon(url, JSON.stringify(data)))) {
197
- this.fetch(url, data);
198
- }
199
- };
200
173
  SpyClient.prototype.handle = function (logItem) {
201
174
  if (!this.check(logItem)) {
202
175
  return;
203
176
  }
177
+ logItem = assign({
178
+ pid: this.option.pid,
179
+ lid: this.option.lid,
180
+ ts: Date.now(),
181
+ group: 'common',
182
+ }, logItem);
183
+ if (this.option.localCache) {
184
+ this.option.localCache.addLog(logItem);
185
+ }
204
186
  // 当前api设置了抽样,
205
187
  if (typeof logItem.sample === 'number') {
206
188
  if (Math.random() > logItem.sample) {
@@ -210,12 +192,6 @@ var SpyClient$1 = /** @class */ (function () {
210
192
  else if (typeof this.option.sample === 'number' && Math.random() > this.option.sample) { // 否则,用全局抽样
211
193
  return;
212
194
  }
213
- logItem = assign({
214
- pid: this.option.pid,
215
- lid: this.option.lid,
216
- ts: Date.now(),
217
- group: 'common',
218
- }, logItem);
219
195
  delete logItem.sample;
220
196
  return logItem;
221
197
  };
@@ -235,16 +211,7 @@ var SpyClient$1 = /** @class */ (function () {
235
211
  continue;
236
212
  }
237
213
  var url = this.option.logServer + stringify(logItem);
238
- // 目前服务器端支持sendBeacon的post请求,可以优先采用,该api可以降低打点丢失率
239
- // 但是ios有些问题:在webkit浏览内核环境下,beacon requests的请求方式存在证书验证的bug,发送失败但返回正确.
240
- // 修复说明在如下链接中:https://bugs.webkit.org/show_bug.cgi?id=193508
241
- // 但是目前为止,在iOS12.2版本中该问题依旧存在
242
- // 2021-11-11: 发现ios 14可以送,故小于14的不发送
243
- if (!(!isLtIos14
244
- && navigator.sendBeacon
245
- && navigator.sendBeacon(url))) {
246
- (new Image()).src = url;
247
- }
214
+ this.request(url);
248
215
  }
249
216
  if (post) {
250
217
  this.sendPost(postData);
@@ -389,6 +356,48 @@ var SpyClient$1 = /** @class */ (function () {
389
356
  SpyClient.prototype.clearAllMark = function () {
390
357
  this.markCache = {};
391
358
  };
359
+ // send(data, true) 也能以post发送,但是会有严格校验
360
+ // sendPost能以post发送,但没有校验
361
+ SpyClient.prototype.sendPost = function (data) {
362
+ var logItems = isArray(data) ? data : [data];
363
+ var first = logItems[0];
364
+ // 需要在页面暴漏出来pid等基本信息,方式调试查看基本信息与兼容目前的监控
365
+ var query = {
366
+ pid: first.pid,
367
+ type: first.type,
368
+ group: first.group,
369
+ };
370
+ var url = this.option.logServer + stringify(query);
371
+ this.request(url, data);
372
+ };
373
+ // 有data时,意味着要用post发送请求
374
+ SpyClient.prototype.request = function (url, data) {
375
+ if (!(!isLtIos14
376
+ && navigator
377
+ && navigator.sendBeacon
378
+ && navigator.sendBeacon(url, data ? JSON.stringify(data) : undefined))) {
379
+ if (data) {
380
+ this.fetch(url, data);
381
+ }
382
+ else {
383
+ (new Image()).src = url;
384
+ }
385
+ }
386
+ };
387
+ SpyClient.prototype.fetch = function (url, data) {
388
+ if (!fetch) {
389
+ err('Global fetch method doesn\'t exist');
390
+ return;
391
+ }
392
+ fetch(url, {
393
+ method: 'POST',
394
+ credentials: 'include',
395
+ headers: {
396
+ 'Content-Type': 'application/json',
397
+ },
398
+ body: JSON.stringify(data),
399
+ });
400
+ };
392
401
  return SpyClient;
393
402
  }());
394
403
 
@@ -1362,8 +1371,25 @@ var SpyClient = /** @class */ (function (_super) {
1362
1371
  document.addEventListener('visibilitychange', _this.visibilitychangeCB);
1363
1372
  window.addEventListener('beforeunload', _this.leave, false);
1364
1373
  window.addEventListener('unload', _this.leave, false);
1374
+ _this.handleHead();
1365
1375
  return _this;
1366
1376
  }
1377
+ SpyClient.prototype.handleHead = function () {
1378
+ var _this = this;
1379
+ if (this.option.localCache) {
1380
+ var spyHead = window.__spyHead;
1381
+ if (spyHead && spyHead.winerrors) {
1382
+ for (var index = 0; index < spyHead.winerrors.length; index++) {
1383
+ var obj = spyHead.winerrors[index];
1384
+ this.option.localCache.addLog(obj);
1385
+ }
1386
+ // Head发送的异常,也保存一份到本地,主要是JS错误和资源加载异常
1387
+ spyHead.interceptor = function (obj) {
1388
+ _this.option.localCache.addLog(obj);
1389
+ };
1390
+ }
1391
+ }
1392
+ };
1367
1393
  SpyClient.prototype.listenFID = function (cb) {
1368
1394
  this.invoke('listenFID', cb);
1369
1395
  };
@@ -135,7 +135,8 @@ var SpyClient = (function () {
135
135
  * @author kaivean
136
136
  */
137
137
  var defaultLogServer = 'https://sp1.baidu.com/5b1ZeDe5KgQFm2e88IuM_a/mwb2.gif?';
138
- var ver = navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?)_/);
138
+ // 基础版本兼容非浏览器环境
139
+ var ver = navigator && navigator.userAgent ? navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?)_/) : '';
139
140
  var isLtIos14 = ver && ver[2] && (+ver[2] < 14);
140
141
  function err(msg) {
141
142
  console.error("[SpyClient_log]" + msg);
@@ -168,42 +169,23 @@ var SpyClient = (function () {
168
169
  lid: option.lid,
169
170
  check: option.check !== false,
170
171
  sample: option.sample,
172
+ localCache: option.localCache,
171
173
  logServer: option.logServer || defaultLogServer,
172
174
  };
173
175
  }
174
- SpyClient.prototype.fetch = function (url, data) {
175
- if (!window.fetch) {
176
- return;
177
- }
178
- fetch(url, {
179
- method: 'POST',
180
- credentials: 'include',
181
- headers: {
182
- 'Content-Type': 'application/json'
183
- },
184
- body: JSON.stringify(data)
185
- });
186
- };
187
- SpyClient.prototype.sendPost = function (data) {
188
- var logItems = isArray(data) ? data : [data];
189
- var first = logItems[0];
190
- // 需要在页面暴漏出来pid等基本信息,方式调试查看基本信息与兼容目前的监控
191
- var query = {
192
- pid: first.pid,
193
- type: first.type,
194
- group: first.group,
195
- };
196
- var url = this.option.logServer + stringify(query);
197
- if (!(!isLtIos14
198
- && navigator.sendBeacon
199
- && navigator.sendBeacon(url, JSON.stringify(data)))) {
200
- this.fetch(url, data);
201
- }
202
- };
203
176
  SpyClient.prototype.handle = function (logItem) {
204
177
  if (!this.check(logItem)) {
205
178
  return;
206
179
  }
180
+ logItem = assign({
181
+ pid: this.option.pid,
182
+ lid: this.option.lid,
183
+ ts: Date.now(),
184
+ group: 'common',
185
+ }, logItem);
186
+ if (this.option.localCache) {
187
+ this.option.localCache.addLog(logItem);
188
+ }
207
189
  // 当前api设置了抽样,
208
190
  if (typeof logItem.sample === 'number') {
209
191
  if (Math.random() > logItem.sample) {
@@ -213,12 +195,6 @@ var SpyClient = (function () {
213
195
  else if (typeof this.option.sample === 'number' && Math.random() > this.option.sample) { // 否则,用全局抽样
214
196
  return;
215
197
  }
216
- logItem = assign({
217
- pid: this.option.pid,
218
- lid: this.option.lid,
219
- ts: Date.now(),
220
- group: 'common',
221
- }, logItem);
222
198
  delete logItem.sample;
223
199
  return logItem;
224
200
  };
@@ -238,16 +214,7 @@ var SpyClient = (function () {
238
214
  continue;
239
215
  }
240
216
  var url = this.option.logServer + stringify(logItem);
241
- // 目前服务器端支持sendBeacon的post请求,可以优先采用,该api可以降低打点丢失率
242
- // 但是ios有些问题:在webkit浏览内核环境下,beacon requests的请求方式存在证书验证的bug,发送失败但返回正确.
243
- // 修复说明在如下链接中:https://bugs.webkit.org/show_bug.cgi?id=193508
244
- // 但是目前为止,在iOS12.2版本中该问题依旧存在
245
- // 2021-11-11: 发现ios 14可以送,故小于14的不发送
246
- if (!(!isLtIos14
247
- && navigator.sendBeacon
248
- && navigator.sendBeacon(url))) {
249
- (new Image()).src = url;
250
- }
217
+ this.request(url);
251
218
  }
252
219
  if (post) {
253
220
  this.sendPost(postData);
@@ -392,6 +359,48 @@ var SpyClient = (function () {
392
359
  SpyClient.prototype.clearAllMark = function () {
393
360
  this.markCache = {};
394
361
  };
362
+ // send(data, true) 也能以post发送,但是会有严格校验
363
+ // sendPost能以post发送,但没有校验
364
+ SpyClient.prototype.sendPost = function (data) {
365
+ var logItems = isArray(data) ? data : [data];
366
+ var first = logItems[0];
367
+ // 需要在页面暴漏出来pid等基本信息,方式调试查看基本信息与兼容目前的监控
368
+ var query = {
369
+ pid: first.pid,
370
+ type: first.type,
371
+ group: first.group,
372
+ };
373
+ var url = this.option.logServer + stringify(query);
374
+ this.request(url, data);
375
+ };
376
+ // 有data时,意味着要用post发送请求
377
+ SpyClient.prototype.request = function (url, data) {
378
+ if (!(!isLtIos14
379
+ && navigator
380
+ && navigator.sendBeacon
381
+ && navigator.sendBeacon(url, data ? JSON.stringify(data) : undefined))) {
382
+ if (data) {
383
+ this.fetch(url, data);
384
+ }
385
+ else {
386
+ (new Image()).src = url;
387
+ }
388
+ }
389
+ };
390
+ SpyClient.prototype.fetch = function (url, data) {
391
+ if (!fetch) {
392
+ err('Global fetch method doesn\'t exist');
393
+ return;
394
+ }
395
+ fetch(url, {
396
+ method: 'POST',
397
+ credentials: 'include',
398
+ headers: {
399
+ 'Content-Type': 'application/json',
400
+ },
401
+ body: JSON.stringify(data),
402
+ });
403
+ };
395
404
  return SpyClient;
396
405
  }());
397
406
 
@@ -1365,8 +1374,25 @@ var SpyClient = (function () {
1365
1374
  document.addEventListener('visibilitychange', _this.visibilitychangeCB);
1366
1375
  window.addEventListener('beforeunload', _this.leave, false);
1367
1376
  window.addEventListener('unload', _this.leave, false);
1377
+ _this.handleHead();
1368
1378
  return _this;
1369
1379
  }
1380
+ SpyClient.prototype.handleHead = function () {
1381
+ var _this = this;
1382
+ if (this.option.localCache) {
1383
+ var spyHead = window.__spyHead;
1384
+ if (spyHead && spyHead.winerrors) {
1385
+ for (var index = 0; index < spyHead.winerrors.length; index++) {
1386
+ var obj = spyHead.winerrors[index];
1387
+ this.option.localCache.addLog(obj);
1388
+ }
1389
+ // Head发送的异常,也保存一份到本地,主要是JS错误和资源加载异常
1390
+ spyHead.interceptor = function (obj) {
1391
+ _this.option.localCache.addLog(obj);
1392
+ };
1393
+ }
1394
+ }
1395
+ };
1370
1396
  SpyClient.prototype.listenFID = function (cb) {
1371
1397
  this.invoke('listenFID', cb);
1372
1398
  };