spy-client 2.1.1 → 2.1.7

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 +5 -1
  44. package/dist/spy-client-basic.esm.js +82 -21
  45. package/dist/spy-client-basic.iife.js +82 -21
  46. package/dist/spy-client-basic.iife.min.js +1 -1
  47. package/dist/spy-client-basic.js +82 -21
  48. package/dist/spy-client-basic.min.js +1 -1
  49. package/dist/spy-client-basic.mjs +82 -21
  50. package/dist/spy-client.d.ts +1 -0
  51. package/dist/spy-client.esm.js +109 -31
  52. package/dist/spy-client.iife.js +109 -31
  53. package/dist/spy-client.iife.min.js +1 -1
  54. package/dist/spy-client.js +109 -31
  55. package/dist/spy-client.min.js +1 -1
  56. package/dist/spy-client.mjs +109 -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 +126 -64
  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 +95 -26
  69. package/src/spy-client.ts +19 -1
  70. package/src/spy-local-cache.ts +103 -10
@@ -33,7 +33,8 @@
33
33
  * @author kaivean
34
34
  */
35
35
  var defaultLogServer = 'https://sp1.baidu.com/5b1ZeDe5KgQFm2e88IuM_a/mwb2.gif?';
36
- var isIos = /(iPhone|iPod|iPad)/.test(navigator.userAgent);
36
+ var ver = navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?)_/);
37
+ var isLtIos14 = ver && ver[2] && (+ver[2] < 14);
37
38
  function err(msg) {
38
39
  console.error("[SpyClient_log]" + msg);
39
40
  // throw new Error(msg);
@@ -50,6 +51,9 @@
50
51
  return encodeURIComponent(key) + '=' + encodeURIComponent(value);
51
52
  }).join('&');
52
53
  }
