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/cjs/index.js CHANGED
@@ -40,8 +40,8 @@ const Config = {
40
40
  reportUrl: '',
41
41
  projectID: '',
42
42
  maxLength: 1000,
43
- spa: false,
44
- hash: false,
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.14.0";
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
- function ajaxEventTrigger(event) {
1241
- const ajaxEvent = new CustomEvent(event, {
1242
- detail: this,
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
- window.dispatchEvent(ajaxEvent);
1245
- }
1246
- const OldXHR = window.XMLHttpRequest;
1247
- function newXHR() {
1248
- const realXHR = new OldXHR();
1249
- realXHR.addEventListener('loadstart', function () {
1250
- ajaxEventTrigger.call(this, 'ajaxLoadStart');
1251
- }, false);
1252
- realXHR.addEventListener('loadend', function () {
1253
- ajaxEventTrigger.call(this, 'ajaxLoadEnd');
1254
- }, false);
1255
- // 此处的捕获的异常会连日志接口也一起捕获,如果日志上报接口异常了,就会导致死循环了。
1256
- realXHR.onerror = function (e) {
1257
- // eslint-disable-next-line no-console
1258
- console.warn('realXHR.onerror, e', e);
1259
- };
1260
- return realXHR;
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
- const tempUrlInfo = {};
1266
- const recordXMLHttpRequestLog = (XMLHttpRequestTimeout) => {
1267
- XMLHttpRequestTimeout = typeof XMLHttpRequestTimeout === 'number' ? XMLHttpRequestTimeout : 1000;
1268
- const timeRecordArray = [];
1269
- //@ts-ignore
1270
- window.__XMLHttpRequest__ = window.XMLHttpRequest;
1271
- //@ts-ignore
1272
- window.XMLHttpRequest = newXHR;
1273
- window.addEventListener('ajaxLoadStart', function (e) {
1274
- const tempObj = {
1275
- timeStamp: new Date().getTime(),
1276
- event: e,
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
- timeRecordArray.push(tempObj);
1279
- });
1280
- window.addEventListener('ajaxLoadEnd', function () {
1281
- const timeRecordArrayCopy = [].concat(timeRecordArray);
1282
- for (let i = 0; i < timeRecordArrayCopy.length; i++) {
1283
- if (timeRecordArrayCopy[i].event.detail && timeRecordArrayCopy[i].event.detail.status > 0) {
1284
- const currentTime = new Date().getTime();
1285
- const { responseURL, status, statusText, timeStamp } = timeRecordArrayCopy[i].event.detail;
1286
- const previousTime = timeStamp || timeRecordArrayCopy[i].timeStamp;
1287
- const loadTime = currentTime - previousTime;
1288
- const request = {
1289
- requestType: 'xhr',
1290
- responseURL,
1291
- status,
1292
- loadTime,
1293
- statusText,
1294
- reason: '',
1295
- detail: '',
1296
- requestData: '',
1297
- method: '',
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
- if (loadTime && loadTime > XMLHttpRequestTimeout) {
1300
- request.reason = 'slow';
1301
- request.detail = `request is too slow, XMLHttpRequestTimeout: ${loadTime}`;
1302
- }
1303
- else if (status && status >= 300 && statusText && statusText.toLowerCase() !== 'ok') {
1304
- request.reason = 'failed';
1305
- request.detail = `request is failed, status: ${status}, statusText: ${statusText}`;
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
- if (request.reason) {
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
- timeRecordArray.splice(i, 1);
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 hackFetch = (XMLHttpRequestTimeout) => {
1330
- XMLHttpRequestTimeout = typeof XMLHttpRequestTimeout === 'number' ? XMLHttpRequestTimeout : 1000;
1331
- if (typeof window.fetch === 'function') {
1332
- const __fetch__ = window.fetch;
1333
- window.__fetch__ = __fetch__;
1334
- //@ts-ignore
1335
- window.fetch = function (t, ...args) {
1336
- const begin = Date.now();
1337
- //禁用数组的扩展运算符,否则portal的生产环境会报Uncaught TypeError: Object(...) is not a function,
1338
- //编译后的__spreadArray函数有问题,而这个函数来自于tslib.具体报错原因不知.
1339
- //其他平台使用数组的扩展运算符没有问题,比如前端监控平台的管理界面
1340
- const params = [].concat(t).concat(args);
1341
- return __fetch__
1342
- .apply(window, params)
1343
- .then(function (res) {
1344
- const response = res.clone();
1345
- const headers = response.headers;
1346
- if (headers && typeof headers.get === 'function') {
1347
- const ct = headers.get('content-type');
1348
- if (ct && !/(text)|(json)/.test(ct)) {
1349
- return res;
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
- const loadTime = Date.now() - begin;
1353
- response
1354
- .text()
1355
- .then(function (result) {
1356
- const { url, status, statusText, ok } = response;
1357
- const request = {
1358
- requestType: 'fetch',
1359
- responseURL: url,
1360
- status,
1361
- loadTime,
1362
- statusText,
1363
- reason: '',
1364
- detail: '',
1365
- requestData: '',
1366
- method: '',
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.log('hackFetch err', err);
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
- recordXMLHttpRequestLog(config.XMLHttpRequestTimeout);
1452
- hackFetch(config.XMLHttpRequestTimeout);
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