sobey-monitor-sdk 1.1.3 → 1.1.5

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/dist/index.umd.js CHANGED
@@ -280,13 +280,22 @@
280
280
  * 策略:优先使用 sendBeacon(更可靠),不支持或失败时降级为 fetch
281
281
  */
282
282
  doSend(data) {
283
+ // 检查配置是否已初始化
284
+ if (!config.isInitialized()) {
285
+ // 配置未初始化,数据放回缓冲区等待下次发送
286
+ this.buffer.unshift(...data);
287
+ this.scheduleFlush();
288
+ return;
289
+ }
283
290
  const cfg = config.get();
284
291
  const dsn = cfg.dsn;
285
- // dsn 未配置,跳过发送
292
+ // dsn 未配置,将数据放回缓冲区等待下次发送
286
293
  if (!dsn) {
287
294
  if (cfg.debug) {
288
- console.warn('[Monitor] dsn not configured, skip sending');
295
+ console.warn('[Monitor] dsn not configured, buffering data for later');
289
296
  }
297
+ this.buffer.unshift(...data);
298
+ this.scheduleFlush();
290
299
  return;
291
300
  }
292
301
  const payload = JSON.stringify(data);
@@ -407,25 +416,83 @@
407
416
  }
408
417
  }
409
418
  /**
410
- * 发送早期缓存的数据
419
+ * 发送早期缓存的数据(根据最新配置过滤)
411
420
  */
412
421
  flushEarlyBuffer() {
422
+ const cfg = config.get();
423
+ let skippedCount = 0;
424
+ // 全局开关检查:如果 enabled 为 false,清空缓存不上报
425
+ if (cfg.enabled === false) {
426
+ const totalCount = this.earlyBuffer.length;
427
+ this.earlyBuffer = [];
428
+ if (cfg.debug) {
429
+ console.log(`[Monitor] SDK disabled, discarded ${totalCount} early buffered items`);
430
+ }
431
+ return;
432
+ }
413
433
  while (this.earlyBuffer.length > 0) {
414
434
  const item = this.earlyBuffer.shift();
415
435
  if (!item)
416
436
  continue;
437
+ // 根据最新配置过滤数据
417
438
  switch (item.type) {
418
439
  case 'error':
440
+ // 检查错误监控是否启用
441
+ if (cfg.error?.enabled === false) {
442
+ skippedCount++;
443
+ continue;
444
+ }
445
+ // 根据错误类型检查具体开关
446
+ const errorType = item.data?.type;
447
+ if (errorType === 'js_error' && cfg.error?.jsError === false) {
448
+ skippedCount++;
449
+ continue;
450
+ }
451
+ if (errorType === 'promise_error' && cfg.error?.promiseError === false) {
452
+ skippedCount++;
453
+ continue;
454
+ }
455
+ if (errorType === 'resource_error' && cfg.error?.resourceError === false) {
456
+ skippedCount++;
457
+ continue;
458
+ }
459
+ if (errorType === 'http_error' && cfg.error?.httpError === false) {
460
+ skippedCount++;
461
+ continue;
462
+ }
419
463
  this.reportError(item.data);
420
464
  break;
421
465
  case 'performance':
466
+ // 检查性能监控是否启用
467
+ if (cfg.performance?.enabled === false) {
468
+ skippedCount++;
469
+ continue;
470
+ }
422
471
  this.reportPerformance(item.data);
423
472
  break;
424
473
  case 'behavior':
474
+ // 检查行为监控是否启用
475
+ if (cfg.behavior?.enabled === false) {
476
+ skippedCount++;
477
+ continue;
478
+ }
479
+ // 根据行为类型检查具体开关
480
+ const action = item.data?.action;
481
+ if (action === 'pv' && cfg.behavior?.pv === false) {
482
+ skippedCount++;
483
+ continue;
484
+ }
485
+ if (action === 'route' && cfg.behavior?.route === false) {
486
+ skippedCount++;
487
+ continue;
488
+ }
425
489
  this.reportBehavior(item.data);
426
490
  break;
427
491
  }
428
492
  }
493
+ if (skippedCount > 0 && cfg.debug) {
494
+ console.log(`[Monitor] Filtered out ${skippedCount} early buffered items based on config`);
495
+ }
429
496
  }
430
497
  /**
431
498
  * 缓存早期数据
@@ -553,15 +620,16 @@
553
620
  * 安装 JS 错误监听
554
621
  */
