keeson-web-report-sdk 1.1.5 → 1.1.6
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/package.json +6 -6
- package/README.md +0 -37
- package/src/index.js +0 -323
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "keeson-web-report-sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"description": "for web/h5",
|
|
5
|
-
"main": "
|
|
6
|
-
"module": "
|
|
5
|
+
"main": "bundle.min.js",
|
|
6
|
+
"module": "bundle.esm.js",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": {
|
|
9
|
-
"require": "./
|
|
10
|
-
"import": "./
|
|
11
|
-
"browser": "./
|
|
9
|
+
"require": "./bundle.cjs.js",
|
|
10
|
+
"import": "./bundle.esm.js",
|
|
11
|
+
"browser": "./bundle.min.js"
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
package/README.md
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
```javascript
|
|
2
|
-
export const REPORT_TYPE = {
|
|
3
|
-
ERROR: "error",
|
|
4
|
-
PERFORMANCE: "performance",
|
|
5
|
-
REQUEST: "request",
|
|
6
|
-
USER: "user",
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export const ERROR_TYPE = {
|
|
10
|
-
MAIN: "main",
|
|
11
|
-
RESOURCE_ERROR: "resourceError",
|
|
12
|
-
PROMISE_REJECTION: "PromiseRejection",
|
|
13
|
-
VUE_ERROR: "VueError",
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export const REQUEST_ERROR_TYPE = {
|
|
17
|
-
ERROR: "error",
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export const PERFORMANCE_TYPE = {
|
|
21
|
-
LOADED: "loaded",
|
|
22
|
-
FP: "paint",
|
|
23
|
-
FCP: "first-contentful-paint",
|
|
24
|
-
LCP: "largest-contentful-paint",
|
|
25
|
-
CLS: "layout-shift",
|
|
26
|
-
FID: "first-input",
|
|
27
|
-
LONGTASK: "longTask",
|
|
28
|
-
RESOURCE: "resource",
|
|
29
|
-
PAGE_RESOURCE: "pageResource",
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export const USER_TYPE = {
|
|
33
|
-
LOCATION_CHANGE: "LocationChange",
|
|
34
|
-
ROUTE_CHANGE: "RouteChange",
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
```
|
package/src/index.js
DELETED
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
import * as reportError from "./report-error";
|
|
2
|
-
import * as reportPerformance from "./report-performance";
|
|
3
|
-
import * as reportRequest from "./report-request";
|
|
4
|
-
import * as reportUser from "./report-user";
|
|
5
|
-
import {
|
|
6
|
-
REPORT_TYPE,
|
|
7
|
-
ERROR_TYPE,
|
|
8
|
-
REQUEST_ERROR_TYPE,
|
|
9
|
-
USER_TYPE,
|
|
10
|
-
} from "./consts";
|
|
11
|
-
function formatDate(date) {
|
|
12
|
-
const year = date.getFullYear();
|
|
13
|
-
const month = date.getMonth() + 1;
|
|
14
|
-
const day = date.getDate();
|
|
15
|
-
return `${year}-${month}-${day}`;
|
|
16
|
-
}
|
|
17
|
-
const defaultOptions = {
|
|
18
|
-
reportUrl: "", // 上报请求地址
|
|
19
|
-
|
|
20
|
-
// app基本信息
|
|
21
|
-
appId: "", // appId
|
|
22
|
-
appVersion: "",
|
|
23
|
-
appUrl: window.location.origin, // 站点地址, 对应应用配置网站站点地址
|
|
24
|
-
appEnv: "prod",
|
|
25
|
-
userAgent: window.navigator.userAgent,
|
|
26
|
-
|
|
27
|
-
reportPath: "", // 上报页面路径
|
|
28
|
-
|
|
29
|
-
// 上报记录
|
|
30
|
-
reportError: true,
|
|
31
|
-
reportPromiseReject: true,
|
|
32
|
-
reportVueError: true,
|
|
33
|
-
vueInstance: null,
|
|
34
|
-
|
|
35
|
-
reportPerformance: true, // 是否上报性能数据
|
|
36
|
-
listenPerformance: true, // 是否监听性能数据
|
|
37
|
-
|
|
38
|
-
longTimeRequestThreshold: 2000, // 长请求时间阈值,单位毫秒
|
|
39
|
-
reportErrorReqest: true, // 是否上报报错请求
|
|
40
|
-
errorRequestFunc: null, // 错误请求过滤函数
|
|
41
|
-
// response => {
|
|
42
|
-
// return response.data.code !== 0
|
|
43
|
-
// },
|
|
44
|
-
|
|
45
|
-
reportUserNavigate: true, // 是否上报用户导航行为
|
|
46
|
-
|
|
47
|
-
// repeatRequestTime: 2000, // todo: 2s调用同一接口,同一参数,上报
|
|
48
|
-
appSecretKey: "", // 应用密钥
|
|
49
|
-
// 级别:错误、性能信息、用户导航行为、重复请求
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
class Report {
|
|
53
|
-
records = [];
|
|
54
|
-
timer = null;
|
|
55
|
-
options = {};
|
|
56
|
-
constructor(options) {
|
|
57
|
-
this.options = { ...defaultOptions, ...options };
|
|
58
|
-
}
|
|
59
|
-
init() {
|
|
60
|
-
const storeDate = localStorage.getItem("report-store-date");
|
|
61
|
-
|
|
62
|
-
const today = formatDate(new Date());
|
|
63
|
-
if (storeDate !== today) {
|
|
64
|
-
localStorage.setItem("report-store-date", today);
|
|
65
|
-
localStorage.setItem("report-store-list", "[]");
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const reportStoreList = JSON.parse(localStorage.getItem("report-store-list"));
|
|
69
|
-
|
|
70
|
-
// type 类型 (string) Required
|
|
71
|
-
// errorType 错误类型 (string)
|
|
72
|
-
// performanceType 性能上报指标 (string)
|
|
73
|
-
// requestType 请求上报指标 (string)
|
|
74
|
-
// navigationType 导航上报指标 (string)
|
|
75
|
-
// message 上报信息 (string)
|
|
76
|
-
// extra 额外信息 (string)
|
|
77
|
-
// originData 原始数据 (string)
|
|
78
|
-
|
|
79
|
-
// todo: 重复的上报太多,需要过滤
|
|
80
|
-
|
|
81
|
-
// listen and callback
|
|
82
|
-
if (this.options.reportError) {
|
|
83
|
-
// 错误上报
|
|
84
|
-
// 包含:资源加载错误,全局代码错误
|
|
85
|
-
reportError.globalErrorHandler((res) => {
|
|
86
|
-
if(reportStoreList.includes(res.message)) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
this.addReportRecord({
|
|
90
|
-
reportType: REPORT_TYPE.ERROR,
|
|
91
|
-
...res,
|
|
92
|
-
});
|
|
93
|
-
reportStoreList.push(res.message);
|
|
94
|
-
localStorage.setItem("report-store-list", JSON.stringify(reportStoreList));
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
if (this.options.reportPromiseReject) {
|
|
98
|
-
// 未处理的 Promise 错误上报
|
|
99
|
-
reportError.promiseErrorHandler((event) => {
|
|
100
|
-
if(reportStoreList.includes(event.reason?.stack)) {
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
this.addReportRecord({
|
|
104
|
-
reportType: REPORT_TYPE.ERROR,
|
|
105
|
-
type: ERROR_TYPE.PROMISE_REJECTION,
|
|
106
|
-
message: event.reason?.stack,
|
|
107
|
-
});
|
|
108
|
-
reportStoreList.push(event.reason?.stack);
|
|
109
|
-
localStorage.setItem("report-store-list", JSON.stringify(reportStoreList));
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
if (this.options.reportVueError && this.options.vueInstance) {
|
|
113
|
-
// vue错误上报
|
|
114
|
-
reportError.vueErrorHandler(this.options.vueInstance, ({ err }) => {
|
|
115
|
-
if(reportStoreList.includes(err.message)) {
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
this.addReportRecord({
|
|
119
|
-
reportType: REPORT_TYPE.ERROR,
|
|
120
|
-
type: ERROR_TYPE.VUE_ERROR,
|
|
121
|
-
message: err.message,
|
|
122
|
-
});
|
|
123
|
-
reportStoreList.push(err.message);
|
|
124
|
-
localStorage.setItem("report-store-list", JSON.stringify(reportStoreList));
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// if (this.options.reportPerformance) {
|
|
129
|
-
// // 性能上报
|
|
130
|
-
// reportPerformance.reportPerformance(options, (performanceList) => {
|
|
131
|
-
// this.addReportRecord({
|
|
132
|
-
// reportType: REPORT_TYPE.PERFORMANCE,
|
|
133
|
-
// type: "performance",
|
|
134
|
-
// message: "",
|
|
135
|
-
// extra: JSON.stringify(performanceList),
|
|
136
|
-
// });
|
|
137
|
-
// });
|
|
138
|
-
// }
|
|
139
|
-
|
|
140
|
-
if (this.options.listenPerformance) {
|
|
141
|
-
console.log("加载性能:fp, fcp, lcp, tbt, cls,等");
|
|
142
|
-
console.log("资源加载性能:dns, tcp, ssl, firstByte, download,等");
|
|
143
|
-
console.log("接口调用时间,需要剔除上报接口!");
|
|
144
|
-
|
|
145
|
-
// reportPerformance.loadedTimestamp((item) => {
|
|
146
|
-
// this.addReportRecord({
|
|
147
|
-
// reportType: REPORT_TYPE.PERFORMANCE,
|
|
148
|
-
// ...item,
|
|
149
|
-
// });
|
|
150
|
-
// });
|
|
151
|
-
|
|
152
|
-
// console.log(this.options,)
|
|
153
|
-
reportPerformance.listenPerformance(this.options, (performanceList) => {
|
|
154
|
-
// 加载性能:fp, fcp, lcp, tbt, cls,等
|
|
155
|
-
// 资源加载性能:dns, tcp, ssl, firstByte, download,等
|
|
156
|
-
// console.log('=============["performanceList"]:',performanceList)
|
|
157
|
-
performanceList.forEach((item) => {
|
|
158
|
-
if (item.extra.resourceName !== this.options.reportUrl) {
|
|
159
|
-
this.addReportRecord({
|
|
160
|
-
reportType: REPORT_TYPE.PERFORMANCE,
|
|
161
|
-
...item,
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
// this.addReportRecord({
|
|
166
|
-
// reportType: REPORT_TYPE.PERFORMANCE,
|
|
167
|
-
// type: "performance",
|
|
168
|
-
// message: "",
|
|
169
|
-
// extra: JSON.stringify(performanceList),
|
|
170
|
-
// });
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (this.options.reportErrorReqest) {
|
|
175
|
-
// 请求性能上报
|
|
176
|
-
reportRequest.xhrReportHandle(
|
|
177
|
-
null,
|
|
178
|
-
// (res) => {
|
|
179
|
-
// if (
|
|
180
|
-
// !!this.options.longTimeRequestThreshold &&
|
|
181
|
-
// res.duration > this.options.longTimeRequestThreshold
|
|
182
|
-
// ) {
|
|
183
|
-
// const { duration, url, method } = res;
|
|
184
|
-
// this.addReportRecord({
|
|
185
|
-
// reportType: REPORT_TYPE.REQUEST,
|
|
186
|
-
// type: REQUEST_ERROR_TYPE.LONG,
|
|
187
|
-
// message: `长请求时间接口:${url},方法:${method},耗时:${duration}ms`,
|
|
188
|
-
// extra: JSON.stringify({ duration }),
|
|
189
|
-
// });
|
|
190
|
-
// }
|
|
191
|
-
// },
|
|
192
|
-
(error) => {
|
|
193
|
-
const { status, url, method, statusText } = error;
|
|
194
|
-
const message = `请求报错接口:${url},方法:${method},状态码:${status},状态信息:${statusText}`
|
|
195
|
-
if(reportStoreList.includes(message)) {
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
this.addReportRecord({
|
|
199
|
-
reportType: REPORT_TYPE.ERROR,
|
|
200
|
-
type: REQUEST_ERROR_TYPE.ERROR,
|
|
201
|
-
message: message,
|
|
202
|
-
});
|
|
203
|
-
reportStoreList.push(message);
|
|
204
|
-
localStorage.setItem("report-store-list", JSON.stringify(reportStoreList));
|
|
205
|
-
},
|
|
206
|
-
this.options,
|
|
207
|
-
);
|
|
208
|
-
reportRequest.fetchReportHandle(
|
|
209
|
-
// (res) => {
|
|
210
|
-
// if (
|
|
211
|
-
// !!this.options.longTimeRequestThreshold &&
|
|
212
|
-
// res.duration > this.options.longTimeRequestThreshold
|
|
213
|
-
// ) {
|
|
214
|
-
// const { duration, url, method } = res;
|
|
215
|
-
// this.addReportRecord({
|
|
216
|
-
// reportType: REPORT_TYPE.REQUEST,
|
|
217
|
-
// type: REQUEST_ERROR_TYPE.LONG,
|
|
218
|
-
// message: `长请求时间接口:${url},方法:${method},耗时:${duration}ms`,
|
|
219
|
-
// extra: JSON.stringify({ duration }),
|
|
220
|
-
// });
|
|
221
|
-
// }
|
|
222
|
-
// },
|
|
223
|
-
null,
|
|
224
|
-
(error) => {
|
|
225
|
-
const { url, method, statusText } = error;
|
|
226
|
-
const message = `请求报错接口:${url},方法:${method},状态信息:${statusText}`
|
|
227
|
-
if(reportStoreList.includes(message)) {
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
this.addReportRecord({
|
|
231
|
-
reportType: REPORT_TYPE.ERROR,
|
|
232
|
-
type: REQUEST_ERROR_TYPE.ERROR,
|
|
233
|
-
message: message,
|
|
234
|
-
});
|
|
235
|
-
reportStoreList.push(message);
|
|
236
|
-
localStorage.setItem("report-store-list", JSON.stringify(reportStoreList));
|
|
237
|
-
},
|
|
238
|
-
this.options,
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if (this.options.reportUserNavigate) {
|
|
243
|
-
const href = window.location.href;
|
|
244
|
-
this.addReportRecord({
|
|
245
|
-
reportType: REPORT_TYPE.USER,
|
|
246
|
-
type: USER_TYPE.LOCATION_CHANGE,
|
|
247
|
-
message: `请求地址:${href}`,
|
|
248
|
-
extra: JSON.stringify({
|
|
249
|
-
url: href,
|
|
250
|
-
}),
|
|
251
|
-
});
|
|
252
|
-
reportUser.initRouteListener((record) => {
|
|
253
|
-
this.addReportRecord({
|
|
254
|
-
reportType: REPORT_TYPE.USER,
|
|
255
|
-
type: USER_TYPE.ROUTE_CHANGE,
|
|
256
|
-
message: `路由变化:${record.to}`,
|
|
257
|
-
extra: JSON.stringify({
|
|
258
|
-
route: record.to,
|
|
259
|
-
}),
|
|
260
|
-
});
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
addReportRecord(record) {
|
|
265
|
-
this.timer && clearTimeout(this.timer);
|
|
266
|
-
this.timer = setTimeout(() => {
|
|
267
|
-
try {
|
|
268
|
-
this.sendReport(JSON.parse(JSON.stringify(this.records)));
|
|
269
|
-
this.records = [];
|
|
270
|
-
} catch (error) {
|
|
271
|
-
console.log(error);
|
|
272
|
-
}
|
|
273
|
-
}, 1000);
|
|
274
|
-
|
|
275
|
-
this.records.push({
|
|
276
|
-
appId: this.options.appId,
|
|
277
|
-
appUrl: this.options.appUrl,
|
|
278
|
-
reportPath: window.location.pathname,
|
|
279
|
-
userAgent: window.navigator.userAgent,
|
|
280
|
-
...record,
|
|
281
|
-
extra:
|
|
282
|
-
record.extra && typeof record.extra === "object"
|
|
283
|
-
? JSON.stringify(record.extra)
|
|
284
|
-
: undefined,
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
sendReport(records) {
|
|
288
|
-
const analyticsData = {
|
|
289
|
-
appSecretKey: this.options.appSecretKey,
|
|
290
|
-
appId: this.options.appId,
|
|
291
|
-
data: records,
|
|
292
|
-
};
|
|
293
|
-
const blob = new Blob(
|
|
294
|
-
[JSON.stringify(analyticsData)], // 将JavaScript对象转换为JSON字符串
|
|
295
|
-
{ type: "application/json; charset=UTF-8" }, // 在这里设置Content-Type
|
|
296
|
-
);
|
|
297
|
-
const success = navigator.sendBeacon(this.options.reportUrl, blob);
|
|
298
|
-
if (success) {
|
|
299
|
-
console.log("数据已成功加入发送队列。");
|
|
300
|
-
console.log(analyticsData);
|
|
301
|
-
} else {
|
|
302
|
-
console.log("数据入队失败,需要降级方案。");
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
let report;
|
|
308
|
-
export function init(options = {}) {
|
|
309
|
-
if (!report) report = new Report(options);
|
|
310
|
-
report.init();
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// // 导出所有模块
|
|
314
|
-
// export {
|
|
315
|
-
// reportError,
|
|
316
|
-
// reportPerformance,
|
|
317
|
-
// reportRequest,
|
|
318
|
-
// reportUser,
|
|
319
|
-
// init
|
|
320
|
-
// };
|
|
321
|
-
export default {
|
|
322
|
-
init,
|
|
323
|
-
};
|