monitor-track 1.10.0
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/CHANGELOG.md +31 -0
- package/README.md +101 -0
- package/dist/CHANGELOG.md +21 -0
- package/dist/README.md +101 -0
- package/dist/cjs/config/global.d.ts +17 -0
- package/dist/cjs/config/index.d.ts +33 -0
- package/dist/cjs/constant.d.ts +2 -0
- package/dist/cjs/handlers/error.d.ts +23 -0
- package/dist/cjs/handlers/index.d.ts +3 -0
- package/dist/cjs/handlers/pv.d.ts +24 -0
- package/dist/cjs/handlers/user-activity.d.ts +9 -0
- package/dist/cjs/index.d.ts +30 -0
- package/dist/cjs/index.js +1485 -0
- package/dist/cjs/main.d.ts +1 -0
- package/dist/cjs/reporter.d.ts +198 -0
- package/dist/cjs/types/config.d.ts +59 -0
- package/dist/cjs/types/global.d.ts +70 -0
- package/dist/cjs/types/index.d.ts +189 -0
- package/dist/cjs/utils/index.d.ts +45 -0
- package/dist/esm/_virtual/_tslib.js +26 -0
- package/dist/esm/config/global.d.ts +17 -0
- package/dist/esm/config/global.js +271 -0
- package/dist/esm/config/index.d.ts +33 -0
- package/dist/esm/config/index.js +32 -0
- package/dist/esm/constant.d.ts +2 -0
- package/dist/esm/constant.js +4 -0
- package/dist/esm/handlers/error.d.ts +23 -0
- package/dist/esm/handlers/error.js +181 -0
- package/dist/esm/handlers/index.d.ts +3 -0
- package/dist/esm/handlers/pv.d.ts +24 -0
- package/dist/esm/handlers/pv.js +99 -0
- package/dist/esm/handlers/user-activity.d.ts +9 -0
- package/dist/esm/handlers/user-activity.js +66 -0
- package/dist/esm/index.d.ts +30 -0
- package/dist/esm/index.js +115 -0
- package/dist/esm/main.d.ts +1 -0
- package/dist/esm/package.json.js +3 -0
- package/dist/esm/reporter.d.ts +198 -0
- package/dist/esm/reporter.js +359 -0
- package/dist/esm/types/config.d.ts +59 -0
- package/dist/esm/types/global.d.ts +70 -0
- package/dist/esm/types/index.d.ts +189 -0
- package/dist/esm/utils/index.d.ts +45 -0
- package/dist/esm/utils/index.js +354 -0
- package/dist/index.js +1534 -0
- package/dist/package.json +41 -0
- package/package.json +42 -0
- package/rollup.config.js +66 -0
- package/scripts/cp.js +11 -0
- package/src/config/global.ts +309 -0
- package/src/config/index.ts +53 -0
- package/src/constant.ts +2 -0
- package/src/handlers/error.ts +187 -0
- package/src/handlers/index.ts +3 -0
- package/src/handlers/pv.ts +124 -0
- package/src/handlers/user-activity.ts +69 -0
- package/src/index.ts +127 -0
- package/src/main.ts +8 -0
- package/src/reporter.ts +372 -0
- package/src/types/config.ts +58 -0
- package/src/types/global.ts +73 -0
- package/src/types/index.ts +227 -0
- package/src/typing.d.ts +15 -0
- package/src/utils/index.ts +371 -0
- package/tsconfig.esm.json +14 -0
package/src/reporter.ts
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
2
|
+
import { IReport } from './types/global';
|
|
3
|
+
import { serialize } from './utils';
|
|
4
|
+
import { getFullScreenShoot } from './handlers/error';
|
|
5
|
+
import { Config } from './config';
|
|
6
|
+
|
|
7
|
+
/** 上报数据映射 */
|
|
8
|
+
export const reportMap = {
|
|
9
|
+
/** SDK 版本 */
|
|
10
|
+
version: '_v',
|
|
11
|
+
/** 项目ID */
|
|
12
|
+
projectID: 'pid',
|
|
13
|
+
/** location.host */
|
|
14
|
+
host: 'host',
|
|
15
|
+
/** 用户uuid */
|
|
16
|
+
uuid: '_id',
|
|
17
|
+
/** 上报日志的时间戳 */
|
|
18
|
+
time: 'time',
|
|
19
|
+
/** 源页面 */
|
|
20
|
+
originPage: 'o',
|
|
21
|
+
/** 当前页面 */
|
|
22
|
+
page: 'p',
|
|
23
|
+
/** 自定义payload */
|
|
24
|
+
customPayload: 'cP',
|
|
25
|
+
/** 信息类型 */
|
|
26
|
+
type: 't',
|
|
27
|
+
/** viewport的宽高 */
|
|
28
|
+
viewport: 'vp',
|
|
29
|
+
/** 屏幕宽高 */
|
|
30
|
+
screen: 'sc',
|
|
31
|
+
/** 页面title */
|
|
32
|
+
pageTitle: 'pt',
|
|
33
|
+
/** 页面referrer */
|
|
34
|
+
referrer: 'ref',
|
|
35
|
+
/** 页面编码 */
|
|
36
|
+
charset: 'char',
|
|
37
|
+
/** language */
|
|
38
|
+
language: 'lan',
|
|
39
|
+
/** vendor, 浏览器厂商 */
|
|
40
|
+
navigatorVendor: 'nV',
|
|
41
|
+
/** 网络连接类型 */
|
|
42
|
+
connectionType: 'cT',
|
|
43
|
+
/** 浏览器名称 */
|
|
44
|
+
browserName: 'bN',
|
|
45
|
+
/** 浏览器版本 */
|
|
46
|
+
browserVersion: 'bV',
|
|
47
|
+
/** 浏览器引擎名称 */
|
|
48
|
+
engineName: 'enN',
|
|
49
|
+
/** 浏览器引擎版本 */
|
|
50
|
+
engineVersion: 'enV',
|
|
51
|
+
/** 操作系统名称 */
|
|
52
|
+
osName: 'osN',
|
|
53
|
+
/** 操作系统版本 */
|
|
54
|
+
osVersion: 'osV',
|
|
55
|
+
pv: {
|
|
56
|
+
/** 子类型 */
|
|
57
|
+
subType: 'suT',
|
|
58
|
+
/** 停留时间 */
|
|
59
|
+
stayTime: 'sT',
|
|
60
|
+
},
|
|
61
|
+
error: {
|
|
62
|
+
/** 子类型 */
|
|
63
|
+
subType: 'suT',
|
|
64
|
+
/** 错误行 */
|
|
65
|
+
line: 'line',
|
|
66
|
+
/** 错误列 */
|
|
67
|
+
column: 'col',
|
|
68
|
+
/** 错误信息 */
|
|
69
|
+
message: 'msg',
|
|
70
|
+
/** 错误文件 */
|
|
71
|
+
filename: 'fil',
|
|
72
|
+
/** 错误函数名 */
|
|
73
|
+
functionName: 'fn',
|
|
74
|
+
/** 错误栈信息 */
|
|
75
|
+
stack: '_st',
|
|
76
|
+
/** 错误帧 */
|
|
77
|
+
stackFrame: '_sf',
|
|
78
|
+
/** 视频录制数据 */
|
|
79
|
+
events: 'evt',
|
|
80
|
+
/** 页面截图 */
|
|
81
|
+
picture: 'pic',
|
|
82
|
+
},
|
|
83
|
+
ua: {
|
|
84
|
+
/** 子类型 */
|
|
85
|
+
subType: 'suT',
|
|
86
|
+
/** x轴坐标 */
|
|
87
|
+
x: 'x',
|
|
88
|
+
/** y轴坐标 */
|
|
89
|
+
y: 'y',
|
|
90
|
+
/** 元素路径 */
|
|
91
|
+
path: 'path',
|
|
92
|
+
},
|
|
93
|
+
/** 性能数据 */
|
|
94
|
+
perf: {
|
|
95
|
+
navigation: {
|
|
96
|
+
/**
|
|
97
|
+
*一个无符号短整型,表示是如何导航到这个页面的。可能的值如下:
|
|
98
|
+
TYPE_NAVIGATE (0)
|
|
99
|
+
当前页面是通过点击链接,书签和表单提交,或者脚本操作,或者在url中直接输入地址,type值为0
|
|
100
|
+
TYPE_RELOAD (1)
|
|
101
|
+
点击刷新页面按钮或者通过Location.reload()方法显示的页面,type值为1
|
|
102
|
+
The page was accessed by clicking the Reload button or via the Location.reload() method.
|
|
103
|
+
TYPE_BACK_FORWARD (2)
|
|
104
|
+
页面通过历史记录和前进后退访问时。type值为2
|
|
105
|
+
TYPE_RESERVED (255)
|
|
106
|
+
任何其他方式,type值为255
|
|
107
|
+
*/
|
|
108
|
+
type: 't',
|
|
109
|
+
/** 无符号短整型,表示在到达这个页面之前重定向了多少次。 */
|
|
110
|
+
redirectCount: 'rc',
|
|
111
|
+
},
|
|
112
|
+
memory: {
|
|
113
|
+
/** 上下文内可用堆的最大体积,以字节计算。 */
|
|
114
|
+
jsHeapSizeLimit: 'hsl',
|
|
115
|
+
/** 已分配的堆体积,以字节计算。 */
|
|
116
|
+
totalJSHeapSize: 'ths',
|
|
117
|
+
/** 当前 JS 堆活跃段(segment)的体积,以字节计算。 */
|
|
118
|
+
usedJSHeapSize: 'uhs',
|
|
119
|
+
},
|
|
120
|
+
/** 返回性能测量开始时的时间的高精度时间戳。 */
|
|
121
|
+
timeOrigin: 'to',
|
|
122
|
+
timing: {
|
|
123
|
+
/** 是一个无符号long long 型的毫秒数,返回浏览器与服务器之间的连接建立时的Unix毫秒时间戳。如果建立的是持久连接,则返回值等同于fetchStart属性的值。连接建立指的是所有握手和认证过程全部结束。 */
|
|
124
|
+
connectEnd: 'ce',
|
|
125
|
+
/** 是一个无符号long long 型的毫秒数,返回HTTP请求开始向服务器发送时的Unix毫秒时间戳。如果使用持久连接(persistent connection),则返回值等同于fetchStart属性的值 */
|
|
126
|
+
connectStart: 'cs',
|
|
127
|
+
/** 是一个无符号long long 型的毫秒数,返回当前文档解析完成,即Document.readyState 变为 'complete'且相对应的readystatechange (en-US) 被触发时的Unix毫秒时间戳。 */
|
|
128
|
+
domComplete: 'dc',
|
|
129
|
+
/** 是一个无符号long long 型的毫秒数,返回当所有需要立即执行的脚本已经被执行(不论执行顺序)时的Unix毫秒时间戳。 */
|
|
130
|
+
domContentLoadedEventEnd: 'scLee',
|
|
131
|
+
/** 是一个无符号long long 型的毫秒数,返回当解析器发送DOMContentLoaded (en-US) 事件,即所有需要被执行的脚本已经被解析时的Unix毫秒时间戳。 */
|
|
132
|
+
domContentLoadedEventStart: 'dcLes',
|
|
133
|
+
/** 是一个无符号long long 型的毫秒数,返回当前网页DOM结构结束解析、开始加载内嵌资源时(即Document.readyState属性变为“interactive”、相应的readystatechange (en-US)事件触发时)的Unix毫秒时间戳。 */
|
|
134
|
+
domInteractive: 'di',
|
|
135
|
+
/** 是一个无符号long long 型的毫秒数,返回当前网页DOM结构开始解析时(即Document.readyState属性变为“loading”、相应的 readystatechange (en-US)事件触发时)的Unix毫秒时间戳。 */
|
|
136
|
+
domLoading: 'dl',
|
|
137
|
+
/** 是一个无符号long long 型的毫秒数,表征了域名查询结束的UNIX时间戳。如果使用了持续连接(persistent connection),或者这个信息存储到了缓存或者本地资源上,这个值将和 PerformanceTiming.fetchStart一致。 */
|
|
138
|
+
domainLookupEnd: 'dle',
|
|
139
|
+
/** 是一个无符号long long 型的毫秒数,表征了域名查询开始的UNIX时间戳。如果使用了持续连接(persistent connection),或者这个信息存储到了缓存或者本地资源上,这个值将和 PerformanceTiming.fetchStart一致。 */
|
|
140
|
+
domainLookupStart: 'dls',
|
|
141
|
+
/** 是一个无符号long long 型的毫秒数,表征了浏览器准备好使用HTTP请求来获取(fetch)文档的UNIX时间戳。这个时间点会在检查任何应用缓存之前。 */
|
|
142
|
+
fetchStart: 'fs',
|
|
143
|
+
/** 是一个无符号long long 型的毫秒数,返回当load (en-US)事件结束,即加载事件完成时的Unix毫秒时间戳。如果这个事件还未被发送,或者尚未完成,它的值将会是0. */
|
|
144
|
+
loadEventEnd: 'lee',
|
|
145
|
+
/** 是一个无符号long long 型的毫秒数,返回该文档下,load (en-US)事件被发送时的Unix毫秒时间戳。如果这个事件还未被发送,它的值将会是0。 */
|
|
146
|
+
loadEventStart: 'les',
|
|
147
|
+
/** 是一个无符号long long 型的毫秒数,表征了从同一个浏览器上下文的上一个文档卸载(unload)结束时的UNIX时间戳。如果没有上一个文档,这个值会和PerformanceTiming.fetchStart相同 */
|
|
148
|
+
navigationStart: 'ns',
|
|
149
|
+
/** 是一个无符号long long 型的毫秒数,表征了最后一个HTTP重定向完成时(也就是说是HTTP响应的最后一个比特直接被收到的时间)的UNIX时间戳。如果没有重定向,或者重定向中的一个不同源,这个值会返回0. */
|
|
150
|
+
redirectEnd: 're',
|
|
151
|
+
/** 是一个无符号long long 型的毫秒数,表征了第一个HTTP重定向开始时的UNIX时间戳。如果没有重定向,或者重定向中的一个不同源,这个值会返回0. */
|
|
152
|
+
redirectStart: 'redS',
|
|
153
|
+
/** 是一个无符号long long 型的毫秒数,返回浏览器向服务器发出HTTP请求时(或开始读取本地缓存时)的Unix毫秒时间戳。 */
|
|
154
|
+
requestStart: 'reqS',
|
|
155
|
+
/** 是一个无符号long long 型的毫秒数,返回浏览器从服务器收到(或从本地缓存读取,或从本地资源读取)最后一个字节时(如果在此之前HTTP连接已经关闭,则返回关闭时)的Unix毫秒时间戳。 */
|
|
156
|
+
responseEnd: 'resE',
|
|
157
|
+
/** 是一个无符号long long 型的毫秒数,返回浏览器从服务器收到(或从本地缓存读取)第一个字节时的Unix毫秒时间戳。如果传输层在开始请求之后失败并且连接被重开,该属性将会被数制成新的请求的相对应的发起时间。 */
|
|
158
|
+
responseStart: 'resS',
|
|
159
|
+
/** 是一个无符号long long 型的毫秒数,返回浏览器与服务器开始安全链接的握手时的Unix毫秒时间戳。如果当前网页不要求安全连接,则返回0。 */
|
|
160
|
+
secureConnectionStart: 'scs',
|
|
161
|
+
/** 是一个无符号long long 型的毫秒数,表征了unload (en-US)事件处理完成时的UNIX时间戳。如果没有上一个文档,or if the previous document, or one of the needed redirects, is not of the same origin, 这个值会返回0. */
|
|
162
|
+
unloadEventEnd: 'uee',
|
|
163
|
+
/** 是一个无符号long long 型的毫秒数,表征了unload (en-US)事件抛出时的UNIX时间戳。如果没有上一个文档,or if the previous document, or one of the needed redirects, is not of the same origin, 这个值会返回0. */
|
|
164
|
+
unloadEventStart: 'ees',
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
/** api请求相关 */
|
|
168
|
+
req: {
|
|
169
|
+
/** 请求类型,xhr或fetch */
|
|
170
|
+
requestType: 'rT',
|
|
171
|
+
/** 请求地址 */
|
|
172
|
+
responseURL: 'url',
|
|
173
|
+
/** 请求结果 */
|
|
174
|
+
status: 'stat',
|
|
175
|
+
/** 请求耗时 */
|
|
176
|
+
loadTime: 'lT',
|
|
177
|
+
/** 请求状态 */
|
|
178
|
+
statusText: 'sT',
|
|
179
|
+
/** 上报原因, slow或failed */
|
|
180
|
+
reason: 're',
|
|
181
|
+
/** 上报时带上的详细信息 */
|
|
182
|
+
detail: 'de',
|
|
183
|
+
},
|
|
184
|
+
vD: {
|
|
185
|
+
/** 埋点名称 */
|
|
186
|
+
trackName: 'tN',
|
|
187
|
+
/** 埋点参数 */
|
|
188
|
+
params: 'params',
|
|
189
|
+
},
|
|
190
|
+
manualReport: 'mR',
|
|
191
|
+
lifeCycleId: 'li',
|
|
192
|
+
sessionId: 'sI',
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
type IRest = { p: string; pid: string; host: string; bN: string; pt: string };
|
|
196
|
+
|
|
197
|
+
const xhrFunc = (
|
|
198
|
+
filename: string,
|
|
199
|
+
userId: string,
|
|
200
|
+
asyncUpdateId: string,
|
|
201
|
+
file: Blob | File,
|
|
202
|
+
res: Function,
|
|
203
|
+
callback: (result: string) => void,
|
|
204
|
+
rest: IRest,
|
|
205
|
+
) => {
|
|
206
|
+
const formData = new FormData();
|
|
207
|
+
for (const i in rest) {
|
|
208
|
+
if (Object.prototype.hasOwnProperty.call(rest, i)) {
|
|
209
|
+
formData.append(i, rest[i as keyof IRest]);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
formData.append('filename', filename);
|
|
213
|
+
formData.append('asyncUpdateId', asyncUpdateId); //用于上传到oss后异步更新到db的id
|
|
214
|
+
formData.append('userId', userId);
|
|
215
|
+
formData.append('files', file);
|
|
216
|
+
const xhr = new XMLHttpRequest();
|
|
217
|
+
xhr.addEventListener('error', () => res(), false);
|
|
218
|
+
xhr.open('POST', Config.reportUrl);
|
|
219
|
+
xhr.onreadystatechange = function () {
|
|
220
|
+
if (xhr.readyState === 4) {
|
|
221
|
+
if (xhr.status === 200) {
|
|
222
|
+
try {
|
|
223
|
+
const response = xhr.responseText;
|
|
224
|
+
const resp = JSON.parse(response);
|
|
225
|
+
callback(resp.result?.response);
|
|
226
|
+
} catch (_err) {
|
|
227
|
+
//
|
|
228
|
+
}
|
|
229
|
+
res();
|
|
230
|
+
} else {
|
|
231
|
+
res();
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
xhr.send(formData);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
const ERROR_MESSAGE_MAP: { [key: string]: boolean } = {};
|
|
239
|
+
function reportFunc(data: IReport) {
|
|
240
|
+
const payload: { [k: string]: any } = convertToSchema(data, reportMap);
|
|
241
|
+
payload.time = new Date().getTime(); // 设置上报时间
|
|
242
|
+
let picturePromise = Promise.resolve();
|
|
243
|
+
let hasErrorEvent = false;
|
|
244
|
+
const filename = uuidv4();
|
|
245
|
+
if (data.type === 'error') {
|
|
246
|
+
let message = data.error?.message || 'default';
|
|
247
|
+
if (data.error?.subType === 'resource') {
|
|
248
|
+
message = 'resource';
|
|
249
|
+
}
|
|
250
|
+
if (ERROR_MESSAGE_MAP[message]) {
|
|
251
|
+
//
|
|
252
|
+
} else {
|
|
253
|
+
ERROR_MESSAGE_MAP[message] = true;
|
|
254
|
+
setTimeout(() => {
|
|
255
|
+
//节流效果,每隔3秒上报一次重复的错误录像和错误截图
|
|
256
|
+
delete ERROR_MESSAGE_MAP[message];
|
|
257
|
+
}, 3000);
|
|
258
|
+
const { p, pid, host, bN, pt } = payload;
|
|
259
|
+
if (data.error?.events) {
|
|
260
|
+
hasErrorEvent = true;
|
|
261
|
+
const errorEvent = data.error.events;
|
|
262
|
+
const delayTime = Math.ceil(Math.random() * 10000);
|
|
263
|
+
setTimeout(
|
|
264
|
+
() => {
|
|
265
|
+
const blob = new Blob([errorEvent], { type: 'text/json' });
|
|
266
|
+
return new Promise((res) => {
|
|
267
|
+
xhrFunc(`${filename}.json`, data.uuid, filename, blob, res, () => {}, { p, pid, host, bN, pt });
|
|
268
|
+
});
|
|
269
|
+
},
|
|
270
|
+
delayTime < 3500 ? 3500 : delayTime,
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
picturePromise = getFullScreenShoot(filename)
|
|
274
|
+
.then((file: File) => {
|
|
275
|
+
return new Promise((res) => {
|
|
276
|
+
xhrFunc(
|
|
277
|
+
file.name,
|
|
278
|
+
data.uuid,
|
|
279
|
+
filename,
|
|
280
|
+
file,
|
|
281
|
+
res,
|
|
282
|
+
(result: string) => {
|
|
283
|
+
payload.error.pic = result;
|
|
284
|
+
},
|
|
285
|
+
{ p, pid, host, bN, pt },
|
|
286
|
+
);
|
|
287
|
+
}) as Promise<void>;
|
|
288
|
+
})
|
|
289
|
+
.catch((err) => {
|
|
290
|
+
payload.error.picError = err?.stack || err?.toString();
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return picturePromise
|
|
295
|
+
.then(() => {
|
|
296
|
+
if (payload.error?.evt) delete payload.error!.evt;
|
|
297
|
+
if (window && window.navigator && typeof window.navigator.sendBeacon === 'function') {
|
|
298
|
+
const formData = new FormData();
|
|
299
|
+
Object.keys(payload).forEach((key) => {
|
|
300
|
+
let value = payload[key];
|
|
301
|
+
if (value !== null && value !== undefined) {
|
|
302
|
+
if (typeof value === 'object') {
|
|
303
|
+
value = JSON.stringify(value);
|
|
304
|
+
}
|
|
305
|
+
formData.append(key, value);
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
//eventErrorFilename,将错误录像的文件名附在错误上报的埋点里,便于将错误录像上报回调地址异步的更新到db
|
|
309
|
+
if (hasErrorEvent) formData.append('eef', filename);
|
|
310
|
+
window.navigator.sendBeacon(Config.reportUrl, formData);
|
|
311
|
+
} else {
|
|
312
|
+
if (hasErrorEvent) payload.eef = filename;
|
|
313
|
+
new Image().src = `${Config.reportUrl}?${serialize(payload)}`;
|
|
314
|
+
}
|
|
315
|
+
})
|
|
316
|
+
.catch((_err) => {
|
|
317
|
+
//
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// 上报
|
|
322
|
+
export function report(data: IReport) {
|
|
323
|
+
return new Promise((res) => {
|
|
324
|
+
//在帧的空闲时间上报
|
|
325
|
+
const dataCopy = JSON.parse(JSON.stringify(data));
|
|
326
|
+
if (typeof window.requestIdleCallback === 'function') {
|
|
327
|
+
window.requestIdleCallback(() => reportFunc(dataCopy).then(res), { timeout: 2000 });
|
|
328
|
+
} else {
|
|
329
|
+
setTimeout(() => reportFunc(dataCopy).then(res), 0);
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* @description 将数据转换成最终提交的数据,主要目的是简化数据的key的长度,从而降低荷载大小
|
|
336
|
+
* @param data 要转换的数据
|
|
337
|
+
* @param map 要转换的数据的字段映射
|
|
338
|
+
* @param redundancyData 冗余数据
|
|
339
|
+
*/
|
|
340
|
+
export function convertToSchema(data: IReport, map: { [K: string]: any }, redundancyData?: object) {
|
|
341
|
+
const reportData: any = {};
|
|
342
|
+
|
|
343
|
+
if (redundancyData) {
|
|
344
|
+
map = { ...map, ...redundancyData };
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
for (const result of Object.entries(map)) {
|
|
348
|
+
const [key, mapKey] = result as [keyof IReport, any];
|
|
349
|
+
if (key === 'manualReport') {
|
|
350
|
+
reportData[mapKey] = data[key];
|
|
351
|
+
} else {
|
|
352
|
+
//字段值为数组的场景,直接转换
|
|
353
|
+
if (typeof data[key] === 'object' && !Array.isArray(data[key])) {
|
|
354
|
+
if (data[key]) {
|
|
355
|
+
if (redundancyData && Object.prototype.hasOwnProperty.call(redundancyData, key)) {
|
|
356
|
+
reportData[key] = data[key];
|
|
357
|
+
} else {
|
|
358
|
+
reportData[key] = convertToSchema(data[key] as any, map[key]);
|
|
359
|
+
}
|
|
360
|
+
} else {
|
|
361
|
+
reportData[key] = data[key];
|
|
362
|
+
}
|
|
363
|
+
} else {
|
|
364
|
+
// 排除undefined
|
|
365
|
+
if (data[key] !== undefined) {
|
|
366
|
+
reportData[mapKey] = data[key];
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return reportData;
|
|
372
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description 配置项接口
|
|
3
|
+
*/
|
|
4
|
+
export interface IConfig {
|
|
5
|
+
/** 开启日志收集 */
|
|
6
|
+
enable?: boolean;
|
|
7
|
+
/** 上报地址,后台地址 */
|
|
8
|
+
reportUrl: string;
|
|
9
|
+
/** 项目ID, 由监控平台后台管理系统创建项目时生成 */
|
|
10
|
+
projectID: string;
|
|
11
|
+
/** 是否为单页面应用,主要区别页面性能,及路由切换行为 */
|
|
12
|
+
spa?: boolean;
|
|
13
|
+
/** 路由是否为hash模式 */
|
|
14
|
+
hash?: boolean;
|
|
15
|
+
/** 启用行为上报 */
|
|
16
|
+
enableBehavior?: boolean;
|
|
17
|
+
/** 启用异常信息上报 */
|
|
18
|
+
enableError?: boolean;
|
|
19
|
+
// 最长上报数据长度
|
|
20
|
+
maxLength?: number;
|
|
21
|
+
/** 忽略上报的信息 */
|
|
22
|
+
ignore?: {
|
|
23
|
+
/** 忽略的url */
|
|
24
|
+
urls?: string[];
|
|
25
|
+
/** 忽略的异常信息 */
|
|
26
|
+
errors?: Array<string | { regExp: boolean; input: string }>;
|
|
27
|
+
/** 忽略的接口 */
|
|
28
|
+
apis?: string[];
|
|
29
|
+
};
|
|
30
|
+
/** 自定义payload */
|
|
31
|
+
customPayload?: string;
|
|
32
|
+
/** 上报 xhr 请求超过指定时间的请求地址 */
|
|
33
|
+
XMLHttpRequestTimeout?: number;
|
|
34
|
+
/** 启用可视化埋点 */
|
|
35
|
+
enableVisualTrack?: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
type IParams = {
|
|
39
|
+
name: string;
|
|
40
|
+
value: string;
|
|
41
|
+
disabled: boolean;
|
|
42
|
+
elementXPath: string;
|
|
43
|
+
id: string;
|
|
44
|
+
errorMsg?: boolean;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export type IListData = {
|
|
48
|
+
trackType: 'click' | 'mount';
|
|
49
|
+
trackElementXPath: string;
|
|
50
|
+
trackNameInfo: {
|
|
51
|
+
name: string;
|
|
52
|
+
disabled: boolean;
|
|
53
|
+
elementXPath: string;
|
|
54
|
+
};
|
|
55
|
+
params: IParams[];
|
|
56
|
+
id: string;
|
|
57
|
+
valid: boolean;
|
|
58
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { IErrorInfo, INavigator, IPv, IUserActivity, IPerformance } from '.';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @description 上报信息
|
|
5
|
+
*/
|
|
6
|
+
export interface IReport extends INavigator {
|
|
7
|
+
/** SDK 版本 */
|
|
8
|
+
version: string;
|
|
9
|
+
/** 项目ID */
|
|
10
|
+
projectID: string;
|
|
11
|
+
/** location.host */
|
|
12
|
+
host: string;
|
|
13
|
+
/** 用户uuid */
|
|
14
|
+
uuid: string;
|
|
15
|
+
/** 源页面 */
|
|
16
|
+
originPage: string;
|
|
17
|
+
/** 当前页面 */
|
|
18
|
+
page: string;
|
|
19
|
+
/** 上报日志的时间戳 */
|
|
20
|
+
time: number;
|
|
21
|
+
/** 自定义payload */
|
|
22
|
+
customPayload?: string;
|
|
23
|
+
/** 信息类型 */
|
|
24
|
+
type: IType;
|
|
25
|
+
/** viewport的宽高 */
|
|
26
|
+
viewport: string;
|
|
27
|
+
/** 屏幕宽高 */
|
|
28
|
+
screen: string;
|
|
29
|
+
/** 页面title */
|
|
30
|
+
pageTitle: string;
|
|
31
|
+
/** 页面referrer */
|
|
32
|
+
referrer: string;
|
|
33
|
+
/** 页面编码 */
|
|
34
|
+
charset: string;
|
|
35
|
+
/** dpr */
|
|
36
|
+
dpr: number;
|
|
37
|
+
pv: IPv | null;
|
|
38
|
+
error: IErrorInfo | null;
|
|
39
|
+
ua: IUserActivity | null;
|
|
40
|
+
perf: IPerformance | null;
|
|
41
|
+
vD?: {
|
|
42
|
+
/** 埋点名称 */
|
|
43
|
+
trackName: string;
|
|
44
|
+
params: {
|
|
45
|
+
/** 参数名称 */
|
|
46
|
+
name: string;
|
|
47
|
+
/** 参数值 */
|
|
48
|
+
value: string;
|
|
49
|
+
}[];
|
|
50
|
+
};
|
|
51
|
+
manualReport?: object;
|
|
52
|
+
lifeCycleId: string;
|
|
53
|
+
sessionId: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @description 上报信息类型
|
|
58
|
+
* @type pv 路由变化
|
|
59
|
+
* @type error 资源加载错误及js错误相关
|
|
60
|
+
* @type ua 用户行为
|
|
61
|
+
* @type api 接口
|
|
62
|
+
* @type per 性能
|
|
63
|
+
* @type init 初始化时上报。因为初始化时,页面已经触发过路由,所以这次上报应
|
|
64
|
+
* 应当算作一次pv,但是又因为是初始化引起的,取单独类型进行区分
|
|
65
|
+
* @type request xhr请求超过阈值时的上报
|
|
66
|
+
* @type visual 可视化埋点上报
|
|
67
|
+
* @type manual 手动上报
|
|
68
|
+
*/
|
|
69
|
+
export type IType = 'pv' | 'error' | 'ua' | 'api' | 'per' | 'init' | 'request' | 'visual' | 'manual';
|
|
70
|
+
|
|
71
|
+
export interface Navigator {
|
|
72
|
+
connection: any;
|
|
73
|
+
}
|