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.d.ts CHANGED
@@ -110,6 +110,21 @@ interface ErrorMonitorConfig {
110
110
  * 例如: [404, 500, 502, 503, 504]
111
111
  */
112
112
  httpErrorStatusCodes?: number[];
113
+ /**
114
+ * 是否上报网络错误(请求失败,无法连接到服务器)
115
+ * 默认值: false
116
+ */
117
+ reportNetworkError?: boolean;
118
+ /**
119
+ * 是否上报请求超时错误
120
+ * 默认值: false
121
+ */
122
+ reportTimeoutError?: boolean;
123
+ /**
124
+ * 是否上报请求取消错误(用户主动取消或页面切换导致的取消)
125
+ * 默认值: false
126
+ */
127
+ reportAbortError?: boolean;
113
128
  }
114
129
  /**
115
130
  * 性能监控配置
@@ -217,6 +232,13 @@ interface HttpInfo {
217
232
  requestBody?: string;
218
233
  /** 响应体 */
219
234
  responseBody?: string;
235
+ /**
236
+ * 错误类型(当 status 为 0 时)
237
+ * - 'timeout': 请求超时
238
+ * - 'abort': 请求被取消
239
+ * - 'network': 网络错误
240
+ */
241
+ errorType?: 'timeout' | 'abort' | 'network';
220
242
  }
