sobey-monitor-sdk 1.1.18 → 1.1.19

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.cjs.js CHANGED
@@ -427,7 +427,7 @@ if (typeof window !== 'undefined') {
427
427
  });
428
428
  }
429
429
 
430
- var version = "1.1.17";
430
+ var version = "1.1.19";
431
431
 
432
432
  /**
433
433
  * 数据上报管理
@@ -859,6 +859,27 @@ function shouldReportHttpError(status) {
859
859
  console.log(`[Monitor] HTTP status ${status} shouldReport: ${shouldReport}, configured codes:`, httpErrorStatusCodes);
860
860
  return shouldReport;
861
861
  }
862
+ /**
863
+ * 根据错误类型判断是否应该上报网络类错误(status = 0)
864
+ * @param errorType 错误类型:'timeout' | 'abort' | 'network'
865
+ * @returns 是否应该上报
866
+ */
867
+ function shouldReportNetworkTypeError(errorType) {
868
+ if (!config.isInitialized()) {
869
+ return false;
870
+ }
871
+ const cfg = config.get();
872
+ const errorConfig = cfg.error;
873
+ switch (errorType) {
874
+ case 'timeout':
875
+ return errorConfig?.reportTimeoutError === true;
876
+ case 'abort':
877
+ return errorConfig?.reportAbortError === true;
878
+ case 'network':
879
+ default:
880
+ return errorConfig?.reportNetworkError === true;
881
+ }
882
+ }
862
883
  /**
863
884
  * 获取嵌套对象的字段值
864
885
  * @param obj 对象
@@ -977,7 +998,20 @@ function interceptXHR() {
977
998
  if (monitorData) {
978
999
  monitorData.startTime = Date.now();
979
1000
  monitorData.requestBody = typeof body === 'string' ? body : undefined;
1001
+ monitorData.errorType = undefined; // 初始化错误类型
980
1002
  }
1003
+ // 监听超时事件
1004
+ this.addEventListener('timeout', function () {
1005
+ if (monitorData) {
1006
+ monitorData.errorType = 'timeout';
1007
+ }
1008
+ });
1009
+ // 监听取消事件
1010
+ this.addEventListener('abort', function () {
1011
+ if (monitorData) {
1012
+ monitorData.errorType = 'abort';
1013
+ }
1014
+ });
981
1015
  this.addEventListener('loadend', function () {
982
1016
  if (!monitorData)
983
1017
  return;
@@ -991,6 +1025,11 @@ function interceptXHR() {
991
1025
  // 其他异常情况(0-网络错误、4xx-客户端错误、5xx-服务端错误)根据配置控制
992
1026
  const isError = status === 0 || status < 200 || status >= 400;
993
1027
  const shouldRecord = isRedirect || recordMode === 'all' || (recordMode === 'error' && isError);
1028
+ // 确定错误类型
1029
+ let errorType;
1030
+ if (status === 0) {
1031
+ errorType = monitorData.errorType || 'network';
1032
+ }
994
1033
  if (shouldRecord) {
995
1034
  context.addBreadcrumb({
996
1035
  type: 'request',
@@ -1000,12 +1039,22 @@ function interceptXHR() {
1000
1039
  url: monitorData.url,
1001
1040
  status,
1002
1041
  duration,
1042
+ errorType,
1003
1043
  },
1004
1044
  });
1005
1045
  }
1006
1046
  const responseBody = this.responseText?.substring(0, 1000);
1007
- // HTTP 错误(根据配置的状态码列表过滤)
1008
- if (shouldReportHttpError(status)) {
1047
+ // HTTP 错误上报逻辑
1048
+ let shouldReport = false;
1049
+ if (status === 0) {
1050
+ // status=0 使用独立的网络错误配置
1051
+ shouldReport = shouldReportNetworkTypeError(errorType);
1052
+ }
1053
+ else {
1054
+ // 其他状态码使用 httpErrorStatusCodes 配置
1055
+ shouldReport = shouldReportHttpError(status);
1056
+ }
1057
+ if (shouldReport) {
1009
1058
  reportHttpError({
1010
1059
  method: monitorData.method,
1011
1060
  url: monitorData.url,
@@ -1013,6 +1062,7 @@ function interceptXHR() {
1013
1062
  duration,
1014
1063
  requestBody: monitorData.requestBody,
1015
1064
  responseBody,
1065
+ errorType,
1016
1066
  });
1017
1067
  }
1018
1068
  else if (status >= 200 && status < 300 && detectBusinessError(responseBody)) {
@@ -1105,6 +1155,22 @@ function interceptFetch() {
1105
1155
  }
1106
1156
  catch (error) {
1107
1157
  const duration = Date.now() - startTime;
1158
+ const err = error;
1159
+ // 判断错误类型
1160
+ // AbortError 表示请求被取消(可能是手动取消或超时)
1161
+ // 注意:fetch 的超时通常也是通过 AbortController 实现的,所以无法区分超时和手动取消
1162
+ // 这里将 AbortError 统一标记为 'abort',如果需要区分超时,建议使用 XHR 或检查 error.message
1163
+ let errorType = 'network';
1164
+ if (err.name === 'AbortError') {
1165
+ // 尝试通过错误消息区分超时和取消
1166
+ // 一些超时实现会在 message 中包含 'timeout'
1167
+ if (err.message?.toLowerCase().includes('timeout')) {
1168
+ errorType = 'timeout';
1169
+ }
1170
+ else {
1171
+ errorType = 'abort';
1172
+ }
1173
+ }
1108
1174
  // 网络错误时根据配置决定是否添加到面包屑
1109
1175
  const cfg = config.isInitialized() ? config.get() : null;
1110
1176
  const recordMode = cfg?.behavior?.recordRequestBreadcrumb || 'error';
@@ -1118,18 +1184,20 @@ function interceptFetch() {
1118
1184
  url,
1119
1185
  status: 0,
1120
1186
  duration,
1121
- error: error.message,
1187
+ error: err.message,
1188
+ errorType,
1122
1189
  },
1123
1190
  });
1124
1191
  }
1125
- // 网络错误也遵守 httpErrorStatusCodes 配置
1126
- if (shouldReportHttpError(0)) {
1192
+ // 网络错误使用独立的配置项判断是否上报
1193
+ if (shouldReportNetworkTypeError(errorType)) {
1127
1194
  reportHttpError({
1128
1195
  method,
1129
1196
  url,
1130
1197
  status: 0,
1131
1198
  duration,
1132
1199
  requestBody,
1200
+ errorType,
1133
1201
  });
1134
1202
  }
1135
1203
  throw error;
@@ -1140,9 +1208,23 @@ function interceptFetch() {
1140
1208
  * 上报 HTTP 错误
1141
1209
  */
