sobey-monitor-sdk 1.0.8 → 1.1.0
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/README.md +24 -2
- package/dist/core/config.d.ts +2 -1
- package/dist/index.cjs.js +101 -10
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +26 -4
- package/dist/index.esm.js +101 -10
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +101 -10
- package/dist/index.umd.js.map +1 -1
- package/dist/types/index.d.ts +11 -4
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -45,13 +45,28 @@ class ConfigManager {
|
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
47
|
* 初始化配置
|
|
48
|
+
* @param skipValidation 是否跳过必填校验(用于远程配置已获取 appId/dsn 的场景)
|
|
48
49
|
*/
|
|
49
|
-
init(userConfig) {
|
|
50
|
-
if (!
|
|
51
|
-
|
|
50
|
+
init(userConfig, skipValidation = false) {
|
|
51
|
+
if (!skipValidation) {
|
|
52
|
+
// 如果没有 configUrl,则 appId 和 dsn 是必填的
|
|
53
|
+
if (!userConfig.configUrl) {
|
|
54
|
+
if (!userConfig.appId) {
|
|
55
|
+
throw new Error('[Monitor] appId is required when configUrl is not provided');
|
|
56
|
+
}
|
|
57
|
+
if (!userConfig.dsn) {
|
|
58
|
+
throw new Error('[Monitor] dsn is required when configUrl is not provided');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
52
61
|
}
|
|
53
|
-
|
|
54
|
-
|
|
62
|
+
else {
|
|
63
|
+
// 远程配置模式下,校验合并后的配置
|
|
64
|
+
if (!userConfig.appId) {
|
|
65
|
+
throw new Error('[Monitor] appId is required (not found in remote config)');
|
|
66
|
+
}
|
|
67
|
+
if (!userConfig.dsn) {
|
|
68
|
+
throw new Error('[Monitor] dsn is required (not found in remote config)');
|
|
69
|
+
}
|
|
55
70
|
}
|
|
56
71
|
this.config = this.mergeConfig(DEFAULT_CONFIG, userConfig);
|
|
57
72
|
}
|
|
@@ -1628,24 +1643,56 @@ const SDK_VERSION = '1.0.0';
|
|
|
1628
1643
|
class MonitorSDK {
|
|
1629
1644
|
constructor() {
|
|
1630
1645
|
this.initialized = false;
|
|
1646
|
+
this.initializing = false;
|
|
1631
1647
|
}
|
|
1632
1648
|
/**
|
|
1633
1649
|
* 初始化 SDK
|
|
1650
|
+
* 如果配置了 configUrl,将先从远程获取配置(仅获取一次)
|
|
1651
|
+
* 无需 await,SDK 内部会自动处理异步逻辑
|
|
1634
1652
|
*/
|
|
1635
1653
|
init(userConfig) {
|
|
1636
|
-
if (this.initialized) {
|
|
1637
|
-
|
|
1654
|
+
if (this.initialized || this.initializing) {
|
|
1655
|
+
if (this.initialized) {
|
|
1656
|
+
console.warn('[Monitor] SDK already initialized');
|
|
1657
|
+
}
|
|
1638
1658
|
return;
|
|
1639
1659
|
}
|
|
1660
|
+
// 如果配置了 configUrl,异步获取远程配置后再初始化
|
|
1661
|
+
if (userConfig.configUrl) {
|
|
1662
|
+
this.initializing = true;
|
|
1663
|
+
this.fetchRemoteConfig(userConfig.configUrl)
|
|
1664
|
+
.then((remoteConfig) => {
|
|
1665
|
+
// 远程配置作为基础,用户本地配置覆盖远程配置
|
|
1666
|
+
const finalConfig = this.mergeUserConfig(remoteConfig, userConfig);
|
|
1667
|
+
if (userConfig.debug) {
|
|
1668
|
+
console.log('[Monitor] Remote config loaded:', remoteConfig);
|
|
1669
|
+
}
|
|
1670
|
+
this.doInit(finalConfig, true);
|
|
1671
|
+
})
|
|
1672
|
+
.catch((error) => {
|
|
1673
|
+
this.initializing = false;
|
|
1674
|
+
console.error('[Monitor] Failed to fetch remote config:', error);
|
|
1675
|
+
});
|
|
1676
|
+
}
|
|
1677
|
+
else {
|
|
1678
|
+
// 没有 configUrl,直接同步初始化
|
|
1679
|
+
this.doInit(userConfig, false);
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
/**
|
|
1683
|
+
* 执行实际的初始化逻辑
|
|
1684
|
+
*/
|
|
1685
|
+
doInit(finalConfig, isRemoteConfig) {
|
|
1640
1686
|
// 初始化配置
|
|
1641
1687
|
config.init({
|
|
1642
|
-
...
|
|
1643
|
-
version:
|
|
1644
|
-
});
|
|
1688
|
+
...finalConfig,
|
|
1689
|
+
version: finalConfig.version || SDK_VERSION,
|
|
1690
|
+
}, isRemoteConfig);
|
|
1645
1691
|
// 初始化上下文
|
|
1646
1692
|
const maxBreadcrumbs = config.get().behavior?.maxBreadcrumbs || 20;
|
|
1647
1693
|
context.init(maxBreadcrumbs);
|
|
1648
1694
|
this.initialized = true;
|
|
1695
|
+
this.initializing = false;
|
|
1649
1696
|
if (config.get().debug) {
|
|
1650
1697
|
console.log('[Monitor] SDK initialized', config.get());
|
|
1651
1698
|
}
|
|
@@ -1654,6 +1701,50 @@ class MonitorSDK {
|
|
|
1654
1701
|
installPerformanceMonitor();
|
|
1655
1702
|
installBehaviorMonitor();
|
|
1656
1703
|
}
|
|
1704
|
+
/**
|
|
1705
|
+
* 从远程获取配置
|
|
1706
|
+
*/
|
|
1707
|
+
async fetchRemoteConfig(configUrl) {
|
|
1708
|
+
const response = await fetch(configUrl, {
|
|
1709
|
+
method: 'GET',
|
|
1710
|
+
headers: {
|
|
1711
|
+
'Content-Type': 'application/json',
|
|
1712
|
+
},
|
|
1713
|
+
});
|
|
1714
|
+
if (!response.ok) {
|
|
1715
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
1716
|
+
}
|
|
1717
|
+
return response.json();
|
|
1718
|
+
}
|
|
1719
|
+
/**
|
|
1720
|
+
* 合并配置:远程配置为基础,用户本地配置优先
|
|
1721
|
+
*/
|
|
1722
|
+
mergeUserConfig(remote, local) {
|
|
1723
|
+
const result = { ...remote };
|
|
1724
|
+
for (const key in local) {
|
|
1725
|
+
if (Object.prototype.hasOwnProperty.call(local, key)) {
|
|
1726
|
+
const localValue = local[key];
|
|
1727
|
+
const remoteValue = remote[key];
|
|
1728
|
+
// 跳过 configUrl,不需要传递给最终配置
|
|
1729
|
+
if (key === 'configUrl')
|
|
1730
|
+
continue;
|
|
1731
|
+
if (localValue !== null &&
|
|
1732
|
+
localValue !== undefined &&
|
|
1733
|
+
typeof localValue === 'object' &&
|
|
1734
|
+
!Array.isArray(localValue) &&
|
|
1735
|
+
remoteValue !== null &&
|
|
1736
|
+
remoteValue !== undefined &&
|
|
1737
|
+
typeof remoteValue === 'object' &&
|
|
1738
|
+
!Array.isArray(remoteValue)) {
|
|
1739
|
+
result[key] = { ...remoteValue, ...localValue };
|
|
1740
|
+
}
|
|
1741
|
+
else if (localValue !== undefined) {
|
|
1742
|
+
result[key] = localValue;
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
return result;
|
|
1747
|
+
}
|
|
1657
1748
|
/**
|
|
1658
1749
|
* 设置用户信息
|
|
1659
1750
|
*/
|