54
+ function isArray(arr) {
55
+ return Object.prototype.toString.call(arr) === '[object Array]';
56
+ }
53
57
  var SpyClient = /** @class */ (function () {
54
58
  function SpyClient(option) {
55
59
  this.sample = {};
@@ -62,38 +66,55 @@
62
66
  lid: option.lid,
63
67
  check: option.check !== false,
64
68
  sample: option.sample,
69
+ localCache: option.localCache,
65
70
  logServer: option.logServer || defaultLogServer,
66
71
  };
67
72
  }
68
- SpyClient.prototype.send = function (query) {
69
- if (!this.check(query)) {
73
+ SpyClient.prototype.handle = function (logItem) {
74
+ if (!this.check(logItem)) {
70
75
  return;
71
76
  }
77
+ logItem = assign({
78
+ pid: this.option.pid,
79
+ lid: this.option.lid,
80
+ ts: Date.now(),
81
+ group: 'common',
82
+ }, logItem);
83
+ if (this.option.localCache) {
84
+ this.option.localCache.addLog(logItem);
85
+ }
72
86
  // 当前api设置了抽样,
73
- if (typeof query.sample === 'number') {
74
- if (Math.random() > query.sample) {
87
+ if (typeof logItem.sample === 'number') {
88
+ if (Math.random() > logItem.sample) {
75
89
  return;
76
90
  }
77
91
  }
78
92
  else if (typeof this.option.sample === 'number' && Math.random() > this.option.sample) { // 否则,用全局抽样
79
93
  return;
80
94
  }
81
- query = assign({
82
- pid: this.option.pid,
83
- lid: this.option.lid,
84
- ts: Date.now(),
85
- group: 'common',
86
- }, query);
87
- delete query.sample;
88
- var url = this.option.logServer + stringify(query);
89
- // 目前服务器端支持sendBeacon的post请求,可以优先采用,该api可以降低打点丢失率
90
- // 但是ios有些问题:在webkit浏览内核环境下,beacon requests的请求方式存在证书验证的bug.
91
- // 修复说明在如下链接中:https://bugs.webkit.org/show_bug.cgi?id=193508
92
- // 但是目前为止,在iOS12.2版本中该问题依旧存在
93
- if (!(!isIos
94
- && navigator.sendBeacon
95
- && navigator.sendBeacon(url))) {
96
- (new Image()).src = url;
95
+ delete logItem.sample;
96
+ return logItem;
97
+ };
98
+ SpyClient.prototype.send = function (data, post) {
99
+ if (post === void 0) { post = false; }
100
+ var logItems = isArray(data) ? data : [data];
101
+ var postData = [];
102
+ for (var _i = 0, logItems_1 = logItems; _i < logItems_1.length; _i++) {
103
+ var logItem = logItems_1[_i];
104
+ logItem = this.handle(logItem);
105
+ if (!logItem) {
106
+ continue;
107
+ }
108
+ postData.push(logItem);
109
+ // 期望通过post方式上传日志
110
+ if (post) {
111
+ continue;
112
+ }
113
+ var url = this.option.logServer + stringify(logItem);
114
+ this.request(url);
115
+ }
116
+ if (post) {
117
+ this.sendPost(postData);
97
118
  }
98
119
  };
99
120
  SpyClient.prototype.check = function (query) {
@@ -235,6 +256,46 @@
235
256
  SpyClient.prototype.clearAllMark = function () {
236
257
  this.markCache = {};
237
258
  };
259
+ // send(data, true) 也能以post发送,但是会有严格校验
260
+ // sendPost能以post发送,但没有校验
261
+ SpyClient.prototype.sendPost = function (data) {
262
+ var logItems = isArray(data) ? data : [data];
263
+ var first = logItems[0];
264
+ // 需要在页面暴漏出来pid等基本信息,方式调试查看基本信息与兼容目前的监控
265
+ var query = {
266
+ pid: first.pid,
267
+ type: first.type,
268
+ group: first.group,
269
+ };
270
+ var url = this.option.logServer + stringify(query);
271
+ this.request(url, data);
272
+ };
273
+ // 有data时,意味着要用post发送请求
274
+ SpyClient.prototype.request = function (url, data) {
275
+ if (!(!isLtIos14
276
+ && navigator.sendBeacon
277
+ && navigator.sendBeacon(url, data ? JSON.stringify(data) : undefined))) {
278
+ if (data) {
279
+ this.fetch(url, data);
280
+ }
281
+ else {
282
+ (new Image()).src = url;
283
+ }
284
+ }
285
+ };
286
+ SpyClient.prototype.fetch = function (url, data) {
287
+ if (!window.fetch) {
288
+ return;
289
+ }
290
+ fetch(url, {
291
+ method: 'POST',
292
+ credentials: 'include',
293
+ headers: {
294
+ 'Content-Type': 'application/json',
295
+ },
296
+ body: JSON.stringify(data),
297
+ });
298
+ };
238
299
  return SpyClient;
239
300
  }());
240
301
 
@@ -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,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 t=/(iPhone|iPod|iPad)/.test(navigator.userAgent);function u(e){console.error("[SpyClient_log]"+e)}function e(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 e.prototype.send=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;delete(e=o({pid:this.option.pid,lid:this.option.lid,ts:Date.now(),group:"common"},e)).sample;var n,e=this.option.logServer+(n=e,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("&"));!t&&navigator.sendBeacon&&navigator.sendBeacon(e)||((new Image).src=e)}},e.prototype.check=function(e){if(!this.option.check)return!0;var t=["perf","except","dist","count"];if(-1===t.indexOf(e.type))return u("type only is one of "+t.join(", ")),!1;if(e.group&&30<e.group.length)return u("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 u("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 u("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 u("info."+i+" value length execeeds 30 when type == 'dist'"),!1}else if("number"!=typeof s)return u("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 u("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 u("dim."+c+" value ["+f+"] is unexpected. Length must be not more than 30. Supported chars: a-zA-Z0-9-_*. /#+@& and Chinese"),!1}return!0},e.prototype.sendPerf=function(e){this.send(o({type:"perf"},e))},e.prototype.sendExcept=function(e){this.send(o({type:"except"},e))},e.prototype.sendDist=function(e){this.send(o({type:"dist"},e))},e.prototype.sendCount=function(e){this.send(o({type:"count"},e))},e.prototype.sendExceptForError=function(e,t){var n=o({},t);n.info=o({},t.info||{},{msg:e.message,stack:e.stack}),this.sendExcept(n)},e.prototype.startMark=function(e){this.markCache[e]={start:Date.now()}},e.prototype.endMark=function(e){return this.markCache[e]?(this.markCache[e].total=Date.now()-this.markCache[e].start,this.markCache[e].total):0},e.prototype.clearMark=function(e){this.markCache[e]&&delete this.markCache[e]},e.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},e.prototype.clearAllMark=function(){this.markCache={}},e});
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 (.*?)_/),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.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){window.fetch&&fetch(e,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})},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 isIos = /(iPhone|iPod|iPad)/.test(navigator.userAgent);
30
+ var ver = navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?)_/);
31
+ var isLtIos14 = ver && ver[2] && (+ver[2] < 14);
31
32
  function err(msg) {
32
33
  console.error("[SpyClient_log]" + msg);
33
34
  // throw new Error(msg);
@@ -44,6 +45,9 @@ function stringify(obj) {
44
45
  return encodeURIComponent(key) + '=' + encodeURIComponent(value);
45
46
  }).join('&');
46
47
  }
48
+ function isArray(arr) {
49
+ return Object.prototype.toString.call(arr) === '[object Array]';
50
+ }
47
51
  var SpyClient = /** @class */ (function () {
48
52
  function SpyClient(option) {
49
53
  this.sample = {};
@@ -56,38 +60,55 @@ var SpyClient = /** @class */ (function () {
56
60
  lid: option.lid,
57
61
  check: option.check !== false,
58
62
  sample: option.sample,
63
+ localCache: option.localCache,
59
64
  logServer: option.logServer || defaultLogServer,
60
65
  };
61
66
  }
62
- SpyClient.prototype.send = function (query) {
63
- if (!this.check(query)) {
67
+ SpyClient.prototype.handle = function (logItem) {
68
+ if (!this.check(logItem)) {
64
69
  return;
65
70
  }
71
+ logItem = assign({
72
+ pid: this.option.pid,
73
+ lid: this.option.lid,
74
+ ts: Date.now(),
75
+ group: 'common',
76
+ }, logItem);
77
+ if (this.option.localCache) {
78
+ this.option.localCache.addLog(logItem);
79
+ }
66
80
  // 当前api设置了抽样,
67
- if (typeof query.sample === 'number') {
68
- if (Math.random() > query.sample) {
81
+ if (typeof logItem.sample === 'number') {
82
+ if (Math.random() > logItem.sample) {
69
83
  return;
70
84
  }
71
85
  }
72
86
  else if (typeof this.option.sample === 'number' && Math.random() > this.option.sample) { // 否则,用全局抽样
73
87
  return;
74
88
  }
75
- query = assign({
76
- pid: this.option.pid,
77
- lid: this.option.lid,
78
- ts: Date.now(),
79
- group: 'common',
80
- }, query);
81
- delete query.sample;
82
- var url = this.option.logServer + stringify(query);
83
- // 目前服务器端支持sendBeacon的post请求,可以优先采用,该api可以降低打点丢失率
84
- // 但是ios有些问题:在webkit浏览内核环境下,beacon requests的请求方式存在证书验证的bug.
85
- // 修复说明在如下链接中:https://bugs.webkit.org/show_bug.cgi?id=193508
86
- // 但是目前为止,在iOS12.2版本中该问题依旧存在
87
- if (!(!isIos
88
- && navigator.sendBeacon
89
- && navigator.sendBeacon(url))) {
90
- (new Image()).src = url;
89
+ delete logItem.sample;
90
+ return logItem;
91
+ };
92
+ SpyClient.prototype.send = function (data, post) {
93
+ if (post === void 0) { post = false; }
94
+ var logItems = isArray(data) ? data : [data];
95
+ var postData = [];
96
+ for (var _i = 0, logItems_1 = logItems; _i < logItems_1.length; _i++) {
97
+ var logItem = logItems_1[_i];
98
+ logItem = this.handle(logItem);
99
+ if (!logItem) {
100
+ continue;
101
+ }
102
+ postData.push(logItem);
103
+ // 期望通过post方式上传日志
104
+ if (post) {
105
+ continue;
106
+ }
107
+ var url = this.option.logServer + stringify(logItem);
108
+ this.request(url);
109
+ }
110
+ if (post) {
111
+ this.sendPost(postData);
91
112
  }
92
113
  };
93
114
  SpyClient.prototype.check = function (query) {
@@ -229,6 +250,46 @@ var SpyClient = /** @class */ (function () {
229
250
  SpyClient.prototype.clearAllMark = function () {
230
251
  this.markCache = {};
231
252
  };
253
+ // send(data, true) 也能以post发送,但是会有严格校验
254
+ // sendPost能以post发送,但没有校验
255
+ SpyClient.prototype.sendPost = function (data) {
256
+ var logItems = isArray(data) ? data : [data];
257
+ var first = logItems[0];
258
+ // 需要在页面暴漏出来pid等基本信息,方式调试查看基本信息与兼容目前的监控
259
+ var query = {
260
+ pid: first.pid,
261
+ type: first.type,
262
+ group: first.group,
263
+ };
264
+ var url = this.option.logServer + stringify(query);
265
+ this.request(url, data);
266
+ };
267
+ // 有data时,意味着要用post发送请求
268
+ SpyClient.prototype.request = function (url, data) {
269
+ if (!(!isLtIos14
270
+ && navigator.sendBeacon
271
+ && navigator.sendBeacon(url, data ? JSON.stringify(data) : undefined))) {
272
+ if (data) {
273
+ this.fetch(url, data);
274
+ }
275
+ else {
276
+ (new Image()).src = url;
277
+ }
278
+ }
279
+ };
280
+ SpyClient.prototype.fetch = function (url, data) {
281
+ if (!window.fetch) {
282
+ return;
283
+ }
284
+ fetch(url, {
285
+ method: 'POST',
286
+ credentials: 'include',
287
+ headers: {
288
+ 'Content-Type': 'application/json',
289
+ },
290
+ body: JSON.stringify(data),
291
+ });
292
+ };
232
293
  return SpyClient;
233
294
  }());
234
295
 
@@ -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;
@@ -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,55 @@ 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.handle = function (logItem) {
173
+ if (!this.check(logItem)) {
169
174
  return;
170
175
  }
176
+ logItem = assign({
177
+ pid: this.option.pid,
178
+ lid: this.option.lid,
179
+ ts: Date.now(),
180
+ group: 'common',
181
+ }, logItem);
182
+ if (this.option.localCache) {
183
+ this.option.localCache.addLog(logItem);
184
+ }
171
185
  // 当前api设置了抽样,
172
- if (typeof query.sample === 'number') {
173
- if (Math.random() > query.sample) {
186
+ if (typeof logItem.sample === 'number') {
187
+ if (Math.random() > logItem.sample) {
174
188
  return;
175
189
  }
176
190
  }
177
191
  else if (typeof this.option.sample === 'number' && Math.random() > this.option.sample) { // 否则,用全局抽样
178
192
  return;
179
193
  }
180
- query = assign({
181
- pid: this.option.pid,
182
- lid: this.option.lid,
183
- ts: Date.now(),
184
- 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;
194
+ delete logItem.sample;
195
+ return logItem;
196
+ };
197
+ SpyClient.prototype.send = function (data, post) {
198
+ if (post === void 0) { post = false; }
199
+ var logItems = isArray(data) ? data : [data];
200
+ var postData = [];
201
+ for (var _i = 0, logItems_1 = logItems; _i < logItems_1.length; _i++) {
202
+ var logItem = logItems_1[_i];
203
+ logItem = this.handle(logItem);
204
+ if (!logItem) {
205
+ continue;
206
+ }
207
+ postData.push(logItem);
208
+ // 期望通过post方式上传日志
209
+ if (post) {
210
+ continue;
211
+ }
212
+ var url = this.option.logServer + stringify(logItem);
213
+ this.request(url);
214
+ }
215
+ if (post) {
216
+ this.sendPost(postData);
196
217
  }
197
218
  };
198
219
  SpyClient.prototype.check = function (query) {
@@ -334,6 +355,46 @@ var SpyClient$1 = /** @class */ (function () {
334
355
  SpyClient.prototype.clearAllMark = function () {
335
356
  this.markCache = {};
336
357
  };
358
+ // send(data, true) 也能以post发送,但是会有严格校验
359
+ // sendPost能以post发送,但没有校验
360
+ SpyClient.prototype.sendPost = function (data) {
361
+ var logItems = isArray(data) ? data : [data];
362
+ var first = logItems[0];
363
+ // 需要在页面暴漏出来pid等基本信息,方式调试查看基本信息与兼容目前的监控
364
+ var query = {
365
+ pid: first.pid,
366
+ type: first.type,
367
+ group: first.group,
368
+ };
369
+ var url = this.option.logServer + stringify(query);
370
+ this.request(url, data);
371
+ };
372
+ // 有data时,意味着要用post发送请求
373
+ SpyClient.prototype.request = function (url, data) {
374
+ if (!(!isLtIos14
375
+ && navigator.sendBeacon
376
+ && navigator.sendBeacon(url, data ? JSON.stringify(data) : undefined))) {
377
+ if (data) {
378
+ this.fetch(url, data);
379
+ }
380
+ else {
381
+ (new Image()).src = url;
382
+ }
383
+ }
384
+ };
385
+ SpyClient.prototype.fetch = function (url, data) {
386
+ if (!window.fetch) {
387
+ return;
388
+ }
389
+ fetch(url, {
390
+ method: 'POST',
391
+ credentials: 'include',
392
+ headers: {
393
+ 'Content-Type': 'application/json',
394
+ },
395
+ body: JSON.stringify(data),
396
+ });
397
+ };
337
398
  return SpyClient;
338
399
  }());
339
400
 
@@ -1307,8 +1368,25 @@ var SpyClient = /** @class */ (function (_super) {
1307
1368
  document.addEventListener('visibilitychange', _this.visibilitychangeCB);
1308
1369
  window.addEventListener('beforeunload', _this.leave, false);
1309
1370
  window.addEventListener('unload', _this.leave, false);
1371
+ _this.handleHead();
1310
1372
  return _this;
1311
1373
  }
1374
+ SpyClient.prototype.handleHead = function () {
1375
+ var _this = this;
1376
+ if (this.option.localCache) {
1377
+ var spyHead = window.__spyHead;
1378
+ if (spyHead && spyHead.winerrors) {
1379
+ for (var index = 0; index < spyHead.winerrors.length; index++) {
1380
+ var obj = spyHead.winerrors[index];
1381
+ this.option.localCache.addLog(obj);
1382
+ }
1383
+ // Head发送的异常,也保存一份到本地,主要是JS错误和资源加载异常
1384
+ spyHead.interceptor = function (obj) {
1385
+ _this.option.localCache.addLog(obj);
1386
+ };
1387
+ }
1388
+ }
1389
+ };
1312
1390
  SpyClient.prototype.listenFID = function (cb) {
1313
1391
  this.invoke('listenFID', cb);
1314
1392
  };