555
622
  function installJsErrorHandler() {
556
- const cfg = config.get();
557
- if (!cfg.error?.enabled || !cfg.error?.jsError) {
558
- return;
559
- }
560
623
  window.addEventListener('error', (event) => {
561
624
  // 过滤资源加载错误(由 resourceError 处理)
562
625
  if (event.target !== window) {
563
626
  return;
564
627
  }
628
+ // 检查配置(在事件触发时检查,而不是安装时)
629
+ const cfg = config.isInitialized() ? config.get() : null;
630
+ if (cfg?.error?.enabled === false || cfg?.error?.jsError === false) {
631
+ return;
632
+ }
565
633
  const errorData = {
566
634
  type: 'js_error',
567
635
  message: event.message || 'Unknown error',
@@ -582,9 +650,7 @@
582
650
  });
583
651
  reporter.reportError(errorData);
584
652
  }, true);
585
- if (cfg.debug) {
586
- console.log('[Monitor] JS error handler installed');
587
- }
653
+ console.log('[Monitor] JS error handler installed');
588
654
  }
589
655
 
590
656
  /**
@@ -594,11 +660,12 @@
594
660
  * 安装 Promise 错误监听
595
661
  */
596
662
  function installPromiseErrorHandler() {
597
- const cfg = config.get();
598
- if (!cfg.error?.enabled || !cfg.error?.promiseError) {
599
- return;
600
- }
601
663
  window.addEventListener('unhandledrejection', (event) => {
664
+ // 检查配置(在事件触发时检查,而不是安装时)
665
+ const cfg = config.isInitialized() ? config.get() : null;
666
+ if (cfg?.error?.enabled === false || cfg?.error?.promiseError === false) {
667
+ return;
668
+ }
602
669
  let message = 'Unhandled Promise rejection';
603
670
  let stack;
604
671
  const reason = event.reason;
@@ -627,9 +694,7 @@
627
694
  });
628
695
  reporter.reportError(errorData);
629
696
  });
630
- if (cfg.debug) {
631
- console.log('[Monitor] Promise error handler installed');
632
- }
697
+ console.log('[Monitor] Promise error handler installed');
633
698
  }
634
699
 
635
700
  /**
@@ -639,16 +704,17 @@
639
704
  * 安装资源错误监听
640
705
  */
641
706
  function installResourceErrorHandler() {
642
- const cfg = config.get();
643
- if (!cfg.error?.enabled || !cfg.error?.resourceError) {
644
- return;
645
- }
646
707
  window.addEventListener('error', (event) => {
647
708
  const target = event.target;
648
709
  // 只处理资源加载错误(target 不是 window)
649
710
  if (!target || target === window || !(target instanceof HTMLElement)) {
650
711
  return;
651
712
  }
713
+ // 检查配置(在事件触发时检查,而不是安装时)
714
+ const cfg = config.isInitialized() ? config.get() : null;
715
+ if (cfg?.error?.enabled === false || cfg?.error?.resourceError === false) {
716
+ return;
717
+ }
652
718
  const tagName = target.tagName.toLowerCase();
653
719
  // 只监控特定标签的资源
654
720
  if (!['img', 'script', 'link', 'video', 'audio', 'source'].includes(tagName)) {
@@ -677,9 +743,7 @@
677
743
  });
678
744
  reporter.reportError(errorData);
679
745
  }, true); // 使用捕获阶段
680
- if (cfg.debug) {
681
- console.log('[Monitor] Resource error handler installed');
682
- }
746
+ console.log('[Monitor] Resource error handler installed');
683
747
  }
684
748
 
685
749
  /**
@@ -694,23 +758,16 @@
694
758
  * 安装 HTTP 错误拦截
695
759
  */
696
760
  function installHttpErrorHandler() {
697
- const cfg = config.get();
698
- if (!cfg.error?.enabled || !cfg.error?.httpError) {
699
- return;
700
- }
701
761
  interceptXHR();
702
762
  interceptFetch();
703
- if (cfg.debug) {
704
- console.log('[Monitor] HTTP error handler installed');
705
- }
763
+ console.log('[Monitor] HTTP error handler installed');
706
764
  }
707
- /**
708
- * 拦截 XMLHttpRequest
709
- */
710
765
  /**
711
766
  * 检查是否是 SDK 自身的请求
712
767
  */
713
768
  function isSdkRequest(url) {
769
+ if (!config.isInitialized())
770
+ return false;
714
771
  const cfg = config.get();
715
772
  if (!cfg.dsn)
716
773
  return false;
@@ -880,10 +937,6 @@
880
937
  reporter.reportError(errorData);
881
938
  }
882
939
 
883
- /**
884
- * 白屏检测插件
885
- * 使用 DOM 采样检测页面是否白屏
886
- */
887
940
  // 采样点 - 页面关键区域
