sobey-monitor-sdk 1.0.5 → 1.0.7

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/README.md CHANGED
@@ -119,6 +119,8 @@ ReactDOM.render(
119
119
  | `sampling.error` | number | 1 | 错误采样率 (0-1) |
120
120
  | `sampling.performance` | number | 1 | 性能采样率 (0-1) |
121
121
  | `sampling.behavior` | number | 1 | 行为采样率 (0-1) |
122
+ | `behavior.maxBreadcrumbs` | number | 20 | 行为回溯最大记录数 |
123
+ | `behavior.recordRequestBreadcrumb` | 'all' \| 'error' \| 'none' | 'error' | 网络请求记录模式:'all' 记录所有、'error' 记录非 2xx 响应(重定向、4xx、5xx、网络错误)、'none' 不记录 |
122
124
  | `report.maxBufferSize` | number | 10 | 缓冲区最大数量 |
123
125
  | `report.flushInterval` | number | 5000 | 上报间隔 (ms) |
124
126
 
package/dist/index.cjs.js CHANGED
@@ -6,6 +6,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
6
6
  * 默认配置
7
7
  */
8
8
  const DEFAULT_CONFIG = {
9
+ enabled: true,
9
10
  debug: false,
10
11
  sampling: {
11
12
  error: 1,
@@ -36,6 +37,7 @@ const DEFAULT_CONFIG = {
36
37
  click: true,
37
38
  route: true,
38
39
  maxBreadcrumbs: 20,
40
+ recordRequestBreadcrumb: 'error',
39
41
  },
40
42
  };
41
43
  /**
@@ -447,6 +449,13 @@ class Reporter {
447
449
  */
448
450
  send(data) {
449
451
  const cfg = config.get();
452
+ // 全局开关检查:如果 enabled 为 false,则不上报
453
+ if (cfg.enabled === false) {
454
+ if (cfg.debug) {
455
+ console.log('[Monitor] SDK disabled, skip report:', data.type || 'unknown');
456
+ }
457
+ return;
458
+ }
450
459
  if (cfg.debug) {
451
460
  console.log('[Monitor] Report:', data);
452
461
  }
@@ -662,18 +671,26 @@ function interceptXHR() {
662
671
  return;
663
672
  const duration = Date.now() - monitorData.startTime;
664
673
  const status = this.status;
665
- // 添加到面包屑
666
- context.addBreadcrumb({
667
- type: 'request',
668
- category: 'xhr',
669
- data: {
670
- method: monitorData.method,
671
- url: monitorData.url,
672
- status,
673
- duration,
674
- },
675
- });
676
- // 只上报错误请求 (4xx, 5xx 或 0)
674
+ // 根据配置决定是否添加到面包屑
675
+ const cfg = config.get();
676
+ const recordMode = cfg.behavior?.recordRequestBreadcrumb || 'error';
677
+ // 重定向(3xx)始终记录,不受配置控制
678
+ const isRedirect = status >= 300 && status < 400;
679
+ // 其他异常情况(0-网络错误、4xx-客户端错误、5xx-服务端错误)根据配置控制
680
+ const isError = status === 0 || status < 200 || status >= 400;
681
+ const shouldRecord = isRedirect || recordMode === 'all' || (recordMode === 'error' && isError);
682
+ if (shouldRecord) {
683
+ context.addBreadcrumb({
684
+ type: 'request',
685
+ category: 'xhr',
686
+ data: {
687
+ method: monitorData.method,
688
+ url: monitorData.url,
689
+ status,
690
+ duration,
691
+ },
692
+ });
693
+ }
677
694
  if (status === 0 || status >= 400) {
678
695
  reportHttpError({
679
696
  method: monitorData.method,
@@ -705,18 +722,26 @@ function interceptFetch() {
705
722
  const response = await originalFetch.call(window, input, init);
706
723
  const duration = Date.now() - startTime;
707
724
  const status = response.status;
708
- // 添加到面包屑
709
- context.addBreadcrumb({
710
- type: 'request',
711
- category: 'fetch',
712
- data: {
713
- method,
714
- url,
715
- status,
716
- duration,
717
- },
718
- });
719
- // 只上报错误请求
725
+ // 根据配置决定是否添加到面包屑
726
+ const cfg = config.get();
727
+ const recordMode = cfg.behavior?.recordRequestBreadcrumb || 'error';
728
+ // 重定向(3xx)始终记录,不受配置控制
729
+ const isRedirect = status >= 300 && status < 400;
730
+ // 其他异常情况根据配置控制
731
+ const isError = status < 200 || status >= 400;
732
+ const shouldRecord = isRedirect || recordMode === 'all' || (recordMode === 'error' && isError);
733
+ if (shouldRecord) {
734
+ context.addBreadcrumb({
735
+ type: 'request',
736
+ category: 'fetch',
737
+ data: {
738
+ method,
739
+ url,
740
+ status,
741
+ duration,
742
+ },
743
+ });
744
+ }
720
745
  if (!response.ok) {
721
746
  // 克隆响应以读取 body
722
747
  const cloned = response.clone();
@@ -739,18 +764,23 @@ function interceptFetch() {
739
764
  }
740
765
  catch (error) {
741
766
  const duration = Date.now() - startTime;
742
- // 网络错误
743
- context.addBreadcrumb({
744
- type: 'request',
745
- category: 'fetch',
746
- data: {
747
- method,
748
- url,
749
- status: 0,
750
- duration,
751
- error: error.message,
752
- },
753
- });
767
+ // 网络错误时根据配置决定是否添加到面包屑
768
+ const cfg = config.get();
769
+ const recordMode = cfg.behavior?.recordRequestBreadcrumb || 'error';
770
+ // 网络错误属于 error,当模式为 'all' 或 'error' 时都记录
771
+ if (recordMode !== 'none') {
772
+ context.addBreadcrumb({
773
+ type: 'request',
774
+ category: 'fetch',
775
+ data: {
776
+ method,
777
+ url,
778
+ status: 0,
779
+ duration,
780
+ error: error.message,
781
+ },
782
+ });
783
+ }
754
784
  reportHttpError({
755
785
  method,
756
786
  url,
@@ -1079,10 +1109,14 @@ function installClickTracker() {
1079
1109
  function extractClickData(element, event) {
1080
1110
  const tagName = element.tagName.toLowerCase();
1081
1111
  const rect = element.getBoundingClientRect();
1112
+ // SVG 元素的 className 是 SVGAnimatedString 对象,需要特殊处理
1113
+ const classNameStr = typeof element.className === 'string'
1114
+ ? element.className
1115
+ : element.className?.baseVal || '';
1082
1116
  return {
1083
1117
  tagName,
1084
1118
  id: element.id || undefined,
1085
- className: element.className || undefined,
1119
+ className: classNameStr || undefined,
1086
1120
  text: getElementText(element),
1087
1121
  path: getElementPath(element),
1088
1122
  // 鼠标坐标
@@ -1120,7 +1154,11 @@ function getElementPath(element) {
1120
1154
  selector += `#${current.id}`;
1121
1155
  }
1122
1156
  else if (current.className) {
1123
- const classes = current.className.split(' ').filter(Boolean).slice(0, 2);
1157
+ // SVG 元素的 className SVGAnimatedString 对象,需要特殊处理
1158
+ const classNameStr = typeof current.className === 'string'
1159
+ ? current.className
1160
+ : current.className?.baseVal || '';
1161
+ const classes = classNameStr.split(' ').filter(Boolean).slice(0, 2);
1124
1162
  if (classes.length) {
1125
1163
  selector += `.${classes.join('.')}`;
1126
1164
  }