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/README.md
CHANGED
|
@@ -17,6 +17,27 @@ npm install sobey-monitor-sdk --save
|
|
|
17
17
|
|
|
18
18
|
## 快速开始
|
|
19
19
|
|
|
20
|
+
### 方式一:使用远程配置(推荐)
|
|
21
|
+
|
|
22
|
+
通过 `configUrl` 从服务端获取配置,无需手动维护 `appId` 和 `dsn`:
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
import { monitor } from 'sobey-monitor-sdk';
|
|
26
|
+
|
|
27
|
+
// 只需提供 configUrl,其他配置从远程获取
|
|
28
|
+
monitor.init({
|
|
29
|
+
configUrl: '/monitor/api/config/your-app-id'
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// 也可以覆盖部分远程配置
|
|
33
|
+
monitor.init({
|
|
34
|
+
configUrl: '/monitor/api/config/your-app-id',
|
|
35
|
+
debug: true // 本地配置优先级高于远程配置
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 方式二:传统配置
|
|
40
|
+
|
|
20
41
|
```javascript
|
|
21
42
|
import { monitor } from 'sobey-monitor-sdk';
|
|
22
43
|
|
|
@@ -113,8 +134,9 @@ ReactDOM.render(
|
|
|
113
134
|
|
|
114
135
|
| 配置项 | 类型 | 默认值 | 说明 |
|
|
115
136
|
|--------|------|--------|------|
|
|
116
|
-
| `
|
|
117
|
-
| `
|
|
137
|
+
| `configUrl` | string | - | 远程配置接口地址,填写后可从远程获取 `appId`、`dsn` 等配置(仅初始化时获取一次) |
|
|
138
|
+
| `appId` | string | 必填* | 应用唯一标识(使用 `configUrl` 时可不填) |
|
|
139
|
+
| `dsn` | string | 必填* | 数据上报地址(使用 `configUrl` 时可不填) |
|
|
118
140
|
| `enabled` | boolean | true | **全局开关**,设为 false 则完全禁用所有监控上报 |
|
|
119
141
|
| `debug` | boolean | false | 调试模式,开启后会在控制台输出日志 |
|
|
120
142
|
| `sampling.error` | number | 1 | 错误采样率 (0-1) |
|
package/dist/core/config.d.ts
CHANGED
|
@@ -9,8 +9,9 @@ declare class ConfigManager {
|
|
|
9
9
|
private config;
|
|
10
10
|
/**
|
|
11
11
|
* 初始化配置
|
|
12
|
+
* @param skipValidation 是否跳过必填校验(用于远程配置已获取 appId/dsn 的场景)
|
|
12
13
|
*/
|
|
13
|
-
init(userConfig: MonitorConfig): void;
|
|
14
|
+
init(userConfig: MonitorConfig, skipValidation?: boolean): void;
|
|
14
15
|
/**
|
|
15
16
|
* 获取配置
|
|
16
17
|
*/
|
package/dist/index.cjs.js
CHANGED
|
@@ -49,13 +49,28 @@ class ConfigManager {
|
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
51
51
|
* 初始化配置
|
|
52
|
+
* @param skipValidation 是否跳过必填校验(用于远程配置已获取 appId/dsn 的场景)
|
|
52
53
|
*/
|
|
53
|
-
init(userConfig) {
|
|
54
|
-
if (!
|
|
55
|
-
|
|
54
|
+
init(userConfig, skipValidation = false) {
|
|
55
|
+
if (!skipValidation) {
|
|
56
|
+
// 如果没有 configUrl,则 appId 和 dsn 是必填的
|
|
57
|
+
if (!userConfig.configUrl) {
|
|
58
|
+
if (!userConfig.appId) {
|
|
59
|
+
throw new Error('[Monitor] appId is required when configUrl is not provided');
|
|
60
|
+
}
|
|
61
|
+
if (!userConfig.dsn) {
|
|
62
|
+
throw new Error('[Monitor] dsn is required when configUrl is not provided');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
56
65
|
}
|
|
57
|
-
|
|
58
|
-
|
|
66
|
+
else {
|
|
67
|
+
// 远程配置模式下,校验合并后的配置
|
|
68
|
+
if (!userConfig.appId) {
|
|
69
|
+
throw new Error('[Monitor] appId is required (not found in remote config)');
|
|
70
|
+
}
|
|
71
|
+
if (!userConfig.dsn) {
|
|
72
|
+
throw new Error('[Monitor] dsn is required (not found in remote config)');
|
|
73
|
+
}
|
|
59
74
|
}
|
|
60
75
|
this.config = this.mergeConfig(DEFAULT_CONFIG, userConfig);
|
|
61
76
|
}
|
|
@@ -1632,24 +1647,56 @@ const SDK_VERSION = '1.0.0';
|
|
|
1632
1647
|
class MonitorSDK {
|
|
1633
1648
|
constructor() {
|
|
1634
1649
|
this.initialized = false;
|
|
1650
|
+
this.initializing = false;
|
|
1635
1651
|
}
|
|
1636
1652
|
/**
|
|
1637
1653
|
* 初始化 SDK
|
|
1654
|
+
* 如果配置了 configUrl,将先从远程获取配置(仅获取一次)
|
|
1655
|
+
* 无需 await,SDK 内部会自动处理异步逻辑
|
|
1638
1656
|
*/
|
|
1639
1657
|
init(userConfig) {
|
|
1640
|
-
if (this.initialized) {
|
|
1641
|
-
|
|
1658
|
+
if (this.initialized || this.initializing) {
|
|
1659
|
+
if (this.initialized) {
|
|
1660
|
+
console.warn('[Monitor] SDK already initialized');
|
|
1661
|
+
}
|
|
1642
1662
|
return;
|
|
1643
1663
|
}
|
|
1664
|
+
// 如果配置了 configUrl,异步获取远程配置后再初始化
|
|
1665
|
+
if (userConfig.configUrl) {
|
|
1666
|
+
this.initializing = true;
|
|
1667
|
+
this.fetchRemoteConfig(userConfig.configUrl)
|
|
1668
|
+
.then((remoteConfig) => {
|
|
1669
|
+
// 远程配置作为基础,用户本地配置覆盖远程配置
|
|
1670
|
+
const finalConfig = this.mergeUserConfig(remoteConfig, userConfig);
|
|
1671
|
+
if (userConfig.debug) {
|
|
1672
|
+
console.log('[Monitor] Remote config loaded:', remoteConfig);
|
|
1673
|
+
}
|
|
1674
|
+
this.doInit(finalConfig, true);
|
|
1675
|
+
})
|
|
1676
|
+
.catch((error) => {
|
|
1677
|
+
this.initializing = false;
|
|
1678
|
+
console.error('[Monitor] Failed to fetch remote config:', error);
|
|
1679
|
+
});
|
|
1680
|
+
}
|
|
1681
|
+
else {
|
|
1682
|
+
// 没有 configUrl,直接同步初始化
|
|
1683
|
+
this.doInit(userConfig, false);
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
/**
|
|
1687
|
+
* 执行实际的初始化逻辑
|
|
1688
|
+
*/
|
|
1689
|
+
doInit(finalConfig, isRemoteConfig) {
|
|
1644
1690
|
// 初始化配置
|
|
1645
1691
|
config.init({
|
|
1646
|
-
...
|
|
1647
|
-
version:
|
|
1648
|
-
});
|
|
1692
|
+
...finalConfig,
|
|
1693
|
+
version: finalConfig.version || SDK_VERSION,
|
|
1694
|
+
}, isRemoteConfig);
|
|
1649
1695
|
// 初始化上下文
|
|
1650
1696
|
const maxBreadcrumbs = config.get().behavior?.maxBreadcrumbs || 20;
|
|
1651
1697
|
context.init(maxBreadcrumbs);
|
|
1652
1698
|
this.initialized = true;
|
|
1699
|
+
this.initializing = false;
|
|
1653
1700
|
if (config.get().debug) {
|
|
1654
1701
|
console.log('[Monitor] SDK initialized', config.get());
|
|
1655
1702
|
}
|
|
@@ -1658,6 +1705,50 @@ class MonitorSDK {
|
|
|
1658
1705
|
installPerformanceMonitor();
|
|
1659
1706
|
installBehaviorMonitor();
|
|
1660
1707
|
}
|
|
1708
|
+
/**
|
|
1709
|
+
* 从远程获取配置
|
|
1710
|
+
*/
|
|
1711
|
+
async fetchRemoteConfig(configUrl) {
|
|
1712
|
+
const response = await fetch(configUrl, {
|
|
1713
|
+
method: 'GET',
|
|
1714
|
+
headers: {
|
|
1715
|
+
'Content-Type': 'application/json',
|
|
1716
|
+
},
|
|
1717
|
+
});
|
|
1718
|
+
if (!response.ok) {
|
|
1719
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
1720
|
+
}
|
|
1721
|
+
return response.json();
|
|
1722
|
+
}
|
|
1723
|
+
/**
|
|
1724
|
+
* 合并配置:远程配置为基础,用户本地配置优先
|
|
1725
|
+
*/
|
|
1726
|
+
mergeUserConfig(remote, local) {
|
|
1727
|
+
const result = { ...remote };
|
|
1728
|
+
for (const key in local) {
|
|
1729
|
+
if (Object.prototype.hasOwnProperty.call(local, key)) {
|
|
1730
|
+
const localValue = local[key];
|
|
1731
|
+
const remoteValue = remote[key];
|
|
1732
|
+
// 跳过 configUrl,不需要传递给最终配置
|
|
1733
|
+
if (key === 'configUrl')
|
|
1734
|
+
continue;
|
|
1735
|
+
if (localValue !== null &&
|
|
1736
|
+
localValue !== undefined &&
|
|
1737
|
+
typeof localValue === 'object' &&
|
|
1738
|
+
!Array.isArray(localValue) &&
|
|
1739
|
+
remoteValue !== null &&
|
|
1740
|
+
remoteValue !== undefined &&
|
|
1741
|
+
typeof remoteValue === 'object' &&
|
|
1742
|
+
!Array.isArray(remoteValue)) {
|
|
1743
|
+
result[key] = { ...remoteValue, ...localValue };
|
|
1744
|
+
}
|
|
1745
|
+
else if (localValue !== undefined) {
|
|
1746
|
+
result[key] = localValue;
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
return result;
|
|
1751
|
+
}
|
|
1661
1752
|
/**
|
|
1662
1753
|
* 设置用户信息
|
|
1663
1754
|
*/
|