888
941
  const SAMPLE_POINTS = [
889
942
  { x: 0.5, y: 0.1 }, // 顶部中间
@@ -898,10 +951,6 @@
898
951
  * 安装白屏检测
899
952
  */
900
953
  function installWhiteScreenDetector() {
901
- const cfg = config.get();
902
- if (!cfg.error?.enabled) {
903
- return;
904
- }
905
954
  // 在页面加载完成后检测
906
955
  if (document.readyState === 'complete') {
907
956
  scheduleDetection();
@@ -911,9 +960,7 @@
911
960
  scheduleDetection();
912
961
  });
913
962
  }
914
- if (cfg.debug) {
915
- console.log('[Monitor] White screen detector installed');
916
- }
963
+ console.log('[Monitor] White screen detector installed');
917
964
  }
918
965
  /**
919
966
  * 调度检测(延迟执行,给页面渲染时间)
@@ -985,10 +1032,6 @@
985
1032
  * 安装 Web Vitals 采集
986
1033
  */
987
1034
  function installWebVitals() {
988
- const cfg = config.get();
989
- if (!cfg.performance?.enabled || !cfg.performance?.webVitals) {
990
- return;
991
- }
992
1035
  // 页面加载完成后采集
993
1036
  if (document.readyState === 'complete') {
994
1037
  collectMetrics();
@@ -999,14 +1042,17 @@
999
1042
  setTimeout(collectMetrics, 3000);
1000
1043
  });
1001
1044
  }
1002
- if (cfg.debug) {
1003
- console.log('[Monitor] Web Vitals collector installed');
1004
- }
1045
+ console.log('[Monitor] Web Vitals collector installed');
1005
1046
  }
1006
1047
  /**
1007
1048
  * 采集性能指标
1008
1049
  */