221
243
  /**
222
244
  * 性能数据
package/dist/index.esm.js CHANGED
@@ -423,7 +423,7 @@ if (typeof window !== 'undefined') {
423
423
  });
424
424
  }
425
425
 
426
- var version = "1.1.17";
426
+ var version = "1.1.19";
427
427
 
428
428
  /**
429
429
  * 数据上报管理
@@ -855,6 +855,27 @@ function shouldReportHttpError(status) {
855
855
  console.log(`[Monitor] HTTP status ${status} shouldReport: ${shouldReport}, configured codes:`, httpErrorStatusCodes);
856
856
  return shouldReport;
857
857
  }
858
+ /**
859
+ * 根据错误类型判断是否应该上报网络类错误(status = 0)
860
+ * @param errorType 错误类型:'timeout' | 'abort' | 'network'
861
+ * @returns 是否应该上报
862
+ */
863
+ function shouldReportNetworkTypeError(errorType) {
864
+ if (!config.isInitialized()) {
865
+ return false;
866
+ }
867
+ const cfg = config.get();
868
+ const errorConfig = cfg.error;
869
+ switch (errorType) {
870
+ case 'timeout':
871
+ return errorConfig?.reportTimeoutError === true;
872
+ case 'abort':
873
+ return errorConfig?.reportAbortError === true;
874
+ case 'network':
875
+ default:
876
+ return errorConfig?.reportNetworkError === true;
877
+ }
878
+ }
858
879
  /**
859
880
  * 获取嵌套对象的字段值
860
881
  * @param obj 对象
@@ -973,7 +994,20 @@ function interceptXHR() {
973
994
  if (monitorData) {
974
995
  monitorData.startTime = Date.now();
975
996
  monitorData.requestBody = typeof body === 'string' ? body : undefined;
997
+ monitorData.errorType = undefined; // 初始化错误类型
976
998
  }
999
+ // 监听超时事件
1000
+ this.addEventListener('timeout', function () {
1001
+ if (monitorData) {
1002
+ monitorData.errorType = 'timeout';
1003
+ }
1004
+ });
1005
+ // 监听取消事件
1006
+ this.addEventListener('abort', function () {
1007
+ if (monitorData) {
1008
+ monitorData.errorType = 'abort';
1009
+ }
1010
+ });
977
1011
  this.addEventListener('loadend', function () {
978
1012
  if (!monitorData)
979
1013
  return;
@@ -987,6 +1021,11 @@ function interceptXHR() {
987
1021
  // 其他异常情况(0-网络错误、4xx-客户端错误、5xx-服务端错误)根据配置控制
988
1022
  const isError = status === 0 || status < 200 || status >= 400;
989
1023
  const shouldRecord = isRedirect || recordMode === 'all' || (recordMode === 'error' && isError);
1024
+ // 确定错误类型
1025
+ let errorType;
1026
+ if (status === 0) {
1027
+ errorType = monitorData.errorType || 'network';
1028
+ }
990
1029
  if (shouldRecord) {
991
1030
  context.addBreadcrumb({
992
1031
  type: 'request',
@@ -996,12 +1035,22 @@ function interceptXHR() {
996
1035
  url: monitorData.url,
997
1036
  status,
998
1037
  duration,
1038
+ errorType,
999
1039
  },
1000
1040
  });
1001
1041
  }
1002
1042
  const responseBody = this.responseText?.substring(0, 1000);
1003
- // HTTP 错误(根据配置的状态码列表过滤)
1004
- if (shouldReportHttpError(status)) {
1043
+ // HTTP 错误上报逻辑
1044
+ let shouldReport = false;
1045
+ if (status === 0) {
1046
+ // status=0 使用独立的网络错误配置
1047
+ shouldReport = shouldReportNetworkTypeError(errorType);
1048
+ }
1049
+ else {
1050
+ // 其他状态码使用 httpErrorStatusCodes 配置
1051
+ shouldReport = shouldReportHttpError(status);
1052
+ }
1053
+ if (shouldReport) {
1005
1054
  reportHttpError({
1006
1055
  method: monitorData.method,
1007
1056
  url: monitorData.url,
@@ -1009,6 +1058,7 @@ function interceptXHR() {
1009
1058
  duration,
1010
1059
  requestBody: monitorData.requestBody,
1011
1060
  responseBody,
1061
+ errorType,
1012
1062
  });
1013
1063
  }
1014
1064
  else if (status >= 200 && status < 300 && detectBusinessError(responseBody)) {
@@ -1101,6 +1151,22 @@ function interceptFetch() {
1101
1151
  }
1102
1152
  catch (error) {
1103
1153
  const duration = Date.now() - startTime;
1154
+ const err = error;
1155
+ // 判断错误类型
1156
+ // AbortError 表示请求被取消(可能是手动取消或超时)
1157
+ // 注意:fetch 的超时通常也是通过 AbortController 实现的,所以无法区分超时和手动取消
1158
+ // 这里将 AbortError 统一标记为 'abort',如果需要区分超时,建议使用 XHR 或检查 error.message
1159
+ let errorType = 'network';
1160
+ if (err.name === 'AbortError') {
1161
+ // 尝试通过错误消息区分超时和取消
1162
+ // 一些超时实现会在 message 中包含 'timeout'
1163
+ if (err.message?.toLowerCase().includes('timeout')) {
1164
+ errorType = 'timeout';
1165
+ }
1166
+ else {
1167
+ errorType = 'abort';
1168
+ }
1169
+ }
1104
1170
  // 网络错误时根据配置决定是否添加到面包屑
1105
1171
  const cfg = config.isInitialized() ? config.get() : null;
1106
1172
  const recordMode = cfg?.behavior?.recordRequestBreadcrumb || 'error';
@@ -1114,18 +1180,20 @@ function interceptFetch() {
1114
1180
  url,
1115
1181
  status: 0,
1116
1182
  duration,
1117
- error: error.message,
1183
+ error: err.message,
1184
+ errorType,
1118
1185
  },
1119
1186
  });
1120
1187
  }
1121
- // 网络错误也遵守 httpErrorStatusCodes 配置
1122
- if (shouldReportHttpError(0)) {
1188
+ // 网络错误使用独立的配置项判断是否上报
1189
+ if (shouldReportNetworkTypeError(errorType)) {
1123
1190
  reportHttpError({
1124
1191
  method,
1125
1192
  url,
1126
1193
  status: 0,
1127
1194
  duration,
1128
1195
  requestBody,
1196
+ errorType,
1129
1197
  });
1130
1198
  }
1131
1199
  throw error;
@@ -1136,9 +1204,23 @@ function interceptFetch() {
1136
1204
  * 上报 HTTP 错误
1137
1205
  */
1138
1206
  function reportHttpError(httpInfo, isBusinessError = false) {
1139
- const message = isBusinessError
1140
- ? `Business Error ${httpInfo.method} ${httpInfo.url}`
1141
- : `HTTP ${httpInfo.status} ${httpInfo.method} ${httpInfo.url}`;
1207
+ let message;
1208
+ if (isBusinessError) {
1209
+ message = `Business Error ${httpInfo.method} ${httpInfo.url}`;
1210
+ }
1211
+ else if (httpInfo.status === 0 && httpInfo.errorType) {
1212
+ // 对于 status 0,显示具体的错误类型
1213
+ const errorTypeLabels = {
1214
+ 'timeout': 'Timeout',
1215
+ 'abort': 'Aborted',
1216
+ 'network': 'Network Error',
1217
+ };
1218
+ const label = errorTypeLabels[httpInfo.errorType] || 'Network Error';
1219
+ message = `HTTP ${label} ${httpInfo.method} ${httpInfo.url}`;
1220
+ }
1221
+ else {
1222
+ message = `HTTP ${httpInfo.status} ${httpInfo.method} ${httpInfo.url}`;
1223
+ }
1142
1224
  const errorData = {
1143
1225
  type: isBusinessError ? 'business_error' : 'http_error',
1144
1226
  message,