1142
1210
  function reportHttpError(httpInfo, isBusinessError = false) {
1143
- const message = isBusinessError
1144
- ? `Business Error ${httpInfo.method} ${httpInfo.url}`
1145
- : `HTTP ${httpInfo.status} ${httpInfo.method} ${httpInfo.url}`;
1211
+ let message;
1212
+ if (isBusinessError) {
1213
+ message = `Business Error ${httpInfo.method} ${httpInfo.url}`;
1214
+ }
1215
+ else if (httpInfo.status === 0 && httpInfo.errorType) {
1216
+ // 对于 status 0,显示具体的错误类型
1217
+ const errorTypeLabels = {
1218
+ 'timeout': 'Timeout',
1219
+ 'abort': 'Aborted',
1220
+ 'network': 'Network Error',
1221
+ };
1222
+ const label = errorTypeLabels[httpInfo.errorType] || 'Network Error';
1223
+ message = `HTTP ${label} ${httpInfo.method} ${httpInfo.url}`;
1224
+ }
1225
+ else {
1226
+ message = `HTTP ${httpInfo.status} ${httpInfo.method} ${httpInfo.url}`;
1227
+ }
1146
1228
  const errorData = {
1147
1229
  type: isBusinessError ? 'business_error' : 'http_error',
1148
1230
  message,