sobey-monitor-sdk 1.1.8 → 1.1.10
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 +128 -15
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +18 -0
- package/dist/index.esm.js +128 -15
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +128 -15
- package/dist/index.umd.js.map +1 -1
- package/dist/types/index.d.ts +18 -0
- package/package.json +1 -1
package/dist/index.umd.js
CHANGED
|
@@ -770,12 +770,93 @@
|
|
|
770
770
|
* 检查是否是 SDK 自身的请求
|
|
771
771
|
*/
|
|
772
772
|
function isSdkRequest(url) {
|
|
773
|
+
// 检查是否匹配常见的 SDK 上报路径
|
|
774
|
+
if (url.includes('/monitor/api/report') ||
|
|
775
|
+
url.includes('/monitor/api/beacon') ||
|
|
776
|
+
url.includes('/monitor/api/config')) {
|
|
777
|
+
return true;
|
|
778
|
+
}
|
|
779
|
+
// 配置已初始化时,检查 dsn
|
|
780
|
+
if (config.isInitialized()) {
|
|
781
|
+
const cfg = config.get();
|
|
782
|
+
if (cfg.dsn && url.includes(cfg.dsn)) {
|
|
783
|
+
return true;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
return false;
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* 获取嵌套对象的字段值
|
|
790
|
+
* @param obj 对象
|
|
791
|
+
* @param path 字段路径,如 "status" 或 "data.code"
|
|
792
|
+
*/
|
|
793
|
+
function getNestedValue(obj, path) {
|
|
794
|
+
if (!obj || typeof obj !== 'object')
|
|
795
|
+
return undefined;
|
|
796
|
+
const keys = path.split('.');
|
|
797
|
+
let value = obj;
|
|
798
|
+
for (const key of keys) {
|
|
799
|
+
if (value === null || value === undefined)
|
|
800
|
+
return undefined;
|
|
801
|
+
value = value[key];
|
|
802
|
+
}
|
|
803
|
+
return value;
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* 检查单条规则是否匹配
|
|
807
|
+
*/
|
|
808
|
+
function matchRule(data, rule) {
|
|
809
|
+
const value = getNestedValue(data, rule.field);
|
|
810
|
+
switch (rule.operator) {
|
|
811
|
+
case 'exists':
|
|
812
|
+
return value !== undefined && value !== null;
|
|
813
|
+
case 'eq':
|
|
814
|
+
return value === rule.value;
|
|
815
|
+
case 'ne':
|
|
816
|
+
return value !== rule.value;
|
|
817
|
+
case 'gt':
|
|
818
|
+
return typeof value === 'number' && typeof rule.value === 'number' && value > rule.value;
|
|
819
|
+
case 'gte':
|
|
820
|
+
return typeof value === 'number' && typeof rule.value === 'number' && value >= rule.value;
|
|
821
|
+
case 'lt':
|
|
822
|
+
return typeof value === 'number' && typeof rule.value === 'number' && value < rule.value;
|
|
823
|
+
case 'lte':
|
|
824
|
+
return typeof value === 'number' && typeof rule.value === 'number' && value <= rule.value;
|
|
825
|
+
default:
|
|
826
|
+
return false;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* 检测业务错误
|
|
831
|
+
* @param responseBody 响应体字符串
|
|
832
|
+
* @returns 是否为业务错误
|
|
833
|
+
*/
|
|
834
|
+
function detectBusinessError(responseBody) {
|
|
835
|
+
if (!responseBody)
|
|
836
|
+
return false;
|
|
773
837
|
if (!config.isInitialized())
|
|
774
838
|
return false;
|
|
775
839
|
const cfg = config.get();
|
|
776
|
-
|
|
840
|
+
const rules = cfg.error?.businessErrorRules;
|
|
841
|
+
if (!rules || rules.length === 0)
|
|
842
|
+
return false;
|
|
843
|
+
try {
|
|
844
|
+
const data = JSON.parse(responseBody);
|
|
845
|
+
// 任一规则匹配时返回 true
|
|
846
|
+
for (const rule of rules) {
|
|
847
|
+
if (matchRule(data, rule)) {
|
|
848
|
+
if (cfg.debug) {
|
|
849
|
+
console.log('[Monitor] Business error detected by rule:', rule, 'data:', data);
|
|
850
|
+
}
|
|
851
|
+
return true;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
777
854
|
return false;
|
|
778
|
-
|
|
855
|
+
}
|
|
856
|
+
catch {
|
|
857
|
+
// JSON 解析失败,不是业务错误
|
|
858
|
+
return false;
|
|
859
|
+
}
|
|
779
860
|
}
|
|
780
861
|
function interceptXHR() {
|
|
781
862
|
XMLHttpRequest.prototype.open = function (method, url, async = true, username, password) {
|
|
@@ -828,6 +909,8 @@
|
|
|
828
909
|
},
|
|
829
910
|
});
|
|
830
911
|
}
|
|
912
|
+
const responseBody = this.responseText?.substring(0, 1000);
|
|
913
|
+
// HTTP 错误或业务错误
|
|
831
914
|
if (status === 0 || status >= 400) {
|
|
832
915
|
reportHttpError({
|
|
833
916
|
method: monitorData.method,
|
|
@@ -835,9 +918,20 @@
|
|
|
835
918
|
status,
|
|
836
919
|
duration,
|
|
837
920
|
requestBody: monitorData.requestBody,
|
|
838
|
-
responseBody
|
|
921
|
+
responseBody,
|
|
839
922
|
});
|
|
840
923
|
}
|
|
924
|
+
else if (status >= 200 && status < 300 && detectBusinessError(responseBody)) {
|
|
925
|
+
// HTTP 200 但检测到业务错误
|
|
926
|
+
reportHttpError({
|
|
927
|
+
method: monitorData.method,
|
|
928
|
+
url: monitorData.url,
|
|
929
|
+
status,
|
|
930
|
+
duration,
|
|
931
|
+
requestBody: monitorData.requestBody,
|
|
932
|
+
responseBody,
|
|
933
|
+
}, true);
|
|
934
|
+
}
|
|
841
935
|
});
|
|
842
936
|
return originalXHRSend.call(this, body);
|
|
843
937
|
};
|
|
@@ -879,8 +973,10 @@
|
|
|
879
973
|
},
|
|
880
974
|
});
|
|
881
975
|
}
|
|
882
|
-
|
|
883
|
-
|
|
976
|
+
// 检查是否配置了业务错误规则
|
|
977
|
+
const hasBusinessRules = cfg?.error?.businessErrorRules && cfg.error.businessErrorRules.length > 0;
|
|
978
|
+
// 只有在请求失败或配置了业务规则时才读取响应体
|
|
979
|
+
if (!response.ok || hasBusinessRules) {
|
|
884
980
|
const cloned = response.clone();
|
|
885
981
|
let responseBody;
|
|
886
982
|
try {
|
|
@@ -888,14 +984,28 @@
|
|
|
888
984
|
responseBody = responseBody.substring(0, 1000);
|
|
889
985
|
}
|
|
890
986
|
catch { }
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
987
|
+
if (!response.ok) {
|
|
988
|
+
// HTTP 错误
|
|
989
|
+
reportHttpError({
|
|
990
|
+
method,
|
|
991
|
+
url,
|
|
992
|
+
status,
|
|
993
|
+
duration,
|
|
994
|
+
requestBody,
|
|
995
|
+
responseBody,
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
else if (hasBusinessRules && detectBusinessError(responseBody)) {
|
|
999
|
+
// HTTP 200 但检测到业务错误
|
|
1000
|
+
reportHttpError({
|
|
1001
|
+
method,
|
|
1002
|
+
url,
|
|
1003
|
+
status,
|
|
1004
|
+
duration,
|
|
1005
|
+
requestBody,
|
|
1006
|
+
responseBody,
|
|
1007
|
+
}, true);
|
|
1008
|
+
}
|
|
899
1009
|
}
|
|
900
1010
|
return response;
|
|
901
1011
|
}
|
|
@@ -932,10 +1042,13 @@
|
|
|
932
1042
|
/**
|
|
933
1043
|
* 上报 HTTP 错误
|
|
934
1044
|
*/
|
|
935
|
-
function reportHttpError(httpInfo) {
|
|
1045
|
+
function reportHttpError(httpInfo, isBusinessError = false) {
|
|
1046
|
+
const message = isBusinessError
|
|
1047
|
+
? `Business Error ${httpInfo.method} ${httpInfo.url}`
|
|
1048
|
+
: `HTTP ${httpInfo.status} ${httpInfo.method} ${httpInfo.url}`;
|
|
936
1049
|
const errorData = {
|
|
937
1050
|
type: 'http_error',
|
|
938
|
-
message
|
|
1051
|
+
message,
|
|
939
1052
|
httpInfo,
|
|
940
1053
|
};
|
|
941
1054
|
reporter.reportError(errorData);
|