monitor-track 1.13.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/index.js CHANGED
@@ -34,12 +34,16 @@ var MonitorTrack = (function (uuid, ErrorStackParser, html2canvas, rrweb, axios,
34
34
  reportUrl: '',
35
35
  projectID: '',
36
36
  maxLength: 1000,
37
- spa: false,
38
- hash: false,
37
+ spa: true,
38
+ hash: true,
39
39
  enableBehavior: true,
40
40
  enableError: true,
41
+ enableErrorScreenshot: false,
42
+ enableErrorEvent: false,
41
43
  enableVisualTrack: false,
42
- enableLagTrack: false,
44
+ enableLagTrack: true,
45
+ enableRecord: false,
46
+ enableOnlinePersons: true,
43
47
  ignore: {
44
48
  urls: [],
45
49
  errors: [],
@@ -51,7 +55,17 @@ var MonitorTrack = (function (uuid, ErrorStackParser, html2canvas, rrweb, axios,
51
55
  * @param config 配置项
52
56
  */
53
57
  function setConfig(config) {
58
+ var _a;
54
59
  Object.assign(Config, config);
60
+ if (!Config.ignore)
61
+ Config.ignore = {};
62
+ if (Array.isArray((_a = Config.ignore) === null || _a === void 0 ? void 0 : _a.errors)) {
63
+ ['ResizeObserver loop limit exceeded', 'ResizeObserver loop completed with undelivered notifications.', 'Cancel'].forEach(function (item) {
64
+ if (!Config.ignore.errors.includes(item)) {
65
+ Config.ignore.errors.push(item);
66
+ }
67
+ });
68
+ }
55
69
  }
56
70
 
57
71
  /******************************************************************************
@@ -68,6 +82,22 @@ var MonitorTrack = (function (uuid, ErrorStackParser, html2canvas, rrweb, axios,
68
82
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
69
83
  PERFORMANCE OF THIS SOFTWARE.
70
84
  ***************************************************************************** */
85
+ /* global Reflect, Promise, SuppressedError, Symbol */
86
+
87
+ var extendStatics = function(d, b) {
88
+ extendStatics = Object.setPrototypeOf ||
89
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
90
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
91
+ return extendStatics(d, b);
92
+ };
93
+
94
+ function __extends(d, b) {
95
+ if (typeof b !== "function" && b !== null)
96
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
97
+ extendStatics(d, b);
98
+ function __() { this.constructor = d; }
99
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
100
+ }
71
101
 
72
102
  var __assign = function() {
73
103
  __assign = Object.assign || function __assign(t) {
@@ -123,24 +153,26 @@ var MonitorTrack = (function (uuid, ErrorStackParser, html2canvas, rrweb, axios,
123
153
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
124
154
  };
125
155
 
126
- var version = "1.13.0";
156
+ var version = "1.15.0";
127
157
 
128
158
  var eventsMatrix = [[]];
129
- rrweb__namespace.record({
130
- emit: function (event, isCheckout) {
131
- // isCheckout 是一个标识,告诉你重新制作了快照
132
- if (isCheckout) {
133
- eventsMatrix.push([]);
134
- }
135
- if (eventsMatrix.length > 2) {
136
- eventsMatrix.shift();
137
- }
138
- var lastEvents = eventsMatrix[eventsMatrix.length - 1];
139
- lastEvents.push(event);
140
- },
141
- // 每30秒重新制作快照
142
- checkoutEveryNms: 30 * 1000
143
- });
159
+ function enableRecordFunc() {
160
+ rrweb__namespace.record({
161
+ emit: function (event, isCheckout) {
162
+ // isCheckout 是一个标识,告诉你重新制作了快照
163
+ if (isCheckout) {
164
+ eventsMatrix.push([]);
165
+ }
166
+ if (eventsMatrix.length > 2) {
167
+ eventsMatrix.shift();
168
+ }
169
+ var lastEvents = eventsMatrix[eventsMatrix.length - 1];
170
+ lastEvents.push(event);
171
+ },
172
+ // 30秒重新制作快照
173
+ checkoutEveryNms: 30 * 1000
174
+ });
175
+ }
144
176
  /**
145
177
  * @description 错误事件触发后的操作
146
178
  */
@@ -881,6 +913,8 @@ var MonitorTrack = (function (uuid, ErrorStackParser, html2canvas, rrweb, axios,
881
913
  detail: 'de',
882
914
  /** 上报时带上的请求参数 */
883
915
  requestData: 'rD',
916
+ /** 上报时带上的响应结果 */
917
+ responseBody: 'rB',
884
918
  /** 上报时带上的请求方法 */
885
919
  method: 'rM'
886
920
  },
@@ -949,7 +983,7 @@ var MonitorTrack = (function (uuid, ErrorStackParser, html2canvas, rrweb, axios,
949
983
  delete ERROR_MESSAGE_MAP[message_1];
950
984
  }, 3000);
951
985
  var p_1 = payload.p, pid_1 = payload.pid, host_1 = payload.host, bN_1 = payload.bN, pt_1 = payload.pt;
952
- if ((_c = data.error) === null || _c === void 0 ? void 0 : _c.events) {
986
+ if (((_c = data.error) === null || _c === void 0 ? void 0 : _c.events) && Config.enableErrorEvent) {
953
987
  hasErrorEvent = true;
954
988
  var errorEvent_1 = data.error.events;
955
989
  var delayTime = Math.ceil(Math.random() * 10000);
@@ -960,16 +994,18 @@ var MonitorTrack = (function (uuid, ErrorStackParser, html2canvas, rrweb, axios,
960
994
  });
961
995
  }, delayTime < 3500 ? 3500 : delayTime);
962
996
  }
963
- picturePromise = getFullScreenShoot(filename)
964
- .then(function (file) {
965
- return new Promise(function (res) {
966
- xhrFunc(file.name, data.uuid, filename, file, res, function (result) {
967
- payload.error.pic = result;
968
- }, { p: p_1, pid: pid_1, host: host_1, bN: bN_1, pt: pt_1 });
997
+ if (Config.enableErrorScreenshot) {
998
+ picturePromise = getFullScreenShoot(filename)
999
+ .then(function (file) {
1000
+ return new Promise(function (res) {
1001
+ xhrFunc(file.name, data.uuid, filename, file, res, function (result) {
1002
+ payload.error.pic = result;
1003
+ }, { p: p_1, pid: pid_1, host: host_1, bN: bN_1, pt: pt_1 });
1004
+ });
1005
+ })["catch"](function (err) {
1006
+ payload.error.picError = (err === null || err === void 0 ? void 0 : err.stack) || (err === null || err === void 0 ? void 0 : err.toString());
969
1007
  });
970
- })["catch"](function (err) {
971
- payload.error.picError = (err === null || err === void 0 ? void 0 : err.stack) || (err === null || err === void 0 ? void 0 : err.toString());
972
- });
1008
+ }
973
1009
  }
974
1010
  }
975
1011
  return picturePromise
@@ -1005,6 +1041,10 @@ var MonitorTrack = (function (uuid, ErrorStackParser, html2canvas, rrweb, axios,
1005
1041
  // 上报
1006
1042
  function report(data) {
1007
1043
  return new Promise(function (res) {
1044
+ var _a;
1045
+ if ((((_a = Config.ignore) === null || _a === void 0 ? void 0 : _a.urls) || []).some(function (url) { return location.href.includes(url); })) {
1046
+ return;
1047
+ }
1008
1048
  //在帧的空闲时间上报
1009
1049
  var dataCopy = JSON.parse(JSON.stringify(data));
1010
1050
  if (typeof window.requestIdleCallback === 'function') {
@@ -1266,175 +1306,456 @@ var MonitorTrack = (function (uuid, ErrorStackParser, html2canvas, rrweb, axios,
1266
1306
  dpr: window.devicePixelRatio
1267
1307
  });
1268
1308
  }
1269
- function ajaxEventTrigger(event) {
1270
- var ajaxEvent = new CustomEvent(event, {
1271
- detail: this
1309
+
1310
+ var reconnectAndSendTimeout, websocketHeartBeatInterval, ws, userId = '';
1311
+ var remoteDebugEnable = false;
1312
+ var targetPlatform = '';
1313
+ var targetUserId = '';
1314
+ var originConsole = __assign({}, console);
1315
+ var formatConsole = function () {
1316
+ if (remoteDebugEnable)
1317
+ return;
1318
+ remoteDebugEnable = true;
1319
+ window.console = __assign({}, originConsole);
1320
+ var arr = ['debug', 'log', 'info', 'warn', 'error'];
1321
+ arr.forEach(function (item) {
1322
+ //@ts-ignore
1323
+ window.console[item] = function () {
1324
+ var args = [];
1325
+ for (var _i = 0; _i < arguments.length; _i++) {
1326
+ args[_i] = arguments[_i];
1327
+ }
1328
+ //@ts-ignore
1329
+ originConsole[item].apply(originConsole, args);
1330
+ var data = {
1331
+ origin: 'console',
1332
+ level: item,
1333
+ userId: userId,
1334
+ time: new Date().toLocaleString(),
1335
+ page: location.href,
1336
+ content: '',
1337
+ targetPlatform: targetPlatform,
1338
+ targetUserId: targetUserId
1339
+ };
1340
+ try {
1341
+ var content = JSON.stringify(args);
1342
+ data.content = content;
1343
+ }
1344
+ catch (err) {
1345
+ data.content = 'console内容解析错误: ' + err.stack || err.message || err.toString();
1346
+ }
1347
+ var msg = {
1348
+ type: WEBSOCKET_TYPE.DEBUG_INFO_UPLOAD,
1349
+ userId: userId,
1350
+ platform: 'monitor-track-sdk',
1351
+ data: data
1352
+ };
1353
+ wsSendFunc(msg);
1354
+ };
1272
1355
  });
1273
- window.dispatchEvent(ajaxEvent);
1274
- }
1275
- var OldXHR = window.XMLHttpRequest;
1276
- function newXHR() {
1277
- var realXHR = new OldXHR();
1278
- realXHR.addEventListener('loadstart', function () {
1279
- ajaxEventTrigger.call(this, 'ajaxLoadStart');
1280
- }, false);
1281
- realXHR.addEventListener('loadend', function () {
1282
- ajaxEventTrigger.call(this, 'ajaxLoadEnd');
1283
- }, false);
1284
- // 此处的捕获的异常会连日志接口也一起捕获,如果日志上报接口异常了,就会导致死循环了。
1285
- realXHR.onerror = function (e) {
1286
- // eslint-disable-next-line no-console
1287
- console.warn('realXHR.onerror, e', e);
1288
- };
1289
- return realXHR;
1356
+ };
1357
+ var resetConsole = function () {
1358
+ window.console = originConsole;
1359
+ remoteDebugEnable = false;
1360
+ };
1361
+ var uploadRequest = function (requestInfo) {
1362
+ // console.log('monitor-track-sdk: uploadRequest remoteDebugEnable', remoteDebugEnable);
1363
+ if (remoteDebugEnable) {
1364
+ var data = {
1365
+ origin: 'request',
1366
+ userId: userId,
1367
+ time: new Date().toLocaleString(),
1368
+ page: location.href,
1369
+ content: requestInfo,
1370
+ targetPlatform: targetPlatform,
1371
+ targetUserId: targetUserId
1372
+ };
1373
+ var msg = {
1374
+ type: WEBSOCKET_TYPE.DEBUG_INFO_UPLOAD,
1375
+ userId: userId,
1376
+ platform: 'monitor-track-sdk',
1377
+ data: data
1378
+ };
1379
+ // console.log('monitor-track-sdk: request-upload sent');
1380
+ wsSendFunc(msg);
1381
+ }
1382
+ };
1383
+ function enableOnlinePersonsFunc() {
1384
+ initWebsocket();
1290
1385
  }
1291
- /**
1292
- * 页面接口请求监控
1293
- */
1294
- var tempUrlInfo = {};
1295
- var recordXMLHttpRequestLog = function (XMLHttpRequestTimeout) {
1296
- XMLHttpRequestTimeout = typeof XMLHttpRequestTimeout === 'number' ? XMLHttpRequestTimeout : 1000;
1297
- var timeRecordArray = [];
1298
- //@ts-ignore
1299
- window.__XMLHttpRequest__ = window.XMLHttpRequest;
1300
- //@ts-ignore
1301
- window.XMLHttpRequest = newXHR;
1302
- window.addEventListener('ajaxLoadStart', function (e) {
1303
- var tempObj = {
1304
- timeStamp: new Date().getTime(),
1305
- event: e
1386
+ var WEBSOCKET_TYPE = {
1387
+ TRY_CONNECT: 'try-connect',
1388
+ CHECK_CONNECT: 'check-connect',
1389
+ PING: 'ping',
1390
+ PONG: 'pong',
1391
+ REPLY_SERVER_HEART_BEAT: 'reply-server-heart-beat',
1392
+ SOCKET_HEART_BEAT: 'socket-heart-beat',
1393
+ RESPONSE_DATE: 'response-date',
1394
+ REMOTE_DEBUG_ENABLE: 'remote-debug-enable',
1395
+ DEBUG_INFO_UPLOAD: 'debug-info-upload',
1396
+ REPlY_MESSAGE: 'reply-message'
1397
+ };
1398
+ var mounted = false;
1399
+ var initWebsocket = function () {
1400
+ if (window.WebSocket) {
1401
+ userId = localStorage.getItem('username') || getUid();
1402
+ closeWebsocket('');
1403
+ websocketHeartBeatInterval = setInterval(reconnectAndSend, 30000);
1404
+ var isLocal = Config.reportUrl.includes('http://');
1405
+ ws = new WebSocket("ws".concat(isLocal ? '' : 's', "://").concat(Config.reportUrl.replace(isLocal ? 'http://' : 'https://', '').replace('/s/r', ''), "?type=monitor-dsk"));
1406
+ ws.onopen = function () { return openWS(); };
1407
+ ws.onmessage = function (data) { return incomingMessage(data); };
1408
+ ws.onerror = function () {
1409
+ ws.close(1000);
1410
+ if (websocketHeartBeatInterval)
1411
+ clearInterval(websocketHeartBeatInterval);
1412
+ websocketHeartBeatInterval = setInterval(reconnectAndSend, 10000);
1306
1413
  };
1307
- timeRecordArray.push(tempObj);
1308
- });
1309
- window.addEventListener('ajaxLoadEnd', function () {
1310
- var timeRecordArrayCopy = [].concat(timeRecordArray);
1311
- var _loop_1 = function (i) {
1312
- if (timeRecordArrayCopy[i].event.detail && timeRecordArrayCopy[i].event.detail.status > 0) {
1313
- var currentTime = new Date().getTime();
1314
- var _a = timeRecordArrayCopy[i].event.detail, responseURL_1 = _a.responseURL, status_1 = _a.status, statusText = _a.statusText, timeStamp = _a.timeStamp;
1315
- var previousTime = timeStamp || timeRecordArrayCopy[i].timeStamp;
1316
- var loadTime = currentTime - previousTime;
1317
- var request = {
1318
- requestType: 'xhr',
1319
- responseURL: responseURL_1,
1320
- status: status_1,
1321
- loadTime: loadTime,
1322
- statusText: statusText,
1323
- reason: '',
1324
- detail: '',
1325
- requestData: '',
1326
- method: ''
1327
- };
1328
- if (loadTime && loadTime > XMLHttpRequestTimeout) {
1329
- request.reason = 'slow';
1330
- request.detail = "request is too slow, XMLHttpRequestTimeout: ".concat(loadTime);
1331
- }
1332
- else if (status_1 && status_1 >= 300 && statusText && statusText.toLowerCase() !== 'ok') {
1333
- request.reason = 'failed';
1334
- request.detail = "request is failed, status: ".concat(status_1, ", statusText: ").concat(statusText);
1414
+ ws.onclose = function () {
1415
+ ws.close(1000);
1416
+ if (websocketHeartBeatInterval)
1417
+ clearInterval(websocketHeartBeatInterval);
1418
+ websocketHeartBeatInterval = setInterval(reconnectAndSend, 10000);
1419
+ };
1420
+ if (!mounted) {
1421
+ reconnectNetwork();
1422
+ mounted = true;
1423
+ }
1424
+ }
1425
+ };
1426
+ var openWS = function () {
1427
+ var data = getReport();
1428
+ var page = data.page, projectID = data.projectID, host = data.host, pageTitle = data.pageTitle;
1429
+ var msg = {
1430
+ type: WEBSOCKET_TYPE.TRY_CONNECT,
1431
+ userId: userId,
1432
+ platform: 'monitor-track-sdk',
1433
+ data: {
1434
+ p: page,
1435
+ pid: projectID,
1436
+ host: host,
1437
+ pt: pageTitle,
1438
+ platform: 'web'
1439
+ }
1440
+ };
1441
+ wsSendFunc(msg);
1442
+ };
1443
+ var reconnectAndSend = function () {
1444
+ try {
1445
+ if (ws.readyState !== 1) {
1446
+ reconnectSocket();
1447
+ }
1448
+ else {
1449
+ var msg = {
1450
+ type: WEBSOCKET_TYPE.CHECK_CONNECT,
1451
+ userId: userId,
1452
+ data: WEBSOCKET_TYPE.PING,
1453
+ date: Date.now()
1454
+ };
1455
+ wsSendFunc(msg, 'reconnectAndSend');
1456
+ // 20秒超时,如果收不到服务端pong响应则表示服务端已主动断开连接,此时需客户端重新开启websocket连接
1457
+ reconnectAndSendTimeout = setTimeout(function () {
1458
+ reconnectSocket();
1459
+ }, 20000);
1460
+ }
1461
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1462
+ }
1463
+ catch (_err) {
1464
+ // console.error('monitor-track-sdk: reconnectAndSend err', err);
1465
+ }
1466
+ };
1467
+ var closeWebsocket = function (info) {
1468
+ if (ws) {
1469
+ ws.onopen = null;
1470
+ ws.onmessage = null;
1471
+ ws.onerror = null;
1472
+ ws.onclose = null;
1473
+ if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) {
1474
+ ws.close(1000, info);
1475
+ }
1476
+ //@ts-ignore
1477
+ ws = null; // 释放引用
1478
+ }
1479
+ if (websocketHeartBeatInterval)
1480
+ clearInterval(websocketHeartBeatInterval);
1481
+ };
1482
+ var reconnectSocket = function () {
1483
+ // console.warn('monitor-track-sdk: 正在重新建立websocket连接...');
1484
+ initWebsocket();
1485
+ };
1486
+ var incomingMessage = function (e) { return __awaiter(void 0, void 0, void 0, function () {
1487
+ var data, msg, _a, enable, platform, userId_1;
1488
+ return __generator(this, function (_b) {
1489
+ data = {};
1490
+ try {
1491
+ data = JSON.parse(e.data);
1492
+ // console.info('incomingMessage data', data);
1493
+ switch (data.type) {
1494
+ case WEBSOCKET_TYPE.PONG:
1495
+ // console.info('monitor-track-sdk: incomingMessage 响应客户端的心跳: ping => pong');
1496
+ clearTimeout(reconnectAndSendTimeout);
1497
+ break;
1498
+ case WEBSOCKET_TYPE.SOCKET_HEART_BEAT: {
1499
+ msg = {
1500
+ type: WEBSOCKET_TYPE.CHECK_CONNECT,
1501
+ userId: userId,
1502
+ data: WEBSOCKET_TYPE.REPLY_SERVER_HEART_BEAT,
1503
+ date: Date.now()
1504
+ };
1505
+ wsSendFunc(msg, 'socket-heart-beat reply-server-heart-beat');
1506
+ break;
1335
1507
  }
1336
- else ;
1337
- if (request.reason) {
1338
- if (!tempUrlInfo[responseURL_1]) {
1339
- tempUrlInfo[responseURL_1] = true;
1340
- setTimeout(function () {
1341
- delete tempUrlInfo[responseURL_1];
1342
- }, 10);
1343
- setReportValue('error', null);
1344
- report(__assign(__assign({}, getReport()), {
1345
- page: location.href,
1346
- originPage: location.href,
1347
- type: 'request',
1348
- req: request
1349
- }));
1508
+ case WEBSOCKET_TYPE.RESPONSE_DATE:
1509
+ // console.info(`monitor-track-sdk: incomingMessage WS connected, Roundtrip time: ${Date.now() - data.data} ms`);
1510
+ break;
1511
+ case WEBSOCKET_TYPE.REMOTE_DEBUG_ENABLE: {
1512
+ _a = data.data, enable = _a.enable, platform = _a.platform, userId_1 = _a.userId;
1513
+ if (enable && platform && userId_1) {
1514
+ targetPlatform = platform;
1515
+ targetUserId = userId_1;
1516
+ formatConsole();
1517
+ }
1518
+ else {
1519
+ resetConsole();
1350
1520
  }
1521
+ break;
1522
+ }
1523
+ case WEBSOCKET_TYPE.REPlY_MESSAGE: {
1524
+ // eslint-disable-next-line no-console
1525
+ console.info('incomingMessage REPlY_MESSAGE, data: ', data.data);
1526
+ break;
1351
1527
  }
1528
+ default:
1529
+ // console.error('incomingMessage default error', data);
1530
+ break;
1352
1531
  }
1353
- // 当前请求成功后就在数组中移除掉
1354
- timeRecordArray.splice(i, 1);
1355
- };
1356
- for (var i = 0; i < timeRecordArrayCopy.length; i++) {
1357
- _loop_1(i);
1358
1532
  }
1533
+ catch (err) {
1534
+ // eslint-disable-next-line no-console
1535
+ console.error('monitor-track-sdk incomingMessage JSON.parse', err);
1536
+ }
1537
+ return [2 /*return*/];
1359
1538
  });
1539
+ }); };
1540
+ var wsSendFunc = function (msg, _info) {
1541
+ if (ws.readyState === 1) {
1542
+ msg.platform = 'monitor-track-sdk';
1543
+ var message = JSON.stringify(msg);
1544
+ ws.send(message);
1545
+ }
1546
+ else {
1547
+ // console.warn('monitor-track-sdk: window.ws.readyState === 1 info', info);
1548
+ reconnectSocket();
1549
+ }
1360
1550
  };
1361
- var hackFetch = function (XMLHttpRequestTimeout) {
1362
- XMLHttpRequestTimeout = typeof XMLHttpRequestTimeout === 'number' ? XMLHttpRequestTimeout : 1000;
1363
- if (typeof window.fetch === 'function') {
1364
- var __fetch__1 = window.fetch;
1365
- window.__fetch__ = __fetch__1;
1366
- //@ts-ignore
1367
- window.fetch = function (t) {
1368
- var args = [];
1369
- for (var _i = 1; _i < arguments.length; _i++) {
1370
- args[_i - 1] = arguments[_i];
1551
+ var reconnectNetwork = function () {
1552
+ var networkFlag = false;
1553
+ var debounceTimeout = null;
1554
+ document.addEventListener('offline', function () {
1555
+ // 断开网络
1556
+ try {
1557
+ // console.info('monitor-track-sdk: 客户端网络已断开,正在关闭websocket');
1558
+ ws.close(1000);
1559
+ networkFlag = true;
1560
+ debounceTimeout = setTimeout(function () {
1561
+ // console.warn('monitor-track-sdk: reconnectNetwork offline 无法访问网络');
1562
+ // message.error('无法访问网络');
1563
+ }, 5000);
1564
+ }
1565
+ catch (err) {
1566
+ // console.error('monitor-track-sdk: addEventListener offline after setTimeout', err);
1567
+ }
1568
+ }, false);
1569
+ document.addEventListener('online', function () {
1570
+ // 连接到网络
1571
+ try {
1572
+ if (networkFlag === true) {
1573
+ clearTimeout(debounceTimeout);
1574
+ // console.info('monitor-track-sdk: addEventListener reconnectNetwork online');
1575
+ // message.success('网络已恢复');
1576
+ networkFlag = false;
1577
+ // console.warn('monitor-track-sdk: addEventListener online websocket 正在重新建立连接...');
1578
+ initWebsocket();
1371
1579
  }
1372
- var begin = Date.now();
1373
- //禁用数组的扩展运算符,否则portal的生产环境会报Uncaught TypeError: Object(...) is not a function,
1374
- //编译后的__spreadArray函数有问题,而这个函数来自于tslib.具体报错原因不知.
1375
- //其他平台使用数组的扩展运算符没有问题,比如前端监控平台的管理界面
1376
- var params = [].concat(t).concat(args);
1377
- return __fetch__1
1378
- .apply(window, params)
1379
- .then(function (res) {
1380
- var response = res.clone();
1381
- var headers = response.headers;
1382
- if (headers && typeof headers.get === 'function') {
1383
- var ct = headers.get('content-type');
1384
- if (ct && !/(text)|(json)/.test(ct)) {
1385
- return res;
1386
- }
1580
+ }
1581
+ catch (err) {
1582
+ // console.error('monitor-track-sdk: document.addEventListener online', err);
1583
+ }
1584
+ }, false);
1585
+ };
1586
+
1587
+ var xhrTimeout = 2500;
1588
+ var fetchTimeout = 2500;
1589
+ var maxContentLength = 1000;
1590
+ // 保存原始 XMLHttpRequest
1591
+ var OriginalXHR = window.XMLHttpRequest;
1592
+ // 创建增强版的 XMLHttpRequest
1593
+ var InterceptedXHR = /** @class */ (function (_super) {
1594
+ __extends(InterceptedXHR, _super);
1595
+ function InterceptedXHR() {
1596
+ var _this = _super.call(this) || this;
1597
+ _this.requestInfo = {
1598
+ requestType: 'xhr',
1599
+ method: '',
1600
+ responseURL: '',
1601
+ requestData: null,
1602
+ responseBody: null,
1603
+ status: 0,
1604
+ startTime: Date.now(),
1605
+ loadTime: 0,
1606
+ statusText: '',
1607
+ reason: '',
1608
+ detail: ''
1609
+ };
1610
+ _this.setupInterceptors();
1611
+ return _this;
1612
+ }
1613
+ InterceptedXHR.prototype.open = function (method, url, async, username, password) {
1614
+ if (async === void 0) { async = true; }
1615
+ _super.prototype.open.call(this, method, url, async, username, password);
1616
+ this.requestInfo.method = method;
1617
+ this.requestInfo.responseURL = url;
1618
+ };
1619
+ // eslint-disable-next-line no-undef
1620
+ InterceptedXHR.prototype.send = function (body) {
1621
+ _super.prototype.send.call(this, body);
1622
+ try {
1623
+ this.requestInfo.requestData =
1624
+ typeof body === 'object' && body
1625
+ ? JSON.stringify(body).slice(0, maxContentLength)
1626
+ : typeof body === 'string'
1627
+ ? body.slice(0, maxContentLength)
1628
+ : body || '';
1629
+ }
1630
+ catch (err) {
1631
+ // eslint-disable-next-line no-console
1632
+ console.error('xhr send err: ', err, 'body', body);
1633
+ }
1634
+ this.requestInfo.startTime = Date.now();
1635
+ };
1636
+ InterceptedXHR.prototype.setupInterceptors = function () {
1637
+ var _this = this;
1638
+ this.addEventListener('load', function () {
1639
+ try {
1640
+ _this.requestInfo.status = _this.status;
1641
+ _this.requestInfo.responseBody = _this.responseText.slice(0, maxContentLength);
1642
+ _this.requestInfo.loadTime = Date.now() - _this.requestInfo.startTime;
1643
+ _this.requestInfo.statusText = _this.statusText;
1644
+ if (_this.requestInfo.loadTime > xhrTimeout) {
1645
+ _this.requestInfo.reason = 'slow';
1646
+ _this.requestInfo.detail = "request is too slow, XMLHttpRequestTimeout: ".concat(_this.requestInfo.loadTime);
1387
1647
  }
1388
- var loadTime = Date.now() - begin;
1389
- response
1390
- .text()
1391
- .then(function (result) {
1392
- var url = response.url, status = response.status, statusText = response.statusText, ok = response.ok;
1393
- var request = {
1648
+ if (_this.status >= 400) {
1649
+ _this.requestInfo.reason = 'failed';
1650
+ _this.requestInfo.detail = "request is failed, status: ".concat(_this.status, ", statusText: ").concat(_this.statusText);
1651
+ }
1652
+ if (_this.requestInfo.reason) {
1653
+ setReportValue('error', null);
1654
+ report(__assign(__assign({}, getReport()), {
1655
+ page: location.href,
1656
+ originPage: location.href,
1657
+ type: 'request',
1658
+ req: _this.requestInfo
1659
+ }));
1660
+ }
1661
+ uploadRequest(_this.requestInfo);
1662
+ }
1663
+ catch (err) {
1664
+ // eslint-disable-next-line no-console
1665
+ console.error('xhr load err: ', err, 'this.requestInfo', _this.requestInfo);
1666
+ }
1667
+ });
1668
+ this.addEventListener('error', function () {
1669
+ // console.error('❌ 请求失败:', this.requestInfo);
1670
+ });
1671
+ };
1672
+ return InterceptedXHR;
1673
+ }(OriginalXHR));
1674
+ var recordXMLHttpRequest = function (XMLHttpRequestTimeout) {
1675
+ xhrTimeout = XMLHttpRequestTimeout;
1676
+ // 重写全局 XMLHttpRequest
1677
+ window.XMLHttpRequest = InterceptedXHR;
1678
+ };
1679
+ var originalFetch = window.fetch;
1680
+ // eslint-disable-next-line no-undef
1681
+ var fetchFUnc = function (input, init) {
1682
+ return __awaiter(this, void 0, void 0, function () {
1683
+ var url, options, requestInfo, response, clonedResponse, responseBody, e_1, err_1;
1684
+ return __generator(this, function (_a) {
1685
+ switch (_a.label) {
1686
+ case 0:
1687
+ url = typeof input === 'string' ? input : input.toString();
1688
+ options = init || {};
1689
+ requestInfo = {
1394
1690
  requestType: 'fetch',
1691
+ method: options.method || 'GET',
1395
1692
  responseURL: url,
1396
- status: status,
1397
- loadTime: loadTime,
1398
- statusText: statusText,
1693
+ requestData: typeof options.body === 'object' && options.body ? JSON.stringify(options.body).slice(0, maxContentLength) : options.body || '',
1694
+ responseBody: '',
1695
+ status: 0,
1696
+ startTime: Date.now(),
1697
+ loadTime: 0,
1698
+ statusText: '',
1399
1699
  reason: '',
1400
- detail: '',
1401
- requestData: '',
1402
- method: ''
1700
+ detail: ''
1403
1701
  };
1404
- if (!ok || status >= 300) {
1405
- request.reason = 'failed';
1406
- request.detail = "request is failed, status: ".concat(status, ", statusText: ").concat(statusText);
1702
+ return [4 /*yield*/, originalFetch(input, init)];
1703
+ case 1:
1704
+ response = _a.sent();
1705
+ _a.label = 2;
1706
+ case 2:
1707
+ _a.trys.push([2, 7, , 8]);
1708
+ clonedResponse = response.clone();
1709
+ requestInfo.status = response.status;
1710
+ requestInfo.loadTime = Date.now() - requestInfo.startTime;
1711
+ requestInfo.statusText = response.statusText;
1712
+ if (!response.ok) {
1713
+ requestInfo.reason = 'failed';
1714
+ requestInfo.detail = "request is failed, status: ".concat(response.status, ", statusText: ").concat(response.statusText);
1407
1715
  }
1408
- else if (loadTime > XMLHttpRequestTimeout) {
1409
- request.reason = 'slow';
1410
- request.detail = "request is too slow, XMLHttpRequestTimeout: ".concat(loadTime, ", result: ").concat(result === null || result === void 0 ? void 0 : result.slice(0, 500));
1411
- }
1412
- if (request.reason) {
1413
- if (!tempUrlInfo[url]) {
1414
- tempUrlInfo[url] = true;
1415
- setTimeout(function () {
1416
- delete tempUrlInfo[url];
1417
- }, 10);
1418
- setReportValue('error', null);
1419
- report(__assign(__assign({}, getReport()), {
1420
- page: location.href,
1421
- originPage: location.href,
1422
- type: 'request',
1423
- req: request
1424
- }));
1716
+ else {
1717
+ if (requestInfo.loadTime > fetchTimeout) {
1718
+ requestInfo.reason = 'slow';
1719
+ requestInfo.detail = "request is too slow, XMLHttpRequestTimeout: ".concat(requestInfo.loadTime);
1425
1720
  }
1426
1721
  }
1427
- })["catch"](function (err) {
1722
+ _a.label = 3;
1723
+ case 3:
1724
+ _a.trys.push([3, 5, , 6]);
1725
+ return [4 /*yield*/, clonedResponse.text()];
1726
+ case 4:
1727
+ responseBody = _a.sent();
1728
+ requestInfo.responseBody = responseBody.slice(0, maxContentLength);
1729
+ return [3 /*break*/, 6];
1730
+ case 5:
1731
+ e_1 = _a.sent();
1732
+ requestInfo.responseBody = (e_1 === null || e_1 === void 0 ? void 0 : e_1.message) || (e_1 === null || e_1 === void 0 ? void 0 : e_1.stack) || (e_1 === null || e_1 === void 0 ? void 0 : e_1.toString());
1733
+ return [3 /*break*/, 6];
1734
+ case 6:
1735
+ if (requestInfo.reason) {
1736
+ setReportValue('error', null);
1737
+ report(__assign(__assign({}, getReport()), {
1738
+ page: location.href,
1739
+ originPage: location.href,
1740
+ type: 'request',
1741
+ req: requestInfo
1742
+ }));
1743
+ }
1744
+ uploadRequest(requestInfo);
1745
+ return [3 /*break*/, 8];
1746
+ case 7:
1747
+ err_1 = _a.sent();
1428
1748
  // eslint-disable-next-line no-console
1429
- console.log('hackFetch response.text() err', err);
1430
- });
1431
- return res;
1432
- })["catch"](function (err) {
1433
- // eslint-disable-next-line no-console
1434
- console.log('hackFetch err', err);
1435
- });
1436
- };
1437
- }
1749
+ console.error(' 获取响应数据失败, requestInfo: ', requestInfo, 'err: ', err_1);
1750
+ return [3 /*break*/, 8];
1751
+ case 8: return [2 /*return*/, response];
1752
+ }
1753
+ });
1754
+ });
1755
+ };
1756
+ var recordFetch = function (XMLHttpRequestTimeout) {
1757
+ fetchTimeout = XMLHttpRequestTimeout;
1758
+ window.fetch = fetchFUnc;
1438
1759
  };
1439
1760
 
1440
1761
  var Track = /** @class */ (function () {
@@ -1450,8 +1771,10 @@ var MonitorTrack = (function (uuid, ErrorStackParser, html2canvas, rrweb, axios,
1450
1771
  this.listenPageLag = function () {
1451
1772
  _this.observer = new PerformanceObserver(function (list) {
1452
1773
  list.getEntries().forEach(function (entry) {
1453
- if (entry.duration > (Config.lagTimeout || 400)) {
1774
+ if (entry.duration > (Config.lagTimeout || 800)) {
1454
1775
  handlePageLag(entry.duration);
1776
+ // eslint-disable-next-line no-console
1777
+ console.log('监测到页面卡顿:', entry.duration, entry, location.href);
1455
1778
  }
1456
1779
  });
1457
1780
  });
@@ -1459,7 +1782,6 @@ var MonitorTrack = (function (uuid, ErrorStackParser, html2canvas, rrweb, axios,
1459
1782
  };
1460
1783
  }
1461
1784
  Track.prototype.init = function (config) {
1462
- var _a;
1463
1785
  // 是否开启日志收集
1464
1786
  if (!config || !config.enable) {
1465
1787
  return;
@@ -1476,18 +1798,17 @@ var MonitorTrack = (function (uuid, ErrorStackParser, html2canvas, rrweb, axios,
1476
1798
  console.warn('缺少上报地址!');
1477
1799
  return;
1478
1800
  }
1479
- if (this.ignoreUrl(((_a = config === null || config === void 0 ? void 0 : config.ignore) === null || _a === void 0 ? void 0 : _a.urls) || [])) {
1480
- return;
1481
- }
1482
1801
  setConfig(config);
1483
1802
  initReport();
1484
- recordXMLHttpRequestLog(config.XMLHttpRequestTimeout);
1485
- hackFetch(config.XMLHttpRequestTimeout);
1803
+ recordXMLHttpRequest(config.XMLHttpRequestTimeout || 2500);
1804
+ recordFetch(config.XMLHttpRequestTimeout || 2500);
1486
1805
  Config.spa && this.addListenRouterChange();
1487
1806
  Config.enableBehavior && this.addListenUserActivity();
1488
1807
  Config.enableError && this.addListenJSUncaught();
1489
1808
  Config.enableVisualTrack && this.visualTrack();
1490
1809
  Config.enableLagTrack && this.listenPageLag();
1810
+ Config.enableRecord && enableRecordFunc();
1811
+ Config.enableOnlinePersons && enableOnlinePersonsFunc();
1491
1812
  this.addListenUnload();
1492
1813
  initWindowObjectFunction();
1493
1814
  };
@@ -1528,14 +1849,6 @@ var MonitorTrack = (function (uuid, ErrorStackParser, html2canvas, rrweb, axios,
1528
1849
  _this.destroy();
1529
1850
  });
1530
1851
  };
1531
- /**
1532
- * 忽略的url
1533
- * @param urls
1534
- */
1535
- Track.prototype.ignoreUrl = function (urls) {
1536
- var someUrl = urls.some(function (url) { return location.href.includes(url); });
1537
- return someUrl;
1538
- };
1539
1852
  /**
1540
1853
  * @description 销毁监听器
1541
1854
  */
@@ -1558,6 +1871,7 @@ var MonitorTrack = (function (uuid, ErrorStackParser, html2canvas, rrweb, axios,
1558
1871
  this.lagTimer && clearInterval(this.lagTimer);
1559
1872
  (_a = this.observer) === null || _a === void 0 ? void 0 : _a.disconnect();
1560
1873
  sessionStorage.removeItem(monitorTrackSessionId);
1874
+ closeWebsocket('destroy');
1561
1875
  };
1562
1876
  return Track;
1563
1877
  }());