spy-client 2.1.8 → 2.1.9
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.
- package/README.md +54 -11
- package/dist/spy-client.esm.js +14 -9
- package/dist/spy-client.iife.js +14 -9
- package/dist/spy-client.iife.min.js +1 -1
- package/dist/spy-client.js +14 -9
- package/dist/spy-client.min.js +1 -1
- package/dist/spy-client.mjs +14 -9
- package/dist/spy-head.js +15 -10
- package/dist/spy-head.min.js +1 -1
- package/package.json +1 -1
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/base.css +0 -224
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/basicSpec.ts.html +0 -740
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/block-navigation.js +0 -79
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/checkSpec.ts.html +0 -479
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/favicon.png +0 -0
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/headSpec.ts.html +0 -695
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/index.html +0 -171
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/markSpec.ts.html +0 -284
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/metricSpec.ts.html +0 -977
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/prettify.css +0 -1
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/prettify.js +0 -2
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/sort-arrow-sprite.png +0 -0
- package/coverage/Chrome 92.0.4515.159 (Mac OS 10.15.7)/html/sorter.js +0 -170
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/base.css +0 -224
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/basicSpec.ts.html +0 -740
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/block-navigation.js +0 -79
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/checkSpec.ts.html +0 -479
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/favicon.png +0 -0
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/headSpec.ts.html +0 -695
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/index.html +0 -171
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/markSpec.ts.html +0 -284
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/metricSpec.ts.html +0 -977
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/prettify.css +0 -1
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/prettify.js +0 -2
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/sort-arrow-sprite.png +0 -0
- package/coverage/Chrome 95.0.4638.69 (Mac OS 10.15.7)/html/sorter.js +0 -170
- package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/base.css +0 -224
- package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/basicSpec.ts.html +0 -740
- package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/block-navigation.js +0 -79
- package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/checkSpec.ts.html +0 -479
- package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/favicon.png +0 -0
- package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/headSpec.ts.html +0 -695
- package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/index.html +0 -171
- package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/markSpec.ts.html +0 -284
- package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/metricSpec.ts.html +0 -977
- package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/prettify.css +0 -1
- package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/prettify.js +0 -2
- package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/sort-arrow-sprite.png +0 -0
- package/coverage/Chrome 96.0.4664.110 (Mac OS 10.15.7)/html/sorter.js +0 -170
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/base.css +0 -224
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/basicSpec.ts.html +0 -740
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/block-navigation.js +0 -79
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/checkSpec.ts.html +0 -479
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/favicon.png +0 -0
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/headSpec.ts.html +0 -695
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/index.html +0 -171
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/markSpec.ts.html +0 -284
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/metricSpec.ts.html +0 -977
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/prettify.css +0 -1
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/prettify.js +0 -2
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/sort-arrow-sprite.png +0 -0
- package/coverage/Chrome 96.0.4664.55 (Mac OS 10.15.7)/html/sorter.js +0 -170
- package/src/head/base.ts +0 -69
- package/src/head/error.ts +0 -118
- package/src/head/observer.ts +0 -40
- package/src/head/readme.md +0 -1
- package/src/head/whitescreen.ts +0 -105
- package/src/lib/data.ts +0 -14
- package/src/lib/huffman.ts +0 -307
- package/src/lib/interface.ts +0 -331
- package/src/lib/spyHeadInterface.ts +0 -40
- package/src/lib/util.ts +0 -101
- package/src/module/fid.ts +0 -56
- package/src/module/layoutShift.ts +0 -71
- package/src/module/lcp.ts +0 -63
- package/src/module/longtask.ts +0 -193
- package/src/module/memory.ts +0 -43
- package/src/module/navigatorInfo.ts +0 -61
- package/src/module/resource.ts +0 -433
- package/src/module/timing.ts +0 -75
- package/src/module/tti.ts +0 -139
- package/src/spy-client-basic.ts +0 -389
- package/src/spy-client.ts +0 -198
- package/src/spy-head.ts +0 -31
- package/src/spy-local-cache.ts +0 -478
- package/src/types/globals.d.ts +0 -93
package/src/spy-client-basic.ts
DELETED
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file SpyClient
|
|
3
|
-
* @author kaivean
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import {SpyClientOption} from './lib/interface';
|
|
7
|
-
import {assign} from './lib/util';
|
|
8
|
-
|
|
9
|
-
interface Option {
|
|
10
|
-
/**
|
|
11
|
-
* 指标组,它的每个key就是指标名称(英文表示),在平台对应分组添加该指标名称便能实现自动统计
|
|
12
|
-
*/
|
|
13
|
-
info: object;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* 维度信息对象,它的每个字段就是一个维度名称(英文表示),在平台对应分组添加该维度名称便能实现自动统计
|
|
17
|
-
*/
|
|
18
|
-
dim?: object;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* 分组,默认:common
|
|
22
|
-
*/
|
|
23
|
-
group?: string;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* 抽样,会覆盖全局抽样配置,默认是 1,取值从[0, 1]
|
|
27
|
-
*/
|
|
28
|
-
sample?: number;
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* 日志服务器,默认是webb服务器,尾部需要加?
|
|
32
|
-
*/
|
|
33
|
-
logServer?: string;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
interface ErrorInfo {
|
|
37
|
-
/**
|
|
38
|
-
* 错误唯一标识,平台会统计该错误唯一标识的数量
|
|
39
|
-
*/
|
|
40
|
-
[propName: string]: any;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
interface ErrorOption {
|
|
44
|
-
/**
|
|
45
|
-
* 错误信息对象,它必须有msg字段,是错误唯一标识,其他字段可用户随意添加用来补充错误信息
|
|
46
|
-
*/
|
|
47
|
-
info?: ErrorInfo;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* 维度信息对象,它的每个字段就是一个维度名称(英文表示),在平台对应分组添加该维度名称便能实现自动统计
|
|
51
|
-
*/
|
|
52
|
-
dim?: object;
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* 分组,默认:common
|
|
56
|
-
*/
|
|
57
|
-
group?: string;
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* 抽样,默认是 1,取值从[0, 1],该抽样会覆盖实例初始化时的抽样配置
|
|
61
|
-
*/
|
|
62
|
-
sample?: number;
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* 业务拓展信息
|
|
66
|
-
*/
|
|
67
|
-
ext?: any;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const defaultLogServer = 'https://sp1.baidu.com/5b1ZeDe5KgQFm2e88IuM_a/mwb2.gif?';
|
|
71
|
-
// 基础版本兼容非浏览器环境
|
|
72
|
-
const ver = navigator && navigator.userAgent ? navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?)_/) : '';
|
|
73
|
-
const isLtIos14 = ver && ver[2] && (+ver[2] < 14);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
function err(msg: string) {
|
|
77
|
-
console.error(`[SpyClient_log]${msg}`);
|
|
78
|
-
// throw new Error(msg);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function stringify(obj: any) {
|
|
82
|
-
return Object.keys(obj).map((key: string) => {
|
|
83
|
-
let value = obj[key];
|
|
84
|
-
|
|
85
|
-
if (typeof value === 'undefined') {
|
|
86
|
-
value = '';
|
|
87
|
-
}
|
|
88
|
-
else if (typeof value !== 'string') {
|
|
89
|
-
value = JSON.stringify(value);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return encodeURIComponent(key) + '=' + encodeURIComponent(value);
|
|
93
|
-
}).join('&');
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function isArray(arr: any) {
|
|
97
|
-
return Object.prototype.toString.call(arr) === '[object Array]';
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
interface SpyClientInnerOption extends SpyClientOption {
|
|
101
|
-
logServer: string;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export default class SpyClient {
|
|
105
|
-
|
|
106
|
-
sample: any = {};
|
|
107
|
-
|
|
108
|
-
markCache: any = {};
|
|
109
|
-
|
|
110
|
-
option: SpyClientInnerOption;
|
|
111
|
-
|
|
112
|
-
constructor(option: SpyClientOption) {
|
|
113
|
-
if (!option.pid) {
|
|
114
|
-
throw new Error('pid is required');
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
this.option = {
|
|
118
|
-
pid: option.pid,
|
|
119
|
-
lid: option.lid,
|
|
120
|
-
check: option.check !== false,
|
|
121
|
-
sample: option.sample,
|
|
122
|
-
localCache: option.localCache,
|
|
123
|
-
logServer: option.logServer || defaultLogServer,
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
handle(logItem: any) {
|
|
128
|
-
if (!this.check(logItem)) {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
logItem = assign(
|
|
133
|
-
{
|
|
134
|
-
pid: this.option.pid,
|
|
135
|
-
lid: this.option.lid,
|
|
136
|
-
ts: Date.now(),
|
|
137
|
-
group: 'common',
|
|
138
|
-
},
|
|
139
|
-
logItem
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
if (this.option.localCache) {
|
|
143
|
-
this.option.localCache.addLog(logItem);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// 当前api设置了抽样,
|
|
147
|
-
if (typeof logItem.sample === 'number') {
|
|
148
|
-
if (Math.random() > logItem.sample) {
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
else if (typeof this.option.sample === 'number' && Math.random() > this.option.sample) { // 否则,用全局抽样
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
delete logItem.sample;
|
|
157
|
-
return logItem;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
send(data: any, post = false) {
|
|
161
|
-
let logItems: any[] = isArray(data) ? data : [data];
|
|
162
|
-
|
|
163
|
-
let postData = [];
|
|
164
|
-
for (let logItem of logItems) {
|
|
165
|
-
logItem = this.handle(logItem);
|
|
166
|
-
if (!logItem) {
|
|
167
|
-
continue;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
postData.push(logItem);
|
|
171
|
-
|
|
172
|
-
// 期望通过post方式上传日志
|
|
173
|
-
if (post) {
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const url = this.option.logServer + stringify(logItem);
|
|
178
|
-
this.request(url);
|
|
179
|
-
}
|
|
180
|
-
if (post) {
|
|
181
|
-
this.sendPost(postData);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
check(query: any): boolean {
|
|
186
|
-
if (!this.option.check) {
|
|
187
|
-
return true;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const types = ['perf', 'except', 'dist', 'count'];
|
|
191
|
-
if (types.indexOf(query.type) === -1) {
|
|
192
|
-
err('type only is one of ' + types.join(', '));
|
|
193
|
-
return false;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (query.group && query.group.length > 30) {
|
|
197
|
-
err('group length execeeds 30');
|
|
198
|
-
return false;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const simpleReg = /^[a-zA-Z0-9-_]{0,30}$/;
|
|
202
|
-
|
|
203
|
-
if (query.type === 'except') {
|
|
204
|
-
if (
|
|
205
|
-
!(typeof query.info.msg === 'string' && query.info.msg.length)
|
|
206
|
-
) {
|
|
207
|
-
err('info.msg field must be not empty and is String');
|
|
208
|
-
return false;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
else {
|
|
212
|
-
for (const infoKey of Object.keys(query.info)) {
|
|
213
|
-
if (!simpleReg.test(infoKey)) {
|
|
214
|
-
err(`info.${infoKey} is unexpected. `
|
|
215
|
-
+ 'Length must be not more than 30. '
|
|
216
|
-
+ 'Supported chars: a-zA-Z0-9-_');
|
|
217
|
-
return false;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const infoVal = query.info[infoKey];
|
|
221
|
-
if (query.type === 'dist') {
|
|
222
|
-
if (infoVal.length > 30) {
|
|
223
|
-
err(`info.${infoKey} value length execeeds 30 when type == 'dist'`);
|
|
224
|
-
return false;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
else if (typeof infoVal !== 'number') {
|
|
228
|
-
err(`info.${infoKey} value must be number`);
|
|
229
|
-
return false;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
if (query.dim) {
|
|
235
|
-
for (const dimKey of Object.keys(query.dim)) {
|
|
236
|
-
if (!simpleReg.test(dimKey)) {
|
|
237
|
-
err(`dim key [${dimKey}] is unexpected. `
|
|
238
|
-
+ 'Length must be not more than 30. '
|
|
239
|
-
+ 'Supported chars: a-zA-Z0-9-_');
|
|
240
|
-
return false;
|
|
241
|
-
}
|
|
242
|
-
const dimVal = query.dim[dimKey];
|
|
243
|
-
if (!/^[a-zA-Z0-9\-_\*\.\s\/#\+@\&\u4e00-\u9fa5]{0,30}$/.test(dimVal)) {
|
|
244
|
-
err(`dim.${dimKey} value [${dimVal}] is unexpected. `
|
|
245
|
-
+ 'Length must be not more than 30. '
|
|
246
|
-
+ 'Supported chars: a-zA-Z0-9-_*. /#+@& and Chinese');
|
|
247
|
-
return false;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
return true;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
*
|
|
257
|
-
* @param option 配置
|
|
258
|
-
*/
|
|
259
|
-
sendPerf(option: Option) {
|
|
260
|
-
this.send(assign({
|
|
261
|
-
type: 'perf',
|
|
262
|
-
}, option));
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
*
|
|
267
|
-
* @param option 错误配置项
|
|
268
|
-
*/
|
|
269
|
-
sendExcept(option: ErrorOption) {
|
|
270
|
-
this.send(assign({
|
|
271
|
-
type: 'except',
|
|
272
|
-
}, option));
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
*
|
|
277
|
-
* @param option 配置
|
|
278
|
-
*/
|
|
279
|
-
sendDist(option: Option) {
|
|
280
|
-
this.send(assign({
|
|
281
|
-
type: 'dist',
|
|
282
|
-
}, option));
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
*
|
|
287
|
-
* @param option 配置
|
|
288
|
-
*/
|
|
289
|
-
sendCount(option: Option) {
|
|
290
|
-
this.send(assign({
|
|
291
|
-
type: 'count',
|
|
292
|
-
}, option));
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
*
|
|
297
|
-
* @param e 错误实例
|
|
298
|
-
* @param option 错误配置项
|
|
299
|
-
*/
|
|
300
|
-
sendExceptForError(e: Error, option: ErrorOption) {
|
|
301
|
-
const newOpt: ErrorOption = assign({}, option);
|
|
302
|
-
newOpt.info = assign({}, option.info || {}, {
|
|
303
|
-
msg: e.message,
|
|
304
|
-
stack: e.stack,
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
this.sendExcept(newOpt);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
startMark(sign: string) {
|
|
311
|
-
this.markCache[sign] = {
|
|
312
|
-
start: Date.now(),
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
endMark(sign: string): number {
|
|
317
|
-
if (this.markCache[sign]) {
|
|
318
|
-
this.markCache[sign].total = Date.now() - this.markCache[sign].start;
|
|
319
|
-
return this.markCache[sign].total;
|
|
320
|
-
}
|
|
321
|
-
return 0;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
clearMark(sign: string) {
|
|
325
|
-
if (this.markCache[sign]) {
|
|
326
|
-
delete this.markCache[sign];
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
getAllMark() {
|
|
331
|
-
const ret: {[propName: string]: number} = {};
|
|
332
|
-
for (const sign of Object.keys(this.markCache)) {
|
|
333
|
-
ret[sign] = this.markCache[sign].total;
|
|
334
|
-
}
|
|
335
|
-
return ret;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
clearAllMark() {
|
|
339
|
-
this.markCache = {};
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// send(data, true) 也能以post发送,但是会有严格校验
|
|
343
|
-
// sendPost能以post发送,但没有校验
|
|
344
|
-
sendPost(data: any) {
|
|
345
|
-
let logItems: any[] = isArray(data) ? data : [data];
|
|
346
|
-
const first = logItems[0];
|
|
347
|
-
// 需要在页面暴漏出来pid等基本信息,方式调试查看基本信息与兼容目前的监控
|
|
348
|
-
const query = {
|
|
349
|
-
pid: first.pid,
|
|
350
|
-
type: first.type,
|
|
351
|
-
group: first.group,
|
|
352
|
-
};
|
|
353
|
-
const url = this.option.logServer + stringify(query);
|
|
354
|
-
|
|
355
|
-
this.request(url, data);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
// 有data时,意味着要用post发送请求
|
|
359
|
-
protected request(url: string, data?: any) {
|
|
360
|
-
if (!(
|
|
361
|
-
!isLtIos14
|
|
362
|
-
&& navigator
|
|
363
|
-
&& navigator.sendBeacon
|
|
364
|
-
&& navigator.sendBeacon(url, data ? JSON.stringify(data) : undefined)
|
|
365
|
-
)) {
|
|
366
|
-
if (data) {
|
|
367
|
-
this.fetch(url, data);
|
|
368
|
-
}
|
|
369
|
-
else {
|
|
370
|
-
(new Image()).src = url;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
protected fetch(url: string, data: any) {
|
|
376
|
-
if (!fetch) {
|
|
377
|
-
err('Global fetch method doesn\'t exist');
|
|
378
|
-
return;
|
|
379
|
-
}
|
|
380
|
-
fetch(url, {
|
|
381
|
-
method: 'POST',
|
|
382
|
-
credentials: 'include',
|
|
383
|
-
headers: {
|
|
384
|
-
'Content-Type': 'application/json',
|
|
385
|
-
},
|
|
386
|
-
body: JSON.stringify(data),
|
|
387
|
-
});
|
|
388
|
-
}
|
|
389
|
-
}
|
package/src/spy-client.ts
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file SpyClient
|
|
3
|
-
* @author kaivean
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import SpyClientBasic from './spy-client-basic';
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
Module,
|
|
10
|
-
SpyClientOption,
|
|
11
|
-
|
|
12
|
-
FIDCB,
|
|
13
|
-
LCPCB,
|
|
14
|
-
LayoutShiftCB,
|
|
15
|
-
PageLongtaskCB,
|
|
16
|
-
LoadLongtaskCB,
|
|
17
|
-
LCPLongtaskCB,
|
|
18
|
-
FSPLongtaskCB,
|
|
19
|
-
MemoryCB,
|
|
20
|
-
NavigatorInfoMetric,
|
|
21
|
-
ResourceCB,
|
|
22
|
-
ResourceErrorCB,
|
|
23
|
-
TimingCB,
|
|
24
|
-
TTICB,
|
|
25
|
-
TTIOption,
|
|
26
|
-
|
|
27
|
-
ResOption,
|
|
28
|
-
BigImgOption,
|
|
29
|
-
HttpResOption,
|
|
30
|
-
SlowOption,
|
|
31
|
-
} from './lib/interface';
|
|
32
|
-
|
|
33
|
-
import FID from './module/fid';
|
|
34
|
-
import LayoutShift from './module/layoutShift';
|
|
35
|
-
import LCP from './module/lcp';
|
|
36
|
-
import TTI from './module/tti';
|
|
37
|
-
import Timing from './module/timing';
|
|
38
|
-
import Resource from './module/resource';
|
|
39
|
-
import Memory from './module/memory';
|
|
40
|
-
import NavigatorInfo from './module/navigatorInfo';
|
|
41
|
-
import Longtask from './module/longtask';
|
|
42
|
-
|
|
43
|
-
export default class SpyClient extends SpyClientBasic {
|
|
44
|
-
private readonly modules: Module[] = [];
|
|
45
|
-
|
|
46
|
-
constructor(option: SpyClientOption) {
|
|
47
|
-
super(option);
|
|
48
|
-
|
|
49
|
-
this.register(new FID());
|
|
50
|
-
this.register(new LCP());
|
|
51
|
-
this.register(new LayoutShift());
|
|
52
|
-
this.register(new TTI());
|
|
53
|
-
this.register(new Timing());
|
|
54
|
-
this.register(new Resource());
|
|
55
|
-
this.register(new Memory());
|
|
56
|
-
this.register(new NavigatorInfo());
|
|
57
|
-
this.register(new Longtask());
|
|
58
|
-
|
|
59
|
-
this.visibilitychangeCB = this.visibilitychangeCB.bind(this);
|
|
60
|
-
this.load = this.load.bind(this);
|
|
61
|
-
this.leave = this.leave.bind(this);
|
|
62
|
-
|
|
63
|
-
if (document.readyState === 'complete') {
|
|
64
|
-
this.load();
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
window.addEventListener('load', this.load);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
document.addEventListener('visibilitychange', this.visibilitychangeCB);
|
|
71
|
-
window.addEventListener('beforeunload', this.leave, false);
|
|
72
|
-
window.addEventListener('unload', this.leave, false);
|
|
73
|
-
|
|
74
|
-
this.handleHead();
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
handleHead() {
|
|
78
|
-
if (this.option.localCache) {
|
|
79
|
-
const spyHead = window.__spyHead;
|
|
80
|
-
if (spyHead && spyHead.winerrors) {
|
|
81
|
-
for (let index = 0; index < spyHead.winerrors.length; index++) {
|
|
82
|
-
const obj = spyHead.winerrors[index];
|
|
83
|
-
this.option.localCache.addLog(obj);
|
|
84
|
-
}
|
|
85
|
-
// Head发送的异常,也保存一份到本地,主要是JS错误和资源加载异常
|
|
86
|
-
spyHead.interceptor = (obj: any) => {
|
|
87
|
-
this.option.localCache.addLog(obj);
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
listenFID(cb: FIDCB) {
|
|
94
|
-
this.invoke('listenFID', cb as any);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
listenLayoutShift(cb: LayoutShiftCB) {
|
|
98
|
-
this.invoke('listenLayoutShift', cb as any);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
listenLCP(cb: LCPCB) {
|
|
102
|
-
this.invoke('listenLCP', cb as any);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
listenFSPLongTask(cb: FSPLongtaskCB) {
|
|
106
|
-
this.invoke('listenFSPLongTask', cb as any);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
listenLCPLongTask(cb: LCPLongtaskCB) {
|
|
110
|
-
this.invoke('listenLCPLongTask', cb as any);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
listenLoadLongTask(cb: LoadLongtaskCB) {
|
|
114
|
-
this.invoke('listenLoadLongTask', cb as any);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
listenPageLongTask(cb: PageLongtaskCB) {
|
|
118
|
-
this.invoke('listenPageLongTask', cb as any);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
listenMemory(cb: MemoryCB) {
|
|
122
|
-
this.invoke('listenMemory', cb as any);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
getNavigatorInfo(): NavigatorInfoMetric {
|
|
126
|
-
return this.invoke('getNavigatorInfo');
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
listenResource(cb: ResourceCB, option?: ResOption) {
|
|
130
|
-
this.invoke('listenResource', cb as any, option);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
listenBigImg(cb: ResourceErrorCB, option?: BigImgOption) {
|
|
134
|
-
this.invoke('listenBigImg', cb as any, option);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
listenHttpResource(cb: ResourceErrorCB, option?: HttpResOption) {
|
|
138
|
-
this.invoke('listenHttpResource', cb as any, option);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
listenSlowResource(cb: ResourceErrorCB, option?: SlowOption) {
|
|
142
|
-
this.invoke('listenSlowResource', cb as any, option);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
listenTiming(cb: TimingCB) {
|
|
146
|
-
this.invoke('listenTiming', cb as any);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
listenTTI(cb: TTICB, option?: TTIOption) {
|
|
150
|
-
this.invoke('listenTTI', cb as any, option as any);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
invoke(name: string, cb?: any, option?: any) {
|
|
154
|
-
for (let index = 0; index < this.modules.length; index++) {
|
|
155
|
-
const mod = this.modules[index];
|
|
156
|
-
if (typeof (mod as any)[name] === 'function') {
|
|
157
|
-
return (mod as any)[name].apply(mod, [cb, option]);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
console.error('no method', name);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
register(mod: Module) {
|
|
164
|
-
this.modules.push(mod);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
load() {
|
|
168
|
-
for (let index = 0; index < this.modules.length; index++) {
|
|
169
|
-
const mod = this.modules[index];
|
|
170
|
-
mod.load && mod.load();
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
leave() {
|
|
175
|
-
for (let index = 0; index < this.modules.length; index++) {
|
|
176
|
-
const mod = this.modules[index];
|
|
177
|
-
mod.leave && mod.leave();
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
destroy() {
|
|
182
|
-
for (let index = 0; index < this.modules.length; index++) {
|
|
183
|
-
const mod = this.modules[index];
|
|
184
|
-
mod.destroy && mod.destroy();
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
document.removeEventListener('visibilitychange', this.visibilitychangeCB);
|
|
188
|
-
window.removeEventListener('load', this.load);
|
|
189
|
-
window.removeEventListener('beforeunload', this.leave);
|
|
190
|
-
window.removeEventListener('unload', this.destroy);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
private visibilitychangeCB() {
|
|
194
|
-
if (document.visibilityState === 'hidden') {
|
|
195
|
-
this.leave();
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
package/src/spy-head.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file SpyClient
|
|
3
|
-
* @author kaivean
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import * as error from './head/error';
|
|
7
|
-
import * as observer from './head/observer';
|
|
8
|
-
import * as whitescreen from './head/whitescreen';
|
|
9
|
-
import spyHead from './head/base';
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
SpyHeadConf,
|
|
13
|
-
} from './lib/spyHeadInterface';
|
|
14
|
-
|
|
15
|
-
spyHead.init = function (conf: SpyHeadConf) {
|
|
16
|
-
if (!conf.logServer) {
|
|
17
|
-
conf.logServer = 'https://sp1.baidu.com/5b1ZeDe5KgQFm2e88IuM_a/mwb2.gif';
|
|
18
|
-
}
|
|
19
|
-
this.conf = conf;
|
|
20
|
-
|
|
21
|
-
error.init(conf);
|
|
22
|
-
observer.init();
|
|
23
|
-
whitescreen.init(conf);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
// 兼容全局变量定义的初始化方式
|
|
27
|
-
if (window.__spyclientConf) {
|
|
28
|
-
spyHead.init(window.__spyclientConf);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export default spyHead;
|