@king-one/monitor 1.0.5 → 1.0.6
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/CHANGELOG.md +6 -0
- package/dist/cdn/index.umd.js +2 -2
- package/dist/es/index.mjs +10 -8
- package/dist/es/src/EventEmitter.mjs +25 -36
- package/dist/es/src/SourceError.mjs +45 -62
- package/dist/es/src/core.mjs +80 -107
- package/dist/es/src/index.mjs +10 -8
- package/dist/es/src/integrations/BrowserError.mjs +39 -48
- package/dist/es/src/integrations/VueError.mjs +20 -22
- package/dist/es/src/utils.mjs +71 -82
- package/dist/lib/index.js +1 -11
- package/dist/lib/src/EventEmitter.js +1 -77
- package/dist/lib/src/SourceError.js +4 -83
- package/dist/lib/src/core.js +1 -239
- package/dist/lib/src/index.js +1 -10
- package/dist/lib/src/integrations/BrowserError.js +1 -76
- package/dist/lib/src/integrations/VueError.js +1 -27
- package/dist/lib/src/utils.js +1 -117
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/types.d.ts +1 -0
- package/dist/types/src/utils.d.ts +1 -0
- package/package.json +1 -1
package/dist/lib/index.js
CHANGED
|
@@ -1,11 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
require("./src/index.js");
|
|
4
|
-
const core = require("./src/core.js");
|
|
5
|
-
const SourceError = require("./src/SourceError.js");
|
|
6
|
-
const VueError = require("./src/integrations/VueError.js");
|
|
7
|
-
const BrowserError = require("./src/integrations/BrowserError.js");
|
|
8
|
-
exports.ErrorMonitor = core.ErrorMonitor;
|
|
9
|
-
exports.SourceError = SourceError.SourceError;
|
|
10
|
-
exports.VueError = VueError.VueError;
|
|
11
|
-
exports.BrowserError = BrowserError.BrowserError;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("./src/index.js");const r=require("./src/utils.js"),e=require("./src/core.js"),o=require("./src/SourceError.js"),t=require("./src/integrations/VueError.js"),u=require("./src/integrations/BrowserError.js");exports.timestampToBase66=r.timestampToBase66;exports.ErrorMonitor=e.ErrorMonitor;exports.SourceError=o.SourceError;exports.VueError=t.VueError;exports.BrowserError=u.BrowserError;
|
|
@@ -1,77 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
6
|
-
class EventEmitter {
|
|
7
|
-
constructor() {
|
|
8
|
-
__publicField(this, "events", /* @__PURE__ */ new Map());
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* 订阅事件
|
|
12
|
-
* @param eventName 事件名称
|
|
13
|
-
* @param handler 事件处理函数
|
|
14
|
-
*/
|
|
15
|
-
on(eventName, handler) {
|
|
16
|
-
if (!this.events.has(eventName)) {
|
|
17
|
-
this.events.set(eventName, /* @__PURE__ */ new Set());
|
|
18
|
-
}
|
|
19
|
-
const handlers = this.events.get(eventName);
|
|
20
|
-
handlers.add(handler);
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* 取消订阅事件
|
|
24
|
-
* @param eventName 事件名称
|
|
25
|
-
* @param handler 事件处理函数
|
|
26
|
-
*/
|
|
27
|
-
off(eventName, handler) {
|
|
28
|
-
const handlers = this.events.get(eventName);
|
|
29
|
-
if (handlers) {
|
|
30
|
-
handlers.delete(handler);
|
|
31
|
-
if (handlers.size === 0) {
|
|
32
|
-
this.events.delete(eventName);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* 触发事件
|
|
38
|
-
* @param eventName 事件名称
|
|
39
|
-
* @param args 事件参数
|
|
40
|
-
*/
|
|
41
|
-
emit(eventName, ...args) {
|
|
42
|
-
const handlers = this.events.get(eventName);
|
|
43
|
-
if (handlers) {
|
|
44
|
-
handlers.forEach((handler) => {
|
|
45
|
-
try {
|
|
46
|
-
handler(...args);
|
|
47
|
-
} catch (error) {
|
|
48
|
-
console.error(`Error in event handler for ${eventName}:`, error);
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* 清除所有订阅
|
|
55
|
-
*/
|
|
56
|
-
clear() {
|
|
57
|
-
this.events.clear();
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* 获取指定事件的订阅者数量
|
|
61
|
-
* @param eventName 事件名称
|
|
62
|
-
* @returns 订阅者数量
|
|
63
|
-
*/
|
|
64
|
-
getSubscriberCount(eventName) {
|
|
65
|
-
const handlers = this.events.get(eventName);
|
|
66
|
-
return handlers ? handlers.size : 0;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* 检查是否有订阅者
|
|
70
|
-
* @param eventName 事件名称
|
|
71
|
-
* @returns 是否有订阅者
|
|
72
|
-
*/
|
|
73
|
-
hasSubscribers(eventName) {
|
|
74
|
-
return this.getSubscriberCount(eventName) > 0;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
exports.EventEmitter = EventEmitter;
|
|
1
|
+
"use strict";var o=Object.defineProperty;var c=(r,e,t)=>e in r?o(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var n=(r,e,t)=>c(r,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class l{constructor(){n(this,"events",new Map)}on(e,t){this.events.has(e)||this.events.set(e,new Set),this.events.get(e).add(t)}off(e,t){const s=this.events.get(e);s&&(s.delete(t),s.size===0&&this.events.delete(e))}emit(e,...t){const s=this.events.get(e);s&&s.forEach(i=>{try{i(...t)}catch(h){console.error(`Error in event handler for ${e}:`,h)}})}clear(){this.events.clear()}getSubscriberCount(e){const t=this.events.get(e);return t?t.size:0}hasSubscribers(e){return this.getSubscriberCount(e)>0}}exports.EventEmitter=l;
|
|
@@ -1,83 +1,4 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
6
|
-
const sourceMapJs = require("source-map-js");
|
|
7
|
-
class SourceError {
|
|
8
|
-
constructor(options) {
|
|
9
|
-
__publicField(this, "options", null);
|
|
10
|
-
if (options)
|
|
11
|
-
this.options = options;
|
|
12
|
-
}
|
|
13
|
-
parseStackTrace(stack) {
|
|
14
|
-
const lines = stack.split("\n");
|
|
15
|
-
const errorLine = lines.find((line) => line.includes(".js:") || line.includes(".ts:"));
|
|
16
|
-
if (!errorLine) {
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
const match = errorLine.match(/(?:at(?:\s+\S.*(?:[\n\r\u2028\u2029]\s*|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF])|\s{2,})\()?([^\s(]+):(\d+):(\d+)/);
|
|
20
|
-
if (!match) {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
const [_, fileName, lineStr, columnStr] = match;
|
|
24
|
-
return {
|
|
25
|
-
fileName,
|
|
26
|
-
lineNumber: Number.parseInt(lineStr, 10),
|
|
27
|
-
columnNumber: Number.parseInt(columnStr, 10)
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
async fetchSourceMap(fileName) {
|
|
31
|
-
try {
|
|
32
|
-
const sourceMapUrl = `${fileName}.map`;
|
|
33
|
-
const response = await fetch(sourceMapUrl);
|
|
34
|
-
if (!response.ok) {
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
return await response.json();
|
|
38
|
-
} catch (error) {
|
|
39
|
-
console.error("获取 source map 失败:", error);
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
// 通过 source map 获取原始错误位置和源码内容
|
|
44
|
-
async getErrorSource(error) {
|
|
45
|
-
if (!(error == null ? void 0 : error.stack)) {
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
try {
|
|
49
|
-
const stackInfo = this.parseStackTrace(error.stack);
|
|
50
|
-
if (!stackInfo) {
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
const sourceMapData = await this.fetchSourceMap(stackInfo.fileName);
|
|
54
|
-
if (!sourceMapData) {
|
|
55
|
-
return stackInfo;
|
|
56
|
-
}
|
|
57
|
-
const consumer = new sourceMapJs.SourceMapConsumer(sourceMapData);
|
|
58
|
-
const originalPosition = consumer.originalPositionFor({
|
|
59
|
-
line: stackInfo.lineNumber,
|
|
60
|
-
column: stackInfo.columnNumber
|
|
61
|
-
});
|
|
62
|
-
if (!originalPosition.source) {
|
|
63
|
-
return stackInfo;
|
|
64
|
-
}
|
|
65
|
-
const sourceContent = consumer.sourceContentFor(originalPosition.source);
|
|
66
|
-
const sourceLines = (sourceContent == null ? void 0 : sourceContent.split("\n")) || [];
|
|
67
|
-
const errorLineIndex = (originalPosition.line || 1) - 1;
|
|
68
|
-
const startLineIndex = Math.max(0, errorLineIndex - 5);
|
|
69
|
-
const endLineIndex = Math.min(sourceLines.length - 1, errorLineIndex + 5);
|
|
70
|
-
const relevantCode = sourceLines.slice(startLineIndex, endLineIndex + 1).join("\n");
|
|
71
|
-
return {
|
|
72
|
-
fileName: originalPosition.source,
|
|
73
|
-
lineNumber: originalPosition.line || 0,
|
|
74
|
-
columnNumber: originalPosition.column || 0,
|
|
75
|
-
sourceContent: relevantCode
|
|
76
|
-
};
|
|
77
|
-
} catch (error2) {
|
|
78
|
-
console.error("分析错误源码失败:", error2);
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
exports.SourceError = SourceError;
|
|
1
|
+
"use strict";var p=Object.defineProperty;var h=(o,e,n)=>e in o?p(o,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):o[e]=n;var a=(o,e,n)=>h(o,typeof e!="symbol"?e+"":e,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("source-map-js");class d{constructor(e){a(this,"options",null);e&&(this.options=e)}parseStackTrace(e){const r=e.split(`
|
|
2
|
+
`).find(l=>l.includes(".js:")||l.includes(".ts:"));if(!r)return null;const s=r.match(/(?:at(?:\s+\S.*(?:[\n\r\u2028\u2029]\s*|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF])|\s{2,})\()?([^\s(]+):(\d+):(\d+)/);if(!s)return null;const[t,c,u,i]=s;return{fileName:c,lineNumber:Number.parseInt(u,10),columnNumber:Number.parseInt(i,10)}}async fetchSourceMap(e){try{const n=`${e}.map`,r=await fetch(n);return r.ok?await r.json():null}catch(n){return console.error("获取 source map 失败:",n),null}}async getErrorSource(e){if(!(e!=null&&e.stack))return null;try{const n=this.parseStackTrace(e.stack);if(!n)return null;const r=await this.fetchSourceMap(n.fileName);if(!r)return n;const s=new S.SourceMapConsumer(r),t=s.originalPositionFor({line:n.lineNumber,column:n.columnNumber});if(!t.source)return n;const c=s.sourceContentFor(t.source),u=(c==null?void 0:c.split(`
|
|
3
|
+
`))||[],i=(t.line||1)-1,l=Math.max(0,i-5),m=Math.min(u.length-1,i+5),f=u.slice(l,m+1).join(`
|
|
4
|
+
`);return{fileName:t.source,lineNumber:t.line||0,columnNumber:t.column||0,sourceContent:f}}catch(n){return console.error("分析错误源码失败:",n),null}}}exports.SourceError=d;
|
package/dist/lib/src/core.js
CHANGED
|
@@ -1,239 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
6
|
-
const EventEmitter = require("./EventEmitter.js");
|
|
7
|
-
const SourceError = require("./SourceError.js");
|
|
8
|
-
const utils = require("./utils.js");
|
|
9
|
-
const _ErrorMonitor = class _ErrorMonitor {
|
|
10
|
-
/**
|
|
11
|
-
* 取消订阅错误上报事件
|
|
12
|
-
* @param callback - 错误上报回调函数
|
|
13
|
-
*/
|
|
14
|
-
// private offErrorReported(callback: (error: ErrorInfo) => void): void {
|
|
15
|
-
// this.event.off(this.ERROR_REPORTED, callback);
|
|
16
|
-
// }
|
|
17
|
-
/**
|
|
18
|
-
* 私有构造函数,防止外部直接实例化
|
|
19
|
-
*/
|
|
20
|
-
constructor(options) {
|
|
21
|
-
__publicField(this, "options");
|
|
22
|
-
__publicField(this, "event");
|
|
23
|
-
__publicField(this, "source");
|
|
24
|
-
// 错误事件类型常量
|
|
25
|
-
__publicField(this, "ERROR_REPORTED", "error-reported");
|
|
26
|
-
this.options = this.validateOptions(options);
|
|
27
|
-
this.event = new EventEmitter.EventEmitter();
|
|
28
|
-
this.source = new SourceError.SourceError();
|
|
29
|
-
this.init();
|
|
30
|
-
if (options.integrations)
|
|
31
|
-
this.initIntegrations();
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* 订阅错误上报事件
|
|
35
|
-
* @param callback - 错误上报回调函数
|
|
36
|
-
*/
|
|
37
|
-
onErrorReported(callback) {
|
|
38
|
-
this.event.on(this.ERROR_REPORTED, callback);
|
|
39
|
-
}
|
|
40
|
-
initIntegrations() {
|
|
41
|
-
var _a;
|
|
42
|
-
(_a = this.options.integrations) == null ? void 0 : _a.forEach((integration) => {
|
|
43
|
-
try {
|
|
44
|
-
integration.install(this);
|
|
45
|
-
} catch (error) {
|
|
46
|
-
console.error(`Failed to initialize integration ${integration.name}:`, error);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* 获取ErrorMonitor实例
|
|
52
|
-
* @throws {Error} 当实例未初始化时抛出错误
|
|
53
|
-
*/
|
|
54
|
-
static getInstance() {
|
|
55
|
-
if (!_ErrorMonitor.instance) {
|
|
56
|
-
throw new Error("ErrorMonitor未初始化,请先调用initialize方法");
|
|
57
|
-
}
|
|
58
|
-
return _ErrorMonitor.instance;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* 静态方法:手动上报错误信息
|
|
62
|
-
* @param error - 错误信息,支持 ErrorInfo | Error | string 类型
|
|
63
|
-
* @example
|
|
64
|
-
* ```typescript
|
|
65
|
-
* // 上报字符串错误
|
|
66
|
-
* ErrorMonitor.captureError('自定义错误信息');
|
|
67
|
-
*
|
|
68
|
-
* // 上报 Error 对象
|
|
69
|
-
* ErrorMonitor.captureError(new Error('发生错误'));
|
|
70
|
-
*
|
|
71
|
-
* // 上报完整错误信息
|
|
72
|
-
* ErrorMonitor.captureError({
|
|
73
|
-
* type: 'custom',
|
|
74
|
-
* message: '自定义错误',
|
|
75
|
-
* stack: '错误堆栈'
|
|
76
|
-
* });
|
|
77
|
-
* ```
|
|
78
|
-
*/
|
|
79
|
-
/**
|
|
80
|
-
* 验证并补充默认配置项
|
|
81
|
-
* @param options - 原始配置项
|
|
82
|
-
* @returns 处理后的完整配置项
|
|
83
|
-
* @throws {Error} 当必要配置项缺失时抛出错误
|
|
84
|
-
*/
|
|
85
|
-
validateOptions(options) {
|
|
86
|
-
if (!options.url) {
|
|
87
|
-
throw new Error("上报地址url不能为空");
|
|
88
|
-
}
|
|
89
|
-
if (!options.appId) {
|
|
90
|
-
throw new Error("应用标识appId不能为空");
|
|
91
|
-
}
|
|
92
|
-
return {
|
|
93
|
-
env: "development",
|
|
94
|
-
sampleRate: 1,
|
|
95
|
-
...options
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* 初始化错误监听器
|
|
100
|
-
* 包括:JS运行时错误、Promise异常、资源加载错误
|
|
101
|
-
*/
|
|
102
|
-
init() {
|
|
103
|
-
this.onErrorReported((error) => {
|
|
104
|
-
this.reportError(error);
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* 获取当前客户端信息
|
|
109
|
-
* @returns 包含URL、浏览器信息、屏幕尺寸等客户端数据
|
|
110
|
-
*/
|
|
111
|
-
getClientInfo() {
|
|
112
|
-
return {
|
|
113
|
-
url: window.location.href,
|
|
114
|
-
userAgent: navigator.userAgent,
|
|
115
|
-
screenSize: `${window.screen.width}x${window.screen.height}`,
|
|
116
|
-
timestamp: Date.now()
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* 上报错误信息到服务器
|
|
121
|
-
* @param errorInfo - 错误信息对象
|
|
122
|
-
*/
|
|
123
|
-
report(errorInfo) {
|
|
124
|
-
if (Math.random() > (this.options.sampleRate || 1)) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
let reportData = {
|
|
128
|
-
...errorInfo,
|
|
129
|
-
appId: this.options.appId,
|
|
130
|
-
env: this.options.env
|
|
131
|
-
};
|
|
132
|
-
let url = this.options.url;
|
|
133
|
-
if (this.options.paramsSerializer) {
|
|
134
|
-
const params = this.options.paramsSerializer();
|
|
135
|
-
url = `${url}?${utils.stringify(params)}`;
|
|
136
|
-
}
|
|
137
|
-
if (this.options.beforeSend) {
|
|
138
|
-
const result = this.options.beforeSend(reportData);
|
|
139
|
-
if (!result) {
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
reportData = result;
|
|
143
|
-
}
|
|
144
|
-
if (navigator.sendBeacon) {
|
|
145
|
-
navigator.sendBeacon(url, JSON.stringify(reportData));
|
|
146
|
-
} else {
|
|
147
|
-
fetch(url, {
|
|
148
|
-
method: "POST",
|
|
149
|
-
body: JSON.stringify(reportData),
|
|
150
|
-
headers: {
|
|
151
|
-
"Content-Type": "application/json"
|
|
152
|
-
},
|
|
153
|
-
keepalive: true
|
|
154
|
-
}).catch(() => {
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* 标准化错误信息
|
|
160
|
-
* @param error - 原始错误信息
|
|
161
|
-
* @returns 标准化后的错误信息对象
|
|
162
|
-
*/
|
|
163
|
-
normalizeError(error) {
|
|
164
|
-
if (this.isErrorInfo(error)) {
|
|
165
|
-
return {
|
|
166
|
-
...error,
|
|
167
|
-
extraInfo: this.options.extraInfo,
|
|
168
|
-
...this.getClientInfo()
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
if (error instanceof Error) {
|
|
172
|
-
return {
|
|
173
|
-
type: error.name,
|
|
174
|
-
message: error.message,
|
|
175
|
-
stack: error.stack,
|
|
176
|
-
extraInfo: this.options.extraInfo,
|
|
177
|
-
...this.getClientInfo()
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
return {
|
|
181
|
-
type: "Error",
|
|
182
|
-
message: error,
|
|
183
|
-
extraInfo: this.options.extraInfo,
|
|
184
|
-
...this.getClientInfo()
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* 类型守卫:判断是否为 ErrorInfo 类型
|
|
189
|
-
* @param error - 待检查的错误信息
|
|
190
|
-
* @returns 是否为 ErrorInfo 类型
|
|
191
|
-
*/
|
|
192
|
-
isErrorInfo(error) {
|
|
193
|
-
return typeof error === "object" && error !== null && "type" in error && "message" in error;
|
|
194
|
-
}
|
|
195
|
-
reportError(error) {
|
|
196
|
-
if (!_ErrorMonitor.instance) {
|
|
197
|
-
throw new Error("ErrorMonitor未初始化,请先调用initialize方法");
|
|
198
|
-
}
|
|
199
|
-
const errorInfo = this.normalizeError(error);
|
|
200
|
-
console.log("errorInfo", errorInfo);
|
|
201
|
-
this.report(errorInfo);
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* 初始化错误监控实例
|
|
205
|
-
* @param options - 监控配置项
|
|
206
|
-
* @returns ErrorMonitor实例
|
|
207
|
-
* @throws {Error} 当重复初始化或配置项缺失时抛出错误
|
|
208
|
-
*/
|
|
209
|
-
static initialize(options) {
|
|
210
|
-
if (_ErrorMonitor.instance) {
|
|
211
|
-
throw new Error("ErrorMonitor已经初始化,请勿重复初始化");
|
|
212
|
-
}
|
|
213
|
-
_ErrorMonitor.instance = new _ErrorMonitor(options);
|
|
214
|
-
return _ErrorMonitor.instance;
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* 销毁实例,清理资源
|
|
218
|
-
*/
|
|
219
|
-
static destroy() {
|
|
220
|
-
if (_ErrorMonitor.instance) {
|
|
221
|
-
_ErrorMonitor.instance = null;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
static captureError(error) {
|
|
225
|
-
_ErrorMonitor.getInstance().reportError(error);
|
|
226
|
-
}
|
|
227
|
-
emitError(error) {
|
|
228
|
-
this.event.emit(this.ERROR_REPORTED, error);
|
|
229
|
-
}
|
|
230
|
-
async getErrorSource(error) {
|
|
231
|
-
return this.source.getErrorSource(error);
|
|
232
|
-
}
|
|
233
|
-
get env() {
|
|
234
|
-
return this.options.env;
|
|
235
|
-
}
|
|
236
|
-
};
|
|
237
|
-
__publicField(_ErrorMonitor, "instance", null);
|
|
238
|
-
let ErrorMonitor = _ErrorMonitor;
|
|
239
|
-
exports.ErrorMonitor = ErrorMonitor;
|
|
1
|
+
"use strict";var c=Object.defineProperty;var h=(o,t,e)=>t in o?c(o,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[t]=e;var i=(o,t,e)=>h(o,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("./EventEmitter.js"),l=require("./SourceError.js"),u=require("./utils.js"),r=class r{constructor(t){i(this,"options");i(this,"event");i(this,"source");i(this,"ERROR_REPORTED","error-reported");this.options=this.validateOptions(t),this.event=new p.EventEmitter,this.source=new l.SourceError,this.init(),t.integrations&&this.initIntegrations()}onErrorReported(t){this.event.on(this.ERROR_REPORTED,t)}initIntegrations(){var t;(t=this.options.integrations)==null||t.forEach(e=>{try{e.install(this)}catch(n){console.error(`Failed to initialize integration ${e.name}:`,n)}})}static getInstance(){if(!r.instance)throw new Error("ErrorMonitor未初始化,请先调用initialize方法");return r.instance}validateOptions(t){if(!t.url)throw new Error("上报地址url不能为空");if(!t.appId)throw new Error("平台标识appId不能为空");return{env:"development",sampleRate:1,...t}}init(){this.onErrorReported(t=>{this.reportError(t)})}getClientInfo(){return{url:window.location.href,userAgent:navigator.userAgent,screenSize:`${window.screen.width}x${window.screen.height}`,timestamp:Date.now()}}report(t){if(Math.random()>(this.options.sampleRate||1))return;let e={...t,appId:this.options.appId,env:this.options.env},n=this.options.url;if(this.options.paramsSerializer){const s=this.options.paramsSerializer();n=`${n}?${u.stringify(s)}`}if(this.options.beforeSend){const s=this.options.beforeSend(e);if(!s)return;e=s}navigator.sendBeacon?navigator.sendBeacon(n,JSON.stringify(e)):fetch(n,{method:"POST",body:JSON.stringify(e),headers:{"Content-Type":"text/plain"},keepalive:!0}).catch(()=>{})}normalizeError(t){return this.isErrorInfo(t)?{...t,extraInfo:this.options.extraInfo,...this.getClientInfo()}:t instanceof Error?{type:t.name,message:t.message,stack:t.stack,extraInfo:this.options.extraInfo,...this.getClientInfo()}:{type:"Error",message:t,extraInfo:this.options.extraInfo,...this.getClientInfo()}}isErrorInfo(t){return typeof t=="object"&&t!==null&&"type"in t&&"message"in t}reportError(t){if(!r.instance)throw new Error("ErrorMonitor未初始化,请先调用initialize方法");const e=this.normalizeError(t);console.log("errorInfo",e),this.report(e)}static initialize(t){if(r.instance)throw new Error("ErrorMonitor已经初始化,请勿重复初始化");return r.instance=new r(t),r.instance}static destroy(){r.instance&&(r.instance=null)}static captureError(t){r.getInstance().reportError(t)}emitError(t){this.event.emit(this.ERROR_REPORTED,t)}async getErrorSource(t){return this.source.getErrorSource(t)}get env(){return this.options.env}};i(r,"instance",null);let a=r;exports.ErrorMonitor=a;
|
package/dist/lib/src/index.js
CHANGED
|
@@ -1,10 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const core = require("./core.js");
|
|
4
|
-
const SourceError = require("./SourceError.js");
|
|
5
|
-
const VueError = require("./integrations/VueError.js");
|
|
6
|
-
const BrowserError = require("./integrations/BrowserError.js");
|
|
7
|
-
exports.ErrorMonitor = core.ErrorMonitor;
|
|
8
|
-
exports.SourceError = SourceError.SourceError;
|
|
9
|
-
exports.VueError = VueError.VueError;
|
|
10
|
-
exports.BrowserError = BrowserError.BrowserError;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("./core.js"),o=require("./SourceError.js"),e=require("./integrations/VueError.js"),t=require("./integrations/BrowserError.js"),s=require("./utils.js");exports.ErrorMonitor=r.ErrorMonitor;exports.SourceError=o.SourceError;exports.VueError=e.VueError;exports.BrowserError=t.BrowserError;exports.timestampToBase66=s.timestampToBase66;
|
|
@@ -1,76 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
6
|
-
const utils = require("../utils.js");
|
|
7
|
-
class BrowserError {
|
|
8
|
-
constructor() {
|
|
9
|
-
__publicField(this, "name", "BrowserError");
|
|
10
|
-
__publicField(this, "monitor", null);
|
|
11
|
-
}
|
|
12
|
-
install(monitor) {
|
|
13
|
-
this.monitor = monitor;
|
|
14
|
-
window.addEventListener("error", (event) => {
|
|
15
|
-
this.handleJsError(event);
|
|
16
|
-
}, true);
|
|
17
|
-
window.addEventListener("unhandledrejection", (event) => {
|
|
18
|
-
this.handlePromiseError(event);
|
|
19
|
-
});
|
|
20
|
-
window.addEventListener("error", (event) => {
|
|
21
|
-
if (event.target && event.target.tagName) {
|
|
22
|
-
this.handleResourceError(event);
|
|
23
|
-
}
|
|
24
|
-
}, true);
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* 处理 JS 运行时错误
|
|
28
|
-
* @param event - 错误事件对象
|
|
29
|
-
*/
|
|
30
|
-
handleJsError(event) {
|
|
31
|
-
var _a, _b;
|
|
32
|
-
const errorInfo = {
|
|
33
|
-
type: (_a = event.error) == null ? void 0 : _a.name,
|
|
34
|
-
message: event.message,
|
|
35
|
-
source: {
|
|
36
|
-
fileName: event.filename,
|
|
37
|
-
lineNumber: event.lineno,
|
|
38
|
-
columnNumber: event.colno
|
|
39
|
-
},
|
|
40
|
-
stack: (_b = event.error) == null ? void 0 : _b.stack,
|
|
41
|
-
...utils.getClientInfo()
|
|
42
|
-
};
|
|
43
|
-
if (this.monitor)
|
|
44
|
-
this.monitor.emitError(errorInfo);
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* 处理 Promise 异常
|
|
48
|
-
* @param event - Promise 异常事件对象
|
|
49
|
-
*/
|
|
50
|
-
handlePromiseError(event) {
|
|
51
|
-
var _a, _b;
|
|
52
|
-
const errorInfo = {
|
|
53
|
-
type: "NetworkError",
|
|
54
|
-
message: ((_a = event.reason) == null ? void 0 : _a.message) || "Promise Error",
|
|
55
|
-
stack: (_b = event.reason) == null ? void 0 : _b.stack,
|
|
56
|
-
...utils.getClientInfo()
|
|
57
|
-
};
|
|
58
|
-
if (this.monitor)
|
|
59
|
-
this.monitor.emitError(errorInfo);
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* 处理资源加载错误
|
|
63
|
-
* @param event - 资源错误事件对象
|
|
64
|
-
*/
|
|
65
|
-
handleResourceError(event) {
|
|
66
|
-
const target = event.target;
|
|
67
|
-
const errorInfo = {
|
|
68
|
-
type: "ResourceError",
|
|
69
|
-
message: `资源加载失败: ${target.tagName} ${target.src || target.href}`,
|
|
70
|
-
...utils.getClientInfo()
|
|
71
|
-
};
|
|
72
|
-
if (this.monitor)
|
|
73
|
-
this.monitor.emitError(errorInfo);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
exports.BrowserError = BrowserError;
|
|
1
|
+
"use strict";var a=Object.defineProperty;var m=(t,r,e)=>r in t?a(t,r,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[r]=e;var i=(t,r,e)=>m(t,typeof r!="symbol"?r+"":r,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("../utils.js");class l{constructor(){i(this,"name","BrowserError");i(this,"monitor",null)}install(r){this.monitor=r,window.addEventListener("error",e=>{this.handleJsError(e)},!0),window.addEventListener("unhandledrejection",e=>{this.handlePromiseError(e)}),window.addEventListener("error",e=>{e.target&&e.target.tagName&&this.handleResourceError(e)},!0)}handleJsError(r){var o,s;const e={type:(o=r.error)==null?void 0:o.name,message:r.message,source:{fileName:r.filename,lineNumber:r.lineno,columnNumber:r.colno},stack:(s=r.error)==null?void 0:s.stack,...n.getClientInfo()};this.monitor&&this.monitor.emitError(e)}handlePromiseError(r){var o,s;const e={type:"NetworkError",message:((o=r.reason)==null?void 0:o.message)||"Promise Error",stack:(s=r.reason)==null?void 0:s.stack,...n.getClientInfo()};this.monitor&&this.monitor.emitError(e)}handleResourceError(r){const e=r.target,o={type:"ResourceError",message:`资源加载失败: ${e.tagName} ${e.src||e.href}`,...n.getClientInfo()};this.monitor&&this.monitor.emitError(o)}}exports.BrowserError=l;
|
|
@@ -1,27 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
6
|
-
class VueError {
|
|
7
|
-
constructor(app) {
|
|
8
|
-
__publicField(this, "name", "VueError");
|
|
9
|
-
__publicField(this, "app");
|
|
10
|
-
this.app = app;
|
|
11
|
-
}
|
|
12
|
-
install(monitor) {
|
|
13
|
-
if (monitor.env === "production") {
|
|
14
|
-
this.app.config.errorHandler = async (error) => {
|
|
15
|
-
const source = await monitor.getErrorSource(error);
|
|
16
|
-
console.log(source);
|
|
17
|
-
monitor.emitError({
|
|
18
|
-
type: error.name,
|
|
19
|
-
message: error.message,
|
|
20
|
-
stack: error.stack,
|
|
21
|
-
source
|
|
22
|
-
});
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
exports.VueError = VueError;
|
|
1
|
+
"use strict";var o=Object.defineProperty;var c=(s,e,r)=>e in s?o(s,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):s[e]=r;var a=(s,e,r)=>c(s,typeof e!="symbol"?e+"":e,r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class l{constructor(e){a(this,"name","VueError");a(this,"app");this.app=e}install(e){e.env==="production"&&(this.app.config.errorHandler=async r=>{const t=await e.getErrorSource(r);console.log(t),e.emitError({type:r.name,message:r.message,stack:r.stack,source:t,level:"error"})})}}exports.VueError=l;
|
package/dist/lib/src/utils.js
CHANGED
|
@@ -1,117 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
function getClientInfo() {
|
|
4
|
-
return {
|
|
5
|
-
url: window.location.href,
|
|
6
|
-
userAgent: navigator.userAgent,
|
|
7
|
-
screenSize: `${window.screen.width}x${window.screen.height}`,
|
|
8
|
-
timestamp: Date.now()
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
function stringify(obj, options = {}) {
|
|
12
|
-
const {
|
|
13
|
-
encode = true,
|
|
14
|
-
encodeValuesOnly = false,
|
|
15
|
-
arrayFormat = "indices",
|
|
16
|
-
skipNulls = false,
|
|
17
|
-
delimiter = "&",
|
|
18
|
-
strictNullHandling = false,
|
|
19
|
-
sort,
|
|
20
|
-
filter,
|
|
21
|
-
allowDots = false,
|
|
22
|
-
serializeDate = (date) => date.toISOString(),
|
|
23
|
-
format = "RFC3986",
|
|
24
|
-
addQueryPrefix = false,
|
|
25
|
-
charset = "utf-8"
|
|
26
|
-
} = options;
|
|
27
|
-
const parts = [];
|
|
28
|
-
const encoder = charset === "iso-8859-1" ? encodeURIComponentISO88591 : encodeURIComponent;
|
|
29
|
-
const encodeValue = (value) => encode ? encoder(value) : value;
|
|
30
|
-
const processKeyValue = (key, value, prefix = null) => {
|
|
31
|
-
const fullKey = prefix ? `${prefix}[${key}]` : key;
|
|
32
|
-
if (filter) {
|
|
33
|
-
const filtered = filter(fullKey, value);
|
|
34
|
-
if (filtered === void 0)
|
|
35
|
-
return;
|
|
36
|
-
value = filtered;
|
|
37
|
-
}
|
|
38
|
-
if (value === null) {
|
|
39
|
-
if (strictNullHandling) {
|
|
40
|
-
parts.push(encodeValue(fullKey) + (encodeValuesOnly ? "" : "="));
|
|
41
|
-
} else if (!skipNulls) {
|
|
42
|
-
parts.push(`${encodeValue(fullKey)}=`);
|
|
43
|
-
}
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
if (typeof value === "boolean" || typeof value === "number") {
|
|
47
|
-
value = String(value);
|
|
48
|
-
}
|
|
49
|
-
if (value instanceof Date) {
|
|
50
|
-
value = serializeDate(value);
|
|
51
|
-
}
|
|
52
|
-
if (Array.isArray(value)) {
|
|
53
|
-
if (value.length === 0 && skipNulls)
|
|
54
|
-
return;
|
|
55
|
-
switch (arrayFormat) {
|
|
56
|
-
case "indices":
|
|
57
|
-
value.forEach((item, i) => {
|
|
58
|
-
processKeyValue(String(i), item, fullKey);
|
|
59
|
-
});
|
|
60
|
-
break;
|
|
61
|
-
case "brackets":
|
|
62
|
-
value.forEach((item) => {
|
|
63
|
-
processKeyValue("", item, fullKey);
|
|
64
|
-
});
|
|
65
|
-
break;
|
|
66
|
-
case "repeat":
|
|
67
|
-
value.forEach((item) => {
|
|
68
|
-
processKeyValue(fullKey, item);
|
|
69
|
-
});
|
|
70
|
-
break;
|
|
71
|
-
case "comma":
|
|
72
|
-
const commaSeparated = value.join(",");
|
|
73
|
-
if (commaSeparated.length > 0) {
|
|
74
|
-
parts.push(
|
|
75
|
-
`${encodeValue(fullKey)}=${encodeValue(commaSeparated)}`
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
} else if (typeof value === "object") {
|
|
81
|
-
Object.keys(value).forEach((subKey) => {
|
|
82
|
-
const separator = allowDots ? "." : "[";
|
|
83
|
-
const suffix = allowDots ? "" : "]";
|
|
84
|
-
processKeyValue(
|
|
85
|
-
subKey,
|
|
86
|
-
value[subKey],
|
|
87
|
-
`${fullKey}${separator}${subKey}${suffix}`
|
|
88
|
-
);
|
|
89
|
-
});
|
|
90
|
-
} else {
|
|
91
|
-
const encodedKey = encode && !encodeValuesOnly ? encodeValue(fullKey) : fullKey;
|
|
92
|
-
const encodedValue = encodeValue(String(value));
|
|
93
|
-
parts.push(`${encodedKey}=${encodedValue}`);
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
let keys = Object.keys(obj);
|
|
97
|
-
if (sort) {
|
|
98
|
-
keys = keys.sort(sort);
|
|
99
|
-
}
|
|
100
|
-
keys.forEach((key) => {
|
|
101
|
-
const value = obj[key];
|
|
102
|
-
processKeyValue(key, value);
|
|
103
|
-
});
|
|
104
|
-
let result = parts.join(delimiter);
|
|
105
|
-
if (addQueryPrefix && result.length > 0) {
|
|
106
|
-
result = `?${result}`;
|
|
107
|
-
}
|
|
108
|
-
return result;
|
|
109
|
-
}
|
|
110
|
-
function encodeURIComponentISO88591(str) {
|
|
111
|
-
return encodeURIComponent(str).replace(/%[0-9A-F]{2}/g, (match) => {
|
|
112
|
-
const code = Number.parseInt(match.substring(1), 16);
|
|
113
|
-
return code >= 128 && code <= 255 ? String.fromCharCode(code) : match;
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
exports.getClientInfo = getClientInfo;
|
|
117
|
-
exports.stringify = stringify;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function D(){return{url:window.location.href,userAgent:navigator.userAgent,screenSize:`${window.screen.width}x${window.screen.height}`,timestamp:Date.now()}}function E(i,c={}){const{encode:t=!0,encodeValuesOnly:f=!1,arrayFormat:g="indices",skipNulls:p=!1,delimiter:S="&",strictNullHandling:I=!1,sort:y,filter:w,allowDots:$=!1,serializeDate:k=r=>r.toISOString(),format:A="RFC3986",addQueryPrefix:C=!1,charset:O="utf-8"}=c,l=[],j=O==="iso-8859-1"?V:encodeURIComponent,a=r=>t?j(r):r,d=(r,e,b=null)=>{const o=b?`${b}[${r}]`:r;if(w){const n=w(o,e);if(n===void 0)return;e=n}if(e===null){I?l.push(a(o)+(f?"":"=")):p||l.push(`${a(o)}=`);return}if((typeof e=="boolean"||typeof e=="number")&&(e=String(e)),e instanceof Date&&(e=k(e)),Array.isArray(e)){if(e.length===0&&p)return;switch(g){case"indices":e.forEach((s,u)=>{d(String(u),s,o)});break;case"brackets":e.forEach(s=>{d("",s,o)});break;case"repeat":e.forEach(s=>{d(o,s)});break;case"comma":const n=e.join(",");n.length>0&&l.push(`${a(o)}=${a(n)}`);break}}else if(typeof e=="object")Object.keys(e).forEach(n=>{const s=$?".":"[",u=$?"":"]";d(n,e[n],`${o}${s}${n}${u}`)});else{const n=t&&!f?a(o):o,s=a(String(e));l.push(`${n}=${s}`)}};let m=Object.keys(i);y&&(m=m.sort(y)),m.forEach(r=>{const e=i[r];d(r,e)});let h=l.join(S);return C&&h.length>0&&(h=`?${h}`),h}function V(i){return encodeURIComponent(i).replace(/%[0-9A-F]{2}/g,c=>{const t=Number.parseInt(c.substring(1),16);return t>=128&&t<=255?String.fromCharCode(t):c})}function x(i,c=Date.now()){if(i.length!==66)throw new Error("BASE66_CHARS must contain exactly 66 characters");let t=c,f="";if(t===0)return i[0];for(;t>0;){const g=t%66;f=i[g]+f,t=Math.floor(t/66)}return f}exports.getClientInfo=D;exports.stringify=E;exports.timestampToBase66=x;
|
|
@@ -65,6 +65,7 @@ export interface BreadcrumbItem {
|
|
|
65
65
|
export interface ErrorInfo extends Partial<ClientInfo> {
|
|
66
66
|
type: ErrorType;
|
|
67
67
|
message: string;
|
|
68
|
+
level?: 'fatal' | 'error' | 'warn' | 'info' | 'debug';
|
|
68
69
|
source?: ErrorSourceInfo;
|
|
69
70
|
stack?: string;
|
|
70
71
|
extraInfo?: Record<string, any>;
|