monitor-track 1.14.0 → 1.15.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 +10 -0
- package/README.md +1 -0
- package/cjs/config/global.d.ts +0 -2
- package/cjs/config/request.d.ts +15 -0
- package/cjs/handlers/websocket.d.ts +16 -0
- package/cjs/index.d.ts +0 -5
- package/cjs/index.js +425 -170
- package/cjs/reporter.d.ts +2 -0
- package/cjs/types/config.d.ts +2 -0
- package/cjs/types/global.d.ts +2 -1
- package/esm/config/global.d.ts +0 -2
- package/esm/config/global.js +2 -167
- package/esm/config/index.js +3 -2
- package/esm/config/request.d.ts +15 -0
- package/esm/config/request.js +158 -0
- package/esm/handlers/websocket.d.ts +16 -0
- package/esm/handlers/websocket.js +277 -0
- package/esm/index.d.ts +0 -5
- package/esm/index.js +7 -15
- package/esm/package.json.js +1 -1
- package/esm/reporter.d.ts +2 -0
- package/esm/reporter.js +6 -0
- package/esm/types/config.d.ts +2 -0
- package/esm/types/global.d.ts +2 -1
- package/index.js +460 -166
- package/package.json +1 -1
package/cjs/index.js
CHANGED
|
@@ -40,8 +40,8 @@ const Config = {
|
|
|
40
40
|
reportUrl: '',
|
|
41
41
|
projectID: '',
|
|
42
42
|
maxLength: 1000,
|
|
43
|
-
spa:
|
|
44
|
-
hash:
|
|
43
|
+
spa: true,
|
|
44
|
+
hash: true,
|
|
45
45
|
enableBehavior: true,
|
|
46
46
|
enableError: true,
|
|
47
47
|
enableErrorScreenshot: false,
|
|
@@ -49,6 +49,7 @@ const Config = {
|
|
|
49
49
|
enableVisualTrack: false,
|
|
50
50
|
enableLagTrack: true,
|
|
51
51
|
enableRecord: false,
|
|
52
|
+
enableOnlinePersons: true,
|
|
52
53
|
ignore: {
|
|
53
54
|
urls: [],
|
|
54
55
|
errors: [],
|
|
@@ -73,7 +74,7 @@ function setConfig(config) {
|
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
|
|
76
|
-
var version = "1.
|
|
77
|
+
var version = "1.15.0";
|
|
77
78
|
|
|
78
79
|
const eventsMatrix = [[]];
|
|
79
80
|
function enableRecordFunc() {
|
|
@@ -850,6 +851,8 @@ const reportMap = {
|
|
|
850
851
|
detail: 'de',
|
|
851
852
|
/** 上报时带上的请求参数 */
|
|
852
853
|
requestData: 'rD',
|
|
854
|
+
/** 上报时带上的响应结果 */
|
|
855
|
+
responseBody: 'rB',
|
|
853
856
|
/** 上报时带上的请求方法 */
|
|
854
857
|
method: 'rM',
|
|
855
858
|
},
|
|
@@ -978,6 +981,10 @@ function reportFunc(data) {
|
|
|
978
981
|
// 上报
|
|
979
982
|
function report(data) {
|
|
980
983
|
return new Promise((res) => {
|
|
984
|
+
var _a;
|
|
985
|
+
if ((((_a = Config.ignore) === null || _a === void 0 ? void 0 : _a.urls) || []).some((url) => location.href.includes(url))) {
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
981
988
|
//在帧的空闲时间上报
|
|
982
989
|
const dataCopy = JSON.parse(JSON.stringify(data));
|
|
983
990
|
if (typeof window.requestIdleCallback === 'function') {
|
|
@@ -1236,171 +1243,429 @@ function getReport() {
|
|
|
1236
1243
|
customPayload: Config.customPayload,
|
|
1237
1244
|
dpr: window.devicePixelRatio,
|
|
1238
1245
|
});
|
|
1239
|
-
}
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
let reconnectAndSendTimeout, websocketHeartBeatInterval, ws, userId = '';
|
|
1249
|
+
let remoteDebugEnable = false;
|
|
1250
|
+
let targetPlatform = '';
|
|
1251
|
+
let targetUserId = '';
|
|
1252
|
+
const originConsole = Object.assign({}, console);
|
|
1253
|
+
const formatConsole = () => {
|
|
1254
|
+
if (remoteDebugEnable)
|
|
1255
|
+
return;
|
|
1256
|
+
remoteDebugEnable = true;
|
|
1257
|
+
window.console = Object.assign({}, originConsole);
|
|
1258
|
+
const arr = ['debug', 'log', 'info', 'warn', 'error'];
|
|
1259
|
+
arr.forEach((item) => {
|
|
1260
|
+
//@ts-ignore
|
|
1261
|
+
window.console[item] = function (...args) {
|
|
1262
|
+
//@ts-ignore
|
|
1263
|
+
originConsole[item](...args);
|
|
1264
|
+
const data = {
|
|
1265
|
+
origin: 'console',
|
|
1266
|
+
level: item,
|
|
1267
|
+
userId,
|
|
1268
|
+
time: new Date().toLocaleString(),
|
|
1269
|
+
page: location.href,
|
|
1270
|
+
content: '',
|
|
1271
|
+
targetPlatform,
|
|
1272
|
+
targetUserId,
|
|
1273
|
+
};
|
|
1274
|
+
try {
|
|
1275
|
+
const content = JSON.stringify(args);
|
|
1276
|
+
data.content = content;
|
|
1277
|
+
}
|
|
1278
|
+
catch (err) {
|
|
1279
|
+
data.content = 'console内容解析错误: ' + err.stack || err.message || err.toString();
|
|
1280
|
+
}
|
|
1281
|
+
const msg = {
|
|
1282
|
+
type: WEBSOCKET_TYPE.DEBUG_INFO_UPLOAD,
|
|
1283
|
+
userId,
|
|
1284
|
+
platform: 'monitor-track-sdk',
|
|
1285
|
+
data,
|
|
1286
|
+
};
|
|
1287
|
+
wsSendFunc(msg);
|
|
1288
|
+
};
|
|
1243
1289
|
});
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1290
|
+
};
|
|
1291
|
+
const resetConsole = () => {
|
|
1292
|
+
window.console = originConsole;
|
|
1293
|
+
remoteDebugEnable = false;
|
|
1294
|
+
};
|
|
1295
|
+
const uploadRequest = (requestInfo) => {
|
|
1296
|
+
// console.log('monitor-track-sdk: uploadRequest remoteDebugEnable', remoteDebugEnable);
|
|
1297
|
+
if (remoteDebugEnable) {
|
|
1298
|
+
const data = {
|
|
1299
|
+
origin: 'request',
|
|
1300
|
+
userId,
|
|
1301
|
+
time: new Date().toLocaleString(),
|
|
1302
|
+
page: location.href,
|
|
1303
|
+
content: requestInfo,
|
|
1304
|
+
targetPlatform,
|
|
1305
|
+
targetUserId,
|
|
1306
|
+
};
|
|
1307
|
+
const msg = {
|
|
1308
|
+
type: WEBSOCKET_TYPE.DEBUG_INFO_UPLOAD,
|
|
1309
|
+
userId,
|
|
1310
|
+
platform: 'monitor-track-sdk',
|
|
1311
|
+
data,
|
|
1312
|
+
};
|
|
1313
|
+
// console.log('monitor-track-sdk: request-upload sent');
|
|
1314
|
+
wsSendFunc(msg);
|
|
1315
|
+
}
|
|
1316
|
+
};
|
|
1317
|
+
function enableOnlinePersonsFunc() {
|
|
1318
|
+
initWebsocket();
|
|
1261
1319
|
}
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1320
|
+
const WEBSOCKET_TYPE = {
|
|
1321
|
+
TRY_CONNECT: 'try-connect',
|
|
1322
|
+
CHECK_CONNECT: 'check-connect',
|
|
1323
|
+
PING: 'ping',
|
|
1324
|
+
PONG: 'pong',
|
|
1325
|
+
REPLY_SERVER_HEART_BEAT: 'reply-server-heart-beat',
|
|
1326
|
+
SOCKET_HEART_BEAT: 'socket-heart-beat',
|
|
1327
|
+
RESPONSE_DATE: 'response-date',
|
|
1328
|
+
REMOTE_DEBUG_ENABLE: 'remote-debug-enable',
|
|
1329
|
+
DEBUG_INFO_UPLOAD: 'debug-info-upload',
|
|
1330
|
+
REPlY_MESSAGE: 'reply-message',
|
|
1331
|
+
};
|
|
1332
|
+
let mounted = false;
|
|
1333
|
+
const initWebsocket = () => {
|
|
1334
|
+
if (window.WebSocket) {
|
|
1335
|
+
userId = localStorage.getItem('username') || getUid();
|
|
1336
|
+
closeWebsocket('');
|
|
1337
|
+
websocketHeartBeatInterval = setInterval(reconnectAndSend, 30000);
|
|
1338
|
+
const isLocal = Config.reportUrl.includes('http://');
|
|
1339
|
+
ws = new WebSocket(`ws${isLocal ? '' : 's'}://${Config.reportUrl.replace(isLocal ? 'http://' : 'https://', '').replace('/s/r', '')}?type=monitor-dsk`);
|
|
1340
|
+
ws.onopen = () => openWS();
|
|
1341
|
+
ws.onmessage = (data) => incomingMessage(data);
|
|
1342
|
+
ws.onerror = () => {
|
|
1343
|
+
ws.close(1000);
|
|
1344
|
+
if (websocketHeartBeatInterval)
|
|
1345
|
+
clearInterval(websocketHeartBeatInterval);
|
|
1346
|
+
websocketHeartBeatInterval = setInterval(reconnectAndSend, 10000);
|
|
1277
1347
|
};
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1348
|
+
ws.onclose = () => {
|
|
1349
|
+
ws.close(1000);
|
|
1350
|
+
if (websocketHeartBeatInterval)
|
|
1351
|
+
clearInterval(websocketHeartBeatInterval);
|
|
1352
|
+
websocketHeartBeatInterval = setInterval(reconnectAndSend, 10000);
|
|
1353
|
+
};
|
|
1354
|
+
if (!mounted) {
|
|
1355
|
+
reconnectNetwork();
|
|
1356
|
+
mounted = true;
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
};
|
|
1360
|
+
const openWS = () => {
|
|
1361
|
+
const data = getReport();
|
|
1362
|
+
const { page, projectID, host, pageTitle } = data;
|
|
1363
|
+
const msg = {
|
|
1364
|
+
type: WEBSOCKET_TYPE.TRY_CONNECT,
|
|
1365
|
+
userId,
|
|
1366
|
+
platform: 'monitor-track-sdk',
|
|
1367
|
+
data: {
|
|
1368
|
+
p: page,
|
|
1369
|
+
pid: projectID,
|
|
1370
|
+
host,
|
|
1371
|
+
pt: pageTitle,
|
|
1372
|
+
platform: 'web',
|
|
1373
|
+
},
|
|
1374
|
+
};
|
|
1375
|
+
wsSendFunc(msg);
|
|
1376
|
+
};
|
|
1377
|
+
const reconnectAndSend = () => {
|
|
1378
|
+
try {
|
|
1379
|
+
if (ws.readyState !== 1) {
|
|
1380
|
+
reconnectSocket();
|
|
1381
|
+
}
|
|
1382
|
+
else {
|
|
1383
|
+
const msg = {
|
|
1384
|
+
type: WEBSOCKET_TYPE.CHECK_CONNECT,
|
|
1385
|
+
userId,
|
|
1386
|
+
data: WEBSOCKET_TYPE.PING,
|
|
1387
|
+
date: Date.now(),
|
|
1388
|
+
};
|
|
1389
|
+
wsSendFunc(msg, 'reconnectAndSend');
|
|
1390
|
+
// 20秒超时,如果收不到服务端pong响应则表示服务端已主动断开连接,此时需客户端重新开启websocket连接
|
|
1391
|
+
reconnectAndSendTimeout = setTimeout(() => {
|
|
1392
|
+
reconnectSocket();
|
|
1393
|
+
}, 20000);
|
|
1394
|
+
}
|
|
1395
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1396
|
+
}
|
|
1397
|
+
catch (_err) {
|
|
1398
|
+
// console.error('monitor-track-sdk: reconnectAndSend err', err);
|
|
1399
|
+
}
|
|
1400
|
+
};
|
|
1401
|
+
const closeWebsocket = (info) => {
|
|
1402
|
+
if (ws) {
|
|
1403
|
+
ws.onopen = null;
|
|
1404
|
+
ws.onmessage = null;
|
|
1405
|
+
ws.onerror = null;
|
|
1406
|
+
ws.onclose = null;
|
|
1407
|
+
if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) {
|
|
1408
|
+
ws.close(1000, info);
|
|
1409
|
+
}
|
|
1410
|
+
//@ts-ignore
|
|
1411
|
+
ws = null; // 释放引用
|
|
1412
|
+
}
|
|
1413
|
+
if (websocketHeartBeatInterval)
|
|
1414
|
+
clearInterval(websocketHeartBeatInterval);
|
|
1415
|
+
};
|
|
1416
|
+
const reconnectSocket = () => {
|
|
1417
|
+
// console.warn('monitor-track-sdk: 正在重新建立websocket连接...');
|
|
1418
|
+
initWebsocket();
|
|
1419
|
+
};
|
|
1420
|
+
const incomingMessage = (e) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1421
|
+
let data = {};
|
|
1422
|
+
try {
|
|
1423
|
+
data = JSON.parse(e.data);
|
|
1424
|
+
// console.info('incomingMessage data', data);
|
|
1425
|
+
switch (data.type) {
|
|
1426
|
+
case WEBSOCKET_TYPE.PONG:
|
|
1427
|
+
// console.info('monitor-track-sdk: incomingMessage 响应客户端的心跳: ping => pong');
|
|
1428
|
+
clearTimeout(reconnectAndSendTimeout);
|
|
1429
|
+
break;
|
|
1430
|
+
case WEBSOCKET_TYPE.SOCKET_HEART_BEAT: {
|
|
1431
|
+
// console.info('monitor-track-sdk: incomingMessage 响应服务端的心跳: heart beat => ', new Date().toLocaleString());
|
|
1432
|
+
const msg = {
|
|
1433
|
+
type: WEBSOCKET_TYPE.CHECK_CONNECT,
|
|
1434
|
+
userId,
|
|
1435
|
+
data: WEBSOCKET_TYPE.REPLY_SERVER_HEART_BEAT,
|
|
1436
|
+
date: Date.now(),
|
|
1298
1437
|
};
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1438
|
+
wsSendFunc(msg, 'socket-heart-beat reply-server-heart-beat');
|
|
1439
|
+
break;
|
|
1440
|
+
}
|
|
1441
|
+
case WEBSOCKET_TYPE.RESPONSE_DATE:
|
|
1442
|
+
// console.info(`monitor-track-sdk: incomingMessage WS connected, Roundtrip time: ${Date.now() - data.data} ms`);
|
|
1443
|
+
break;
|
|
1444
|
+
case WEBSOCKET_TYPE.REMOTE_DEBUG_ENABLE: {
|
|
1445
|
+
// console.log('monitor-track-sdk REMOTE_DEBUG_ENABLE data.data', data.data);
|
|
1446
|
+
const { enable, platform, userId } = data.data;
|
|
1447
|
+
if (enable && platform && userId) {
|
|
1448
|
+
targetPlatform = platform;
|
|
1449
|
+
targetUserId = userId;
|
|
1450
|
+
formatConsole();
|
|
1306
1451
|
}
|
|
1307
|
-
else
|
|
1308
|
-
|
|
1309
|
-
if (!tempUrlInfo[responseURL]) {
|
|
1310
|
-
tempUrlInfo[responseURL] = true;
|
|
1311
|
-
setTimeout(() => {
|
|
1312
|
-
delete tempUrlInfo[responseURL];
|
|
1313
|
-
}, 10);
|
|
1314
|
-
setReportValue('error', null);
|
|
1315
|
-
report(Object.assign(Object.assign({}, getReport()), {
|
|
1316
|
-
page: location.href,
|
|
1317
|
-
originPage: location.href,
|
|
1318
|
-
type: 'request',
|
|
1319
|
-
req: request,
|
|
1320
|
-
}));
|
|
1321
|
-
}
|
|
1452
|
+
else {
|
|
1453
|
+
resetConsole();
|
|
1322
1454
|
}
|
|
1455
|
+
break;
|
|
1456
|
+
}
|
|
1457
|
+
case WEBSOCKET_TYPE.REPlY_MESSAGE: {
|
|
1458
|
+
// eslint-disable-next-line no-console
|
|
1459
|
+
console.info('incomingMessage REPlY_MESSAGE, data: ', data.data);
|
|
1460
|
+
break;
|
|
1323
1461
|
}
|
|
1324
|
-
|
|
1325
|
-
|
|
1462
|
+
default:
|
|
1463
|
+
// console.error('incomingMessage default error', data);
|
|
1464
|
+
break;
|
|
1326
1465
|
}
|
|
1327
|
-
}
|
|
1466
|
+
}
|
|
1467
|
+
catch (err) {
|
|
1468
|
+
// eslint-disable-next-line no-console
|
|
1469
|
+
console.error('monitor-track-sdk incomingMessage JSON.parse', err);
|
|
1470
|
+
}
|
|
1471
|
+
});
|
|
1472
|
+
const wsSendFunc = (msg, _info) => {
|
|
1473
|
+
if (ws.readyState === 1) {
|
|
1474
|
+
msg.platform = 'monitor-track-sdk';
|
|
1475
|
+
const message = JSON.stringify(msg);
|
|
1476
|
+
ws.send(message);
|
|
1477
|
+
}
|
|
1478
|
+
else {
|
|
1479
|
+
// console.warn('monitor-track-sdk: window.ws.readyState === 1 info', info);
|
|
1480
|
+
reconnectSocket();
|
|
1481
|
+
}
|
|
1328
1482
|
};
|
|
1329
|
-
const
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1483
|
+
const reconnectNetwork = () => {
|
|
1484
|
+
let networkFlag = false;
|
|
1485
|
+
let debounceTimeout = null;
|
|
1486
|
+
document.addEventListener('offline', function () {
|
|
1487
|
+
// 断开网络
|
|
1488
|
+
try {
|
|
1489
|
+
// console.info('monitor-track-sdk: 客户端网络已断开,正在关闭websocket');
|
|
1490
|
+
ws.close(1000);
|
|
1491
|
+
networkFlag = true;
|
|
1492
|
+
debounceTimeout = setTimeout(() => {
|
|
1493
|
+
// console.warn('monitor-track-sdk: reconnectNetwork offline 无法访问网络');
|
|
1494
|
+
// message.error('无法访问网络');
|
|
1495
|
+
}, 5000);
|
|
1496
|
+
}
|
|
1497
|
+
catch (err) {
|
|
1498
|
+
// console.error('monitor-track-sdk: addEventListener offline after setTimeout', err);
|
|
1499
|
+
}
|
|
1500
|
+
}, false);
|
|
1501
|
+
document.addEventListener('online', function () {
|
|
1502
|
+
// 连接到网络
|
|
1503
|
+
try {
|
|
1504
|
+
if (networkFlag === true) {
|
|
1505
|
+
clearTimeout(debounceTimeout);
|
|
1506
|
+
// console.info('monitor-track-sdk: addEventListener reconnectNetwork online');
|
|
1507
|
+
// message.success('网络已恢复');
|
|
1508
|
+
networkFlag = false;
|
|
1509
|
+
// console.warn('monitor-track-sdk: addEventListener online websocket 正在重新建立连接...');
|
|
1510
|
+
initWebsocket();
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
catch (err) {
|
|
1514
|
+
// console.error('monitor-track-sdk: document.addEventListener online', err);
|
|
1515
|
+
}
|
|
1516
|
+
}, false);
|
|
1517
|
+
};
|
|
1518
|
+
|
|
1519
|
+
let xhrTimeout = 2500;
|
|
1520
|
+
let fetchTimeout = 2500;
|
|
1521
|
+
const maxContentLength = 1000;
|
|
1522
|
+
// 保存原始 XMLHttpRequest
|
|
1523
|
+
const OriginalXHR = window.XMLHttpRequest;
|
|
1524
|
+
// 创建增强版的 XMLHttpRequest 类
|
|
1525
|
+
class InterceptedXHR extends OriginalXHR {
|
|
1526
|
+
constructor() {
|
|
1527
|
+
super();
|
|
1528
|
+
this.requestInfo = {
|
|
1529
|
+
requestType: 'xhr',
|
|
1530
|
+
method: '',
|
|
1531
|
+
responseURL: '',
|
|
1532
|
+
requestData: null,
|
|
1533
|
+
responseBody: null,
|
|
1534
|
+
status: 0,
|
|
1535
|
+
startTime: Date.now(),
|
|
1536
|
+
loadTime: 0,
|
|
1537
|
+
statusText: '',
|
|
1538
|
+
reason: '',
|
|
1539
|
+
detail: '',
|
|
1540
|
+
};
|
|
1541
|
+
this.setupInterceptors();
|
|
1542
|
+
}
|
|
1543
|
+
open(method, url, async = true, username, password) {
|
|
1544
|
+
super.open(method, url, async, username, password);
|
|
1545
|
+
this.requestInfo.method = method;
|
|
1546
|
+
this.requestInfo.responseURL = url;
|
|
1547
|
+
}
|
|
1548
|
+
// eslint-disable-next-line no-undef
|
|
1549
|
+
send(body) {
|
|
1550
|
+
super.send(body);
|
|
1551
|
+
try {
|
|
1552
|
+
this.requestInfo.requestData =
|
|
1553
|
+
typeof body === 'object' && body
|
|
1554
|
+
? JSON.stringify(body).slice(0, maxContentLength)
|
|
1555
|
+
: typeof body === 'string'
|
|
1556
|
+
? body.slice(0, maxContentLength)
|
|
1557
|
+
: body || '';
|
|
1558
|
+
}
|
|
1559
|
+
catch (err) {
|
|
1560
|
+
// eslint-disable-next-line no-console
|
|
1561
|
+
console.error('xhr send err: ', err, 'body', body);
|
|
1562
|
+
}
|
|
1563
|
+
this.requestInfo.startTime = Date.now();
|
|
1564
|
+
}
|
|
1565
|
+
setupInterceptors() {
|
|
1566
|
+
this.addEventListener('load', () => {
|
|
1567
|
+
try {
|
|
1568
|
+
this.requestInfo.status = this.status;
|
|
1569
|
+
this.requestInfo.responseBody = this.responseText.slice(0, maxContentLength);
|
|
1570
|
+
this.requestInfo.loadTime = Date.now() - this.requestInfo.startTime;
|
|
1571
|
+
this.requestInfo.statusText = this.statusText;
|
|
1572
|
+
if (this.requestInfo.loadTime > xhrTimeout) {
|
|
1573
|
+
this.requestInfo.reason = 'slow';
|
|
1574
|
+
this.requestInfo.detail = `request is too slow, XMLHttpRequestTimeout: ${this.requestInfo.loadTime}`;
|
|
1351
1575
|
}
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
.
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
if (!ok || status >= 300) {
|
|
1369
|
-
request.reason = 'failed';
|
|
1370
|
-
request.detail = `request is failed, status: ${status}, statusText: ${statusText}`;
|
|
1371
|
-
}
|
|
1372
|
-
else if (loadTime > XMLHttpRequestTimeout) {
|
|
1373
|
-
request.reason = 'slow';
|
|
1374
|
-
request.detail = `request is too slow, XMLHttpRequestTimeout: ${loadTime}, result: ${result === null || result === void 0 ? void 0 : result.slice(0, 500)}`;
|
|
1375
|
-
}
|
|
1376
|
-
if (request.reason) {
|
|
1377
|
-
if (!tempUrlInfo[url]) {
|
|
1378
|
-
tempUrlInfo[url] = true;
|
|
1379
|
-
setTimeout(() => {
|
|
1380
|
-
delete tempUrlInfo[url];
|
|
1381
|
-
}, 10);
|
|
1382
|
-
setReportValue('error', null);
|
|
1383
|
-
report(Object.assign(Object.assign({}, getReport()), {
|
|
1384
|
-
page: location.href,
|
|
1385
|
-
originPage: location.href,
|
|
1386
|
-
type: 'request',
|
|
1387
|
-
req: request,
|
|
1388
|
-
}));
|
|
1389
|
-
}
|
|
1390
|
-
}
|
|
1391
|
-
})
|
|
1392
|
-
.catch((err) => {
|
|
1393
|
-
// eslint-disable-next-line no-console
|
|
1394
|
-
console.log('hackFetch response.text() err', err);
|
|
1395
|
-
});
|
|
1396
|
-
return res;
|
|
1397
|
-
})
|
|
1398
|
-
.catch((err) => {
|
|
1576
|
+
if (this.status >= 400) {
|
|
1577
|
+
this.requestInfo.reason = 'failed';
|
|
1578
|
+
this.requestInfo.detail = `request is failed, status: ${this.status}, statusText: ${this.statusText}`;
|
|
1579
|
+
}
|
|
1580
|
+
if (this.requestInfo.reason) {
|
|
1581
|
+
setReportValue('error', null);
|
|
1582
|
+
report(Object.assign(Object.assign({}, getReport()), {
|
|
1583
|
+
page: location.href,
|
|
1584
|
+
originPage: location.href,
|
|
1585
|
+
type: 'request',
|
|
1586
|
+
req: this.requestInfo,
|
|
1587
|
+
}));
|
|
1588
|
+
}
|
|
1589
|
+
uploadRequest(this.requestInfo);
|
|
1590
|
+
}
|
|
1591
|
+
catch (err) {
|
|
1399
1592
|
// eslint-disable-next-line no-console
|
|
1400
|
-
console.
|
|
1401
|
-
}
|
|
1402
|
-
};
|
|
1593
|
+
console.error('xhr load err: ', err, 'this.requestInfo', this.requestInfo);
|
|
1594
|
+
}
|
|
1595
|
+
});
|
|
1596
|
+
this.addEventListener('error', () => {
|
|
1597
|
+
// console.error('❌ 请求失败:', this.requestInfo);
|
|
1598
|
+
});
|
|
1403
1599
|
}
|
|
1600
|
+
}
|
|
1601
|
+
const recordXMLHttpRequest = (XMLHttpRequestTimeout) => {
|
|
1602
|
+
xhrTimeout = XMLHttpRequestTimeout;
|
|
1603
|
+
// 重写全局 XMLHttpRequest
|
|
1604
|
+
window.XMLHttpRequest = InterceptedXHR;
|
|
1605
|
+
};
|
|
1606
|
+
const originalFetch = window.fetch;
|
|
1607
|
+
// eslint-disable-next-line no-undef
|
|
1608
|
+
const fetchFUnc = function (input, init) {
|
|
1609
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1610
|
+
const url = typeof input === 'string' ? input : input.toString();
|
|
1611
|
+
const options = init || {};
|
|
1612
|
+
const requestInfo = {
|
|
1613
|
+
requestType: 'fetch',
|
|
1614
|
+
method: options.method || 'GET',
|
|
1615
|
+
responseURL: url,
|
|
1616
|
+
requestData: typeof options.body === 'object' && options.body ? JSON.stringify(options.body).slice(0, maxContentLength) : options.body || '',
|
|
1617
|
+
responseBody: '',
|
|
1618
|
+
status: 0,
|
|
1619
|
+
startTime: Date.now(),
|
|
1620
|
+
loadTime: 0,
|
|
1621
|
+
statusText: '',
|
|
1622
|
+
reason: '',
|
|
1623
|
+
detail: '',
|
|
1624
|
+
};
|
|
1625
|
+
const response = yield originalFetch(input, init);
|
|
1626
|
+
try {
|
|
1627
|
+
const clonedResponse = response.clone();
|
|
1628
|
+
requestInfo.status = response.status;
|
|
1629
|
+
requestInfo.loadTime = Date.now() - requestInfo.startTime;
|
|
1630
|
+
requestInfo.statusText = response.statusText;
|
|
1631
|
+
if (!response.ok) {
|
|
1632
|
+
requestInfo.reason = 'failed';
|
|
1633
|
+
requestInfo.detail = `request is failed, status: ${response.status}, statusText: ${response.statusText}`;
|
|
1634
|
+
}
|
|
1635
|
+
else {
|
|
1636
|
+
if (requestInfo.loadTime > fetchTimeout) {
|
|
1637
|
+
requestInfo.reason = 'slow';
|
|
1638
|
+
requestInfo.detail = `request is too slow, XMLHttpRequestTimeout: ${requestInfo.loadTime}`;
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
try {
|
|
1642
|
+
const responseBody = yield clonedResponse.text();
|
|
1643
|
+
requestInfo.responseBody = responseBody.slice(0, maxContentLength);
|
|
1644
|
+
}
|
|
1645
|
+
catch (e) {
|
|
1646
|
+
requestInfo.responseBody = (e === null || e === void 0 ? void 0 : e.message) || (e === null || e === void 0 ? void 0 : e.stack) || (e === null || e === void 0 ? void 0 : e.toString());
|
|
1647
|
+
}
|
|
1648
|
+
if (requestInfo.reason) {
|
|
1649
|
+
setReportValue('error', null);
|
|
1650
|
+
report(Object.assign(Object.assign({}, getReport()), {
|
|
1651
|
+
page: location.href,
|
|
1652
|
+
originPage: location.href,
|
|
1653
|
+
type: 'request',
|
|
1654
|
+
req: requestInfo,
|
|
1655
|
+
}));
|
|
1656
|
+
}
|
|
1657
|
+
uploadRequest(requestInfo);
|
|
1658
|
+
}
|
|
1659
|
+
catch (err) {
|
|
1660
|
+
// eslint-disable-next-line no-console
|
|
1661
|
+
console.error('❌ 获取响应数据失败, requestInfo: ', requestInfo, 'err: ', err);
|
|
1662
|
+
}
|
|
1663
|
+
return response;
|
|
1664
|
+
});
|
|
1665
|
+
};
|
|
1666
|
+
const recordFetch = (XMLHttpRequestTimeout) => {
|
|
1667
|
+
fetchTimeout = XMLHttpRequestTimeout;
|
|
1668
|
+
window.fetch = fetchFUnc;
|
|
1404
1669
|
};
|
|
1405
1670
|
|
|
1406
1671
|
class Track {
|
|
@@ -1426,7 +1691,6 @@ class Track {
|
|
|
1426
1691
|
};
|
|
1427
1692
|
}
|
|
1428
1693
|
init(config) {
|
|
1429
|
-
var _a;
|
|
1430
1694
|
// 是否开启日志收集
|
|
1431
1695
|
if (!config || !config.enable) {
|
|
1432
1696
|
return;
|
|
@@ -1443,19 +1707,17 @@ class Track {
|
|
|
1443
1707
|
console.warn('缺少上报地址!');
|
|
1444
1708
|
return;
|
|
1445
1709
|
}
|
|
1446
|
-
if (this.ignoreUrl(((_a = config === null || config === void 0 ? void 0 : config.ignore) === null || _a === void 0 ? void 0 : _a.urls) || [])) {
|
|
1447
|
-
return;
|
|
1448
|
-
}
|
|
1449
1710
|
setConfig(config);
|
|
1450
1711
|
initReport();
|
|
1451
|
-
|
|
1452
|
-
|
|
1712
|
+
recordXMLHttpRequest(config.XMLHttpRequestTimeout || 2500);
|
|
1713
|
+
recordFetch(config.XMLHttpRequestTimeout || 2500);
|
|
1453
1714
|
Config.spa && this.addListenRouterChange();
|
|
1454
1715
|
Config.enableBehavior && this.addListenUserActivity();
|
|
1455
1716
|
Config.enableError && this.addListenJSUncaught();
|
|
1456
1717
|
Config.enableVisualTrack && this.visualTrack();
|
|
1457
1718
|
Config.enableLagTrack && this.listenPageLag();
|
|
1458
1719
|
Config.enableRecord && enableRecordFunc();
|
|
1720
|
+
Config.enableOnlinePersons && enableOnlinePersonsFunc();
|
|
1459
1721
|
this.addListenUnload();
|
|
1460
1722
|
initWindowObjectFunction();
|
|
1461
1723
|
}
|
|
@@ -1495,14 +1757,6 @@ class Track {
|
|
|
1495
1757
|
this.destroy();
|
|
1496
1758
|
});
|
|
1497
1759
|
}
|
|
1498
|
-
/**
|
|
1499
|
-
* 忽略的url
|
|
1500
|
-
* @param urls
|
|
1501
|
-
*/
|
|
1502
|
-
ignoreUrl(urls) {
|
|
1503
|
-
const someUrl = urls.some((url) => location.href.includes(url));
|
|
1504
|
-
return someUrl;
|
|
1505
|
-
}
|
|
1506
1760
|
/**
|
|
1507
1761
|
* @description 销毁监听器
|
|
1508
1762
|
*/
|
|
@@ -1525,6 +1779,7 @@ class Track {
|
|
|
1525
1779
|
this.lagTimer && clearInterval(this.lagTimer);
|
|
1526
1780
|
(_a = this.observer) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
1527
1781
|
sessionStorage.removeItem(monitorTrackSessionId);
|
|
1782
|
+
closeWebsocket('destroy');
|
|
1528
1783
|
}
|
|
1529
1784
|
}
|
|
1530
1785
|
|