1009
1050
  function collectMetrics() {
1051
+ // 检查配置(在采集时检查,而不是安装时)
1052
+ const cfg = config.isInitialized() ? config.get() : null;
1053
+ if (cfg?.performance?.enabled === false || cfg?.performance?.webVitals === false) {
1054
+ return;
1055
+ }
1010
1056
  const metrics = {};
1011
1057
  // 使用 Performance API
1012
1058
  if (!window.performance) {
@@ -1115,22 +1161,13 @@
1115
1161
  installWebVitals();
1116
1162
  }
1117
1163
 
1118
- /**
1119
- * PV (Page View) 统计插件
1120
- */
1121
1164
  /**
1122
1165
  * 安装 PV 统计
1123
1166
  */
1124
1167
  function installPVTracker() {
1125
- const cfg = config.get();
1126
- if (!cfg.behavior?.enabled || !cfg.behavior?.pv) {
1127
- return;
1128
- }
1129
- // 页面加载时上报
1168
+ // 页面加载时上报(reporter 会缓存直到 SDK 就绪)
1130
1169
  reportPV();
1131
- if (cfg.debug) {
1132
- console.log('[Monitor] PV tracker installed');
1133
- }
1170
+ console.log('[Monitor] PV tracker installed');
1134
1171
  }
1135
1172
  /**
1136
1173
  * 上报 PV
@@ -1153,11 +1190,12 @@
1153
1190
  * 安装点击追踪
1154
1191
  */
1155
1192
  function installClickTracker() {
1156
- const cfg = config.get();
1157
- if (!cfg.behavior?.enabled || !cfg.behavior?.click) {
1158
- return;
1159
- }
1160
1193
  document.addEventListener('click', (event) => {
1194
+ // 检查配置(在事件触发时检查,而不是安装时)
1195
+ const cfg = config.isInitialized() ? config.get() : null;
1196
+ if (cfg?.behavior?.enabled === false || cfg?.behavior?.click === false) {
1197
+ return;
1198
+ }
1161
1199
  const target = event.target;
1162
1200
  if (!target)
1163
1201
  return;
@@ -1175,9 +1213,7 @@
1175
1213
  // data: clickData,
1176
1214
  // });
1177
1215
  }, true);
1178
- if (cfg.debug) {
1179
- console.log('[Monitor] Click tracker installed');
1180
- }
1216
+ console.log('[Monitor] Click tracker installed');
1181
1217
  }
1182
1218
  /**
1183
1219
  * 提取点击数据
@@ -1256,10 +1292,6 @@
1256
1292
  * 安装路由监控
1257
1293
  */
1258
1294
  function installRouteTracker() {
1259
- const cfg = config.get();
1260
- if (!cfg.behavior?.enabled || !cfg.behavior?.route) {
1261
- return;
1262
- }
1263
1295
  // 拦截 pushState
1264
1296
  history.pushState = function (...args) {
1265
1297
  const result = originalPushState.apply(this, args);
@@ -1280,14 +1312,17 @@
1280
1312
  window.addEventListener('hashchange', () => {
1281
1313
  handleRouteChange('hashchange');
1282
1314
  });
1283
- if (cfg.debug) {
1284
- console.log('[Monitor] Route tracker installed');
1285
- }
1315
+ console.log('[Monitor] Route tracker installed');
1286
1316
  }
1287
1317
  /**
1288
1318
  * 处理路由变化
1289
1319
  */
1290
1320
  function handleRouteChange(trigger) {
1321
+ // 检查配置(在事件触发时检查,而不是安装时)
1322
+ const cfg = config.isInitialized() ? config.get() : null;
1323
+ if (cfg?.behavior?.enabled === false || cfg?.behavior?.route === false) {
1324
+ return;
1325
+ }
1291
1326
  const routeData = {
1292
1327
  url: getPageUrl(),
1293
1328
  title: getPageTitle(),
@@ -1322,16 +1357,16 @@
1322
1357
  * 安装控制台追踪
1323
1358
  */
1324
1359
  function installConsoleTracker() {
1325
- const cfg = config.get();
1326
- // 默认启用控制台追踪(跟随 behavior.enabled)
1327
- if (!cfg.behavior?.enabled) {
1328
- return;
1329
- }
1330
1360
  const levels = ['log', 'info', 'warn', 'error'];
1331
1361
  levels.forEach((level) => {
1332
1362
  console[level] = function (...args) {
1333
1363
  // 调用原始方法
1334
1364
  originalConsole[level].apply(console, args);
1365
+ // 检查配置(在调用时检查,而不是安装时)
1366
+ const cfg = config.isInitialized() ? config.get() : null;
1367
+ if (cfg?.behavior?.enabled === false) {
1368
+ return;
1369
+ }
1335
1370
  // 添加到面包屑(只记录 warn 和 error)
1336
1371
  if (level === 'warn' || level === 'error') {
1337
1372
  const message = formatConsoleArgs(args);
@@ -1346,9 +1381,7 @@
1346
1381
  }
1347
1382
  };
1348
1383
  });
1349
- if (cfg.debug) {
1350
- originalConsole.log('[Monitor] Console tracker installed');
1351
- }
1384
+ originalConsole.log('[Monitor] Console tracker installed');
1352
1385
  }
1353
1386
  /**
1354
1387
  * 格式化控制台参数
@@ -1380,24 +1413,22 @@
1380
1413
  * 安装输入追踪
1381
1414
  */
1382
1415
  function installInputTracker() {
1383
- const cfg = config.get();
1384
- // 默认启用输入追踪(跟随 behavior.enabled)
1385
- if (!cfg.behavior?.enabled) {
1386
- return;
1387
- }
1388
1416
  // 监听 input 事件(使用 change 事件减少数据量)
1389
1417
  document.addEventListener('change', handleInputChange, true);
1390
1418
  // 监听焦点事件
1391
1419
  document.addEventListener('focus', handleFocus, true);
1392
1420
  document.addEventListener('blur', handleBlur, true);
1393
- if (cfg.debug) {
1394
- console.log('[Monitor] Input tracker installed');
1395
- }
1421
+ console.log('[Monitor] Input tracker installed');
1396
1422
  }
1397
1423
  /**
1398
1424
  * 处理输入变化
1399
1425
  */
1400
1426
  function handleInputChange(event) {
1427
+ // 检查配置(在事件触发时检查,而不是安装时)
1428
+ const cfg = config.isInitialized() ? config.get() : null;
1429
+ if (cfg?.behavior?.enabled === false) {
1430
+ return;
1431
+ }
1401
1432
  const target = event.target;
1402
1433
  if (!target || !isFormElement(target))
1403
1434
  return;
@@ -1412,6 +1443,11 @@
1412
1443
  * 处理焦点获取
1413
1444
  */
1414
1445
  function handleFocus(event) {
1446
+ // 检查配置
1447
+ const cfg = config.isInitialized() ? config.get() : null;
1448
+ if (cfg?.behavior?.enabled === false) {
1449
+ return;
1450
+ }
1415
1451
  const target = event.target;
1416
1452
  if (!target || !isFormElement(target))
1417
1453
  return;
@@ -1425,6 +1461,11 @@
1425
1461
  * 处理焦点失去
1426
1462
  */
1427
1463
  function handleBlur(event) {
1464
+ // 检查配置
1465
+ const cfg = config.isInitialized() ? config.get() : null;
1466
+ if (cfg?.behavior?.enabled === false) {
1467
+ return;
1468
+ }
1428
1469
  const target = event.target;
1429
1470
  if (!target || !isFormElement(target))
1430
1471
  return;