sobey-monitor-sdk 1.1.2 → 1.1.3
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/core/config.d.ts +0 -1
- package/dist/frameworks/react.d.ts +1 -1
- package/dist/frameworks/vue.d.ts +1 -1
- package/dist/index.cjs.js +196 -111
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +27 -19
- package/dist/index.esm.js +196 -111
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +196 -111
- package/dist/index.umd.js.map +1 -1
- package/dist/reporter/index.d.ts +18 -0
- package/package.json +1 -1
package/dist/index.umd.js
CHANGED
|
@@ -51,27 +51,14 @@
|
|
|
51
51
|
}
|
|
52
52
|
/**
|
|
53
53
|
* 初始化配置
|
|
54
|
-
* @param skipValidation 是否跳过必填校验(用于远程配置已获取 appId/dsn 的场景)
|
|
55
54
|
*/
|
|
56
55
|
init(userConfig, skipValidation = false) {
|
|
57
56
|
if (!skipValidation) {
|
|
58
|
-
// 如果没有 configUrl,则 appId 和 dsn 是必填的
|
|
59
|
-
if (!userConfig.configUrl) {
|
|
60
|
-
if (!userConfig.appId) {
|
|
61
|
-
throw new Error('[Monitor] appId is required when configUrl is not provided');
|
|
62
|
-
}
|
|
63
|
-
if (!userConfig.dsn) {
|
|
64
|
-
throw new Error('[Monitor] dsn is required when configUrl is not provided');
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
// 远程配置模式下,校验合并后的配置
|
|
70
57
|
if (!userConfig.appId) {
|
|
71
|
-
throw new Error('[Monitor] appId is required
|
|
58
|
+
throw new Error('[Monitor] appId is required');
|
|
72
59
|
}
|
|
73
60
|
if (!userConfig.dsn) {
|
|
74
|
-
throw new Error('[Monitor] dsn is required
|
|
61
|
+
throw new Error('[Monitor] dsn is required');
|
|
75
62
|
}
|
|
76
63
|
}
|
|
77
64
|
this.config = this.mergeConfig(DEFAULT_CONFIG, userConfig);
|
|
@@ -295,6 +282,13 @@
|
|
|
295
282
|
doSend(data) {
|
|
296
283
|
const cfg = config.get();
|
|
297
284
|
const dsn = cfg.dsn;
|
|
285
|
+
// dsn 未配置,跳过发送
|
|
286
|
+
if (!dsn) {
|
|
287
|
+
if (cfg.debug) {
|
|
288
|
+
console.warn('[Monitor] dsn not configured, skip sending');
|
|
289
|
+
}
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
298
292
|
const payload = JSON.stringify(data);
|
|
299
293
|
// 优先使用 sendBeacon(更可靠、异步、不阻塞页面)
|
|
300
294
|
if (supportsSendBeacon()) {
|
|
@@ -393,13 +387,63 @@
|
|
|
393
387
|
* 上报器类
|
|
394
388
|
*/
|
|
395
389
|
class Reporter {
|
|
390
|
+
constructor() {
|
|
391
|
+
/** SDK 是否就绪 */
|
|
392
|
+
this.ready = false;
|
|
393
|
+
/** 早期数据缓存队列(SDK 未就绪时缓存) */
|
|
394
|
+
this.earlyBuffer = [];
|
|
395
|
+
/** 最大缓存数量 */
|
|
396
|
+
this.maxEarlyBufferSize = 50;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* 设置 SDK 就绪状态
|
|
400
|
+
*/
|
|
401
|
+
setReady(ready) {
|
|
402
|
+
this.ready = ready;
|
|
403
|
+
// 就绪后发送缓存的早期数据
|
|
404
|
+
if (ready && this.earlyBuffer.length > 0) {
|
|
405
|
+
console.log(`[Monitor] Flushing ${this.earlyBuffer.length} early buffered items`);
|
|
406
|
+
this.flushEarlyBuffer();
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* 发送早期缓存的数据
|
|
411
|
+
*/
|
|
412
|
+
flushEarlyBuffer() {
|
|
413
|
+
while (this.earlyBuffer.length > 0) {
|
|
414
|
+
const item = this.earlyBuffer.shift();
|
|
415
|
+
if (!item)
|
|
416
|
+
continue;
|
|
417
|
+
switch (item.type) {
|
|
418
|
+
case 'error':
|
|
419
|
+
this.reportError(item.data);
|
|
420
|
+
break;
|
|
421
|
+
case 'performance':
|
|
422
|
+
this.reportPerformance(item.data);
|
|
423
|
+
break;
|
|
424
|
+
case 'behavior':
|
|
425
|
+
this.reportBehavior(item.data);
|
|
426
|
+
break;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* 缓存早期数据
|
|
432
|
+
*/
|
|
433
|
+
bufferEarly(type, data) {
|
|
434
|
+
if (this.earlyBuffer.length >= this.maxEarlyBufferSize) {
|
|
435
|
+
// 缓存已满,丢弃最早的数据
|
|
436
|
+
this.earlyBuffer.shift();
|
|
437
|
+
}
|
|
438
|
+
this.earlyBuffer.push({ type, data });
|
|
439
|
+
}
|
|
396
440
|
/**
|
|
397
441
|
* 构建基础数据
|
|
398
442
|
*/
|
|
399
443
|
buildBaseData() {
|
|
400
444
|
const cfg = config.get();
|
|
401
445
|
return {
|
|
402
|
-
appId: cfg.appId,
|
|
446
|
+
appId: cfg.appId || '',
|
|
403
447
|
userId: cfg.user?.userId,
|
|
404
448
|
sessionId: context.getSessionId(),
|
|
405
449
|
pageUrl: getPageUrl(),
|
|
@@ -420,6 +464,11 @@
|
|
|
420
464
|
* 上报错误
|
|
421
465
|
*/
|
|
422
466
|
reportError(data) {
|
|
467
|
+
// SDK 未就绪时缓存数据
|
|
468
|
+
if (!this.ready) {
|
|
469
|
+
this.bufferEarly('error', data);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
423
472
|
if (!this.shouldSample('error'))
|
|
424
473
|
return;
|
|
425
474
|
const cfg = config.get();
|
|
@@ -441,6 +490,11 @@
|
|
|
441
490
|
* 上报性能
|
|
442
491
|
*/
|
|
443
492
|
reportPerformance(data) {
|
|
493
|
+
// SDK 未就绪时缓存数据
|
|
494
|
+
if (!this.ready) {
|
|
495
|
+
this.bufferEarly('performance', data);
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
444
498
|
if (!this.shouldSample('performance'))
|
|
445
499
|
return;
|
|
446
500
|
const reportData = {
|
|
@@ -453,6 +507,11 @@
|
|
|
453
507
|
* 上报行为
|
|
454
508
|
*/
|
|
455
509
|
reportBehavior(data) {
|
|
510
|
+
// SDK 未就绪时缓存数据
|
|
511
|
+
if (!this.ready) {
|
|
512
|
+
this.bufferEarly('behavior', data);
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
456
515
|
if (!this.shouldSample('behavior'))
|
|
457
516
|
return;
|
|
458
517
|
const reportData = {
|
|
@@ -1441,13 +1500,8 @@
|
|
|
1441
1500
|
* ```
|
|
1442
1501
|
*/
|
|
1443
1502
|
const VueMonitorPlugin = {
|
|
1444
|
-
install(app, options) {
|
|
1445
|
-
//
|
|
1446
|
-
if (!options || (!options.configUrl && (!options.appId || !options.dsn))) {
|
|
1447
|
-
console.warn('[Monitor] VueMonitorPlugin requires either configUrl or (appId and dsn) in options');
|
|
1448
|
-
return;
|
|
1449
|
-
}
|
|
1450
|
-
// 初始化 SDK(如果尚未初始化)
|
|
1503
|
+
install(app, options = {}) {
|
|
1504
|
+
// 初始化 SDK(支持空配置,后续通过 updateConfig 激活)
|
|
1451
1505
|
try {
|
|
1452
1506
|
monitor.init(options);
|
|
1453
1507
|
}
|
|
@@ -1543,18 +1597,8 @@
|
|
|
1543
1597
|
* );
|
|
1544
1598
|
* ```
|
|
1545
1599
|
*/
|
|
1546
|
-
function createReactErrorBoundary(React, config) {
|
|
1547
|
-
//
|
|
1548
|
-
if (!config || (!config.configUrl && (!config.appId || !config.dsn))) {
|
|
1549
|
-
console.warn('[Monitor] createReactErrorBoundary requires either configUrl or (appId and dsn) in config');
|
|
1550
|
-
// 返回一个空的组件
|
|
1551
|
-
return class EmptyBoundary extends React.Component {
|
|
1552
|
-
render() {
|
|
1553
|
-
return this.props.children;
|
|
1554
|
-
}
|
|
1555
|
-
};
|
|
1556
|
-
}
|
|
1557
|
-
// 初始化 SDK(如果尚未初始化)
|
|
1600
|
+
function createReactErrorBoundary(React, config = {}) {
|
|
1601
|
+
// 初始化 SDK(支持空配置,后续通过 updateConfig 激活)
|
|
1558
1602
|
try {
|
|
1559
1603
|
monitor.init(config);
|
|
1560
1604
|
}
|
|
@@ -1650,64 +1694,131 @@
|
|
|
1650
1694
|
*/
|
|
1651
1695
|
class MonitorSDK {
|
|
1652
1696
|
constructor() {
|
|
1697
|
+
/** SDK 是否已初始化(基础初始化,可能还没有完整配置) */
|
|
1653
1698
|
this.initialized = false;
|
|
1654
|
-
|
|
1699
|
+
/** SDK 是否已就绪(配置完整,可以上报数据) */
|
|
1700
|
+
this.ready = false;
|
|
1701
|
+
/** 是否正在加载远程配置 */
|
|
1702
|
+
this.loading = false;
|
|
1703
|
+
/** 监控模块是否已安装 */
|
|
1704
|
+
this.monitorsInstalled = false;
|
|
1655
1705
|
}
|
|
1656
1706
|
/**
|
|
1657
1707
|
* 初始化 SDK
|
|
1658
|
-
*
|
|
1659
|
-
* 无需 await,SDK 内部会自动处理异步逻辑
|
|
1708
|
+
* 支持空配置初始化,后续通过 updateConfig 传入 configUrl 完成配置
|
|
1660
1709
|
*/
|
|
1661
|
-
init(userConfig) {
|
|
1662
|
-
if (this.initialized
|
|
1663
|
-
|
|
1664
|
-
console.warn('[Monitor] SDK already initialized');
|
|
1665
|
-
}
|
|
1710
|
+
init(userConfig = {}) {
|
|
1711
|
+
if (this.initialized) {
|
|
1712
|
+
console.warn('[Monitor] SDK already initialized');
|
|
1666
1713
|
return;
|
|
1667
1714
|
}
|
|
1668
|
-
// 如果配置了 configUrl
|
|
1715
|
+
// 如果配置了 configUrl,异步获取远程配置
|
|
1669
1716
|
if (userConfig.configUrl) {
|
|
1670
|
-
this.
|
|
1717
|
+
this.loading = true;
|
|
1718
|
+
this.initBasic(userConfig);
|
|
1671
1719
|
this.fetchRemoteConfig(userConfig.configUrl)
|
|
1672
1720
|
.then((remoteConfig) => {
|
|
1673
|
-
// 远程配置作为基础,用户本地配置覆盖远程配置
|
|
1674
1721
|
const finalConfig = this.mergeUserConfig(remoteConfig, userConfig);
|
|
1675
1722
|
if (userConfig.debug) {
|
|
1676
1723
|
console.log('[Monitor] Remote config loaded:', remoteConfig);
|
|
1677
1724
|
}
|
|
1678
|
-
this.
|
|
1725
|
+
this.activate(finalConfig);
|
|
1679
1726
|
})
|
|
1680
1727
|
.catch((error) => {
|
|
1681
|
-
this.
|
|
1728
|
+
this.loading = false;
|
|
1682
1729
|
console.error('[Monitor] Failed to fetch remote config:', error);
|
|
1683
1730
|
});
|
|
1684
1731
|
}
|
|
1732
|
+
else if (userConfig.appId && userConfig.dsn) {
|
|
1733
|
+
// 有完整配置,直接激活
|
|
1734
|
+
this.initBasic(userConfig);
|
|
1735
|
+
this.activate(userConfig);
|
|
1736
|
+
}
|
|
1685
1737
|
else {
|
|
1686
|
-
//
|
|
1687
|
-
this.
|
|
1738
|
+
// 空配置或不完整配置,只做基础初始化,等待后续 updateConfig
|
|
1739
|
+
this.initBasic(userConfig);
|
|
1740
|
+
console.log('[Monitor] SDK initialized in pending mode. Call updateConfig({configUrl}) to activate.');
|
|
1688
1741
|
}
|
|
1689
1742
|
}
|
|
1690
1743
|
/**
|
|
1691
|
-
*
|
|
1744
|
+
* 基础初始化(安装监控模块,但不开始上报)
|
|
1692
1745
|
*/
|
|
1693
|
-
|
|
1694
|
-
// 初始化配置
|
|
1695
|
-
config.init({
|
|
1696
|
-
...finalConfig,
|
|
1697
|
-
version: finalConfig.version || SDK_VERSION,
|
|
1698
|
-
}, isRemoteConfig);
|
|
1746
|
+
initBasic(userConfig) {
|
|
1699
1747
|
// 初始化上下文
|
|
1700
|
-
const maxBreadcrumbs =
|
|
1748
|
+
const maxBreadcrumbs = userConfig.behavior?.maxBreadcrumbs || 20;
|
|
1701
1749
|
context.init(maxBreadcrumbs);
|
|
1750
|
+
// 安装监控模块(早期捕获的数据会被缓存)
|
|
1751
|
+
if (!this.monitorsInstalled) {
|
|
1752
|
+
installErrorHandlers();
|
|
1753
|
+
installPerformanceMonitor();
|
|
1754
|
+
installBehaviorMonitor();
|
|
1755
|
+
this.monitorsInstalled = true;
|
|
1756
|
+
}
|
|
1702
1757
|
this.initialized = true;
|
|
1703
|
-
|
|
1758
|
+
if (userConfig.debug) {
|
|
1759
|
+
console.log('[Monitor] SDK basic initialized (monitors installed, waiting for config)');
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
/**
|
|
1763
|
+
* 激活 SDK(配置完整后调用)
|
|
1764
|
+
*/
|
|
1765
|
+
activate(finalConfig) {
|
|
1766
|
+
// 初始化配置管理器
|
|
1767
|
+
config.init({
|
|
1768
|
+
...finalConfig,
|
|
1769
|
+
version: finalConfig.version || SDK_VERSION,
|
|
1770
|
+
}, true);
|
|
1771
|
+
this.ready = true;
|
|
1772
|
+
this.loading = false;
|
|
1773
|
+
// 通知 reporter 可以开始上报(会自动发送缓存的早期数据)
|
|
1774
|
+
reporter.setReady(true);
|
|
1704
1775
|
if (config.get().debug) {
|
|
1705
|
-
console.log('[Monitor] SDK
|
|
1776
|
+
console.log('[Monitor] SDK activated with config:', config.get());
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
/**
|
|
1780
|
+
* 动态更新配置
|
|
1781
|
+
* 如果传入 configUrl,会从远程获取配置并激活 SDK
|
|
1782
|
+
*/
|
|
1783
|
+
updateConfig(partialConfig) {
|
|
1784
|
+
// 如果传入了 configUrl,从远程获取配置
|
|
1785
|
+
if (partialConfig.configUrl) {
|
|
1786
|
+
console.log('[Monitor] Fetching remote config from:', partialConfig.configUrl);
|
|
1787
|
+
this.loading = true;
|
|
1788
|
+
this.fetchRemoteConfig(partialConfig.configUrl)
|
|
1789
|
+
.then((remoteConfig) => {
|
|
1790
|
+
const mergedConfig = this.mergeUserConfig(remoteConfig, partialConfig);
|
|
1791
|
+
// 移除 configUrl
|
|
1792
|
+
delete mergedConfig.configUrl;
|
|
1793
|
+
if (this.ready) {
|
|
1794
|
+
// 已就绪,更新配置
|
|
1795
|
+
config.update(mergedConfig);
|
|
1796
|
+
this.loading = false;
|
|
1797
|
+
if (config.get().debug) {
|
|
1798
|
+
console.log('[Monitor] Config updated from remote:', mergedConfig);
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
else {
|
|
1802
|
+
// 未就绪,激活 SDK
|
|
1803
|
+
this.activate(mergedConfig);
|
|
1804
|
+
}
|
|
1805
|
+
})
|
|
1806
|
+
.catch((error) => {
|
|
1807
|
+
this.loading = false;
|
|
1808
|
+
console.error('[Monitor] Failed to fetch remote config:', error);
|
|
1809
|
+
});
|
|
1810
|
+
}
|
|
1811
|
+
else {
|
|
1812
|
+
// 普通配置更新
|
|
1813
|
+
if (!this.ready) {
|
|
1814
|
+
console.warn('[Monitor] SDK not ready. Please provide configUrl or (appId + dsn) first.');
|
|
1815
|
+
return;
|
|
1816
|
+
}
|
|
1817
|
+
config.update(partialConfig);
|
|
1818
|
+
if (config.get().debug) {
|
|
1819
|
+
console.log('[Monitor] Config updated', partialConfig);
|
|
1820
|
+
}
|
|
1706
1821
|
}
|
|
1707
|
-
// 安装监控模块
|
|
1708
|
-
installErrorHandlers();
|
|
1709
|
-
installPerformanceMonitor();
|
|
1710
|
-
installBehaviorMonitor();
|
|
1711
1822
|
}
|
|
1712
1823
|
/**
|
|
1713
1824
|
* 从远程获取配置
|
|
@@ -1733,7 +1844,7 @@
|
|
|
1733
1844
|
if (Object.prototype.hasOwnProperty.call(local, key)) {
|
|
1734
1845
|
const localValue = local[key];
|
|
1735
1846
|
const remoteValue = remote[key];
|
|
1736
|
-
// 跳过 configUrl
|
|
1847
|
+
// 跳过 configUrl
|
|
1737
1848
|
if (key === 'configUrl')
|
|
1738
1849
|
continue;
|
|
1739
1850
|
if (localValue !== null &&
|
|
@@ -1754,55 +1865,33 @@
|
|
|
1754
1865
|
return result;
|
|
1755
1866
|
}
|
|
1756
1867
|
/**
|
|
1757
|
-
*
|
|
1868
|
+
* 检查 SDK 是否就绪
|
|
1758
1869
|
*/
|
|
1759
|
-
|
|
1760
|
-
this.
|
|
1761
|
-
config.setUser(user);
|
|
1870
|
+
isReady() {
|
|
1871
|
+
return this.ready;
|
|
1762
1872
|
}
|
|
1763
1873
|
/**
|
|
1764
|
-
*
|
|
1765
|
-
* @description 可以在运行时更新 SDK 配置,如 debug、sampling、report 等
|
|
1766
|
-
* 如果传入 configUrl,会从远程获取配置并合并
|
|
1874
|
+
* 设置用户信息
|
|
1767
1875
|
*/
|
|
1768
|
-
|
|
1769
|
-
this.
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
this.fetchRemoteConfig(partialConfig.configUrl)
|
|
1773
|
-
.then((remoteConfig) => {
|
|
1774
|
-
// 远程配置作为基础,传入的其他本地配置覆盖远程配置
|
|
1775
|
-
const mergedConfig = this.mergeUserConfig(remoteConfig, partialConfig);
|
|
1776
|
-
// 移除 configUrl,不需要存到配置里
|
|
1777
|
-
delete mergedConfig.configUrl;
|
|
1778
|
-
config.update(mergedConfig);
|
|
1779
|
-
if (config.get().debug) {
|
|
1780
|
-
console.log('[Monitor] Config updated from remote:', mergedConfig);
|
|
1781
|
-
}
|
|
1782
|
-
})
|
|
1783
|
-
.catch((error) => {
|
|
1784
|
-
console.error('[Monitor] Failed to fetch remote config:', error);
|
|
1785
|
-
});
|
|
1786
|
-
}
|
|
1787
|
-
else {
|
|
1788
|
-
config.update(partialConfig);
|
|
1789
|
-
if (config.get().debug) {
|
|
1790
|
-
console.log('[Monitor] Config updated', partialConfig);
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1876
|
+
setUser(user) {
|
|
1877
|
+
if (!this.ready)
|
|
1878
|
+
return;
|
|
1879
|
+
config.setUser(user);
|
|
1793
1880
|
}
|
|
1794
1881
|
/**
|
|
1795
1882
|
* 获取当前配置
|
|
1796
1883
|
*/
|
|
1797
1884
|
getConfig() {
|
|
1798
|
-
this.
|
|
1885
|
+
if (!this.ready)
|
|
1886
|
+
return null;
|
|
1799
1887
|
return config.get();
|
|
1800
1888
|
}
|
|
1801
1889
|
/**
|
|
1802
1890
|
* 手动上报错误
|
|
1803
1891
|
*/
|
|
1804
1892
|
captureError(error, extra) {
|
|
1805
|
-
this.
|
|
1893
|
+
if (!this.ready)
|
|
1894
|
+
return;
|
|
1806
1895
|
const errorData = {
|
|
1807
1896
|
type: 'js_error',
|
|
1808
1897
|
message: typeof error === 'string' ? error : error.message,
|
|
@@ -1815,7 +1904,8 @@
|
|
|
1815
1904
|
* 手动上报性能数据
|
|
1816
1905
|
*/
|
|
1817
1906
|
capturePerformance(metrics) {
|
|
1818
|
-
this.
|
|
1907
|
+
if (!this.ready)
|
|
1908
|
+
return;
|
|
1819
1909
|
reporter.reportPerformance({
|
|
1820
1910
|
type: 'performance',
|
|
1821
1911
|
metrics,
|
|
@@ -1825,7 +1915,8 @@
|
|
|
1825
1915
|
* 手动上报行为数据
|
|
1826
1916
|
*/
|
|
1827
1917
|
captureBehavior(action, data) {
|
|
1828
|
-
this.
|
|
1918
|
+
if (!this.ready)
|
|
1919
|
+
return;
|
|
1829
1920
|
reporter.reportBehavior({
|
|
1830
1921
|
type: 'behavior',
|
|
1831
1922
|
action,
|
|
@@ -1836,14 +1927,16 @@
|
|
|
1836
1927
|
* 添加面包屑
|
|
1837
1928
|
*/
|
|
1838
1929
|
addBreadcrumb(crumb) {
|
|
1839
|
-
this.
|
|
1930
|
+
if (!this.initialized)
|
|
1931
|
+
return;
|
|
1840
1932
|
context.addBreadcrumb(crumb);
|
|
1841
1933
|
}
|
|
1842
1934
|
/**
|
|
1843
1935
|
* 立即发送缓冲区数据
|
|
1844
1936
|
*/
|
|
1845
1937
|
flush() {
|
|
1846
|
-
this.
|
|
1938
|
+
if (!this.ready)
|
|
1939
|
+
return;
|
|
1847
1940
|
reporter.flush();
|
|
1848
1941
|
}
|
|
1849
1942
|
/**
|
|
@@ -1852,14 +1945,6 @@
|
|
|
1852
1945
|
getVersion() {
|
|
1853
1946
|
return SDK_VERSION;
|
|
1854
1947
|
}
|
|
1855
|
-
/**
|
|
1856
|
-
* 检查是否已初始化
|
|
1857
|
-
*/
|
|
1858
|
-
checkInit() {
|
|
1859
|
-
if (!this.initialized) {
|
|
1860
|
-
throw new Error('[Monitor] SDK not initialized. Please call init() first.');
|
|
1861
|
-
}
|
|
1862
|
-
}
|
|
1863
1948
|
}
|
|
1864
1949
|
// 导出单例
|
|
1865
1950
|
const monitor = new MonitorSDK();
|