@arms/rum-core 0.1.4 → 0.1.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.
Files changed (44) hide show
  1. package/README.md +26 -2
  2. package/es/index.d.ts +1 -0
  3. package/es/index.js +1 -0
  4. package/es/model/client.d.ts +2 -1
  5. package/es/model/client.js +27 -1
  6. package/es/model/configManager.js +2 -2
  7. package/es/model/reporter.js +4 -1
  8. package/es/monitor/index.d.ts +6 -0
  9. package/es/monitor/index.js +3 -0
  10. package/es/monitor/logger.d.ts +34 -0
  11. package/es/monitor/logger.js +112 -0
  12. package/es/monitor/telemetry.d.ts +42 -0
  13. package/es/monitor/telemetry.js +210 -0
  14. package/es/monitor/types.d.ts +46 -0
  15. package/es/monitor/types.js +1 -0
  16. package/es/types/client.d.ts +22 -1
  17. package/es/types/rum-event.d.ts +242 -54
  18. package/es/types/rum-event.js +67 -1
  19. package/es/utils/base.js +2 -2
  20. package/es/utils/events.js +2 -1
  21. package/es/utils/protobuf.d.ts +24 -0
  22. package/es/utils/protobuf.js +123 -0
  23. package/lib/index.d.ts +1 -0
  24. package/lib/index.js +7 -0
  25. package/lib/model/client.d.ts +2 -1
  26. package/lib/model/client.js +27 -1
  27. package/lib/model/configManager.js +2 -2
  28. package/lib/model/reporter.js +4 -1
  29. package/lib/monitor/index.d.ts +6 -0
  30. package/lib/monitor/index.js +12 -0
  31. package/lib/monitor/logger.d.ts +34 -0
  32. package/lib/monitor/logger.js +117 -0
  33. package/lib/monitor/telemetry.d.ts +42 -0
  34. package/lib/monitor/telemetry.js +214 -0
  35. package/lib/monitor/types.d.ts +46 -0
  36. package/lib/monitor/types.js +3 -0
  37. package/lib/types/client.d.ts +22 -1
  38. package/lib/types/rum-event.d.ts +242 -54
  39. package/lib/types/rum-event.js +50 -1
  40. package/lib/utils/base.js +2 -2
  41. package/lib/utils/events.js +2 -1
  42. package/lib/utils/protobuf.d.ts +24 -0
  43. package/lib/utils/protobuf.js +127 -0
  44. package/package.json +10 -1
package/README.md CHANGED
@@ -1,3 +1,27 @@
1
- ## @arms/rum-core
1
+ # @arms/rum-core
2
2
 
3
- Core SDK 上报提供核心流程角色抽象
3
+ ARMS RUM SDK 多端方案的核心抽象层,为各平台 shell(`browser` / `uniapp` / `miniapp` / `minigame` / `electron` / `reactnative` 等)提供统一的角色模型、事件协议与跨运行时工具。
4
+
5
+ ## 角色模型
6
+
7
+ - **Client**:装载并编排 `Collector` / `Processor` / `Reporter`,串联事件管线。
8
+ - **Context**:运行时上下文,承载 `config` / `session` / `views` / `emitter`。
9
+ - **Shell**:对外 API 入口,提供 `sendCustom` / `sendView` / `sendException` / `sendResource`。
10
+ - **ConfigManager**:本地+远端配置编排,支持 `launch-first` / `remote-first` 两种模式。
11
+ - **Collector / Processor / Reporter**:平台扩展点,分别负责数据采集、加工、上报。
12
+
13
+ 事件流:`Collector → sendEvent → Processor 链 → Reporter(队列 / 合并 / 重试) → Transport`。
14
+
15
+ ## 支持运行时
16
+
17
+ 浏览器(ES2017+,不含 IE)、Node.js 16+、Deno、Bun、Electron、React Native 0.68+、微信/支付宝/字节小程序(基础库 2.10+ 同等能力)、uni-app 3.x。
18
+
19
+ `core` 自身不依赖任何浏览器或 Node 专属 API(`window` / `document` / `fetch` / `localStorage` / `XMLHttpRequest` 等);host API 通过 `env/` 抽象由 shell 注入。
20
+
21
+
22
+ ## 开发
23
+
24
+ ```bash
25
+ npm run build # 产出 lib/ (CJS) + es/ (ESM)
26
+ npm test # 单元测试(先 build 后 test,重构后改为直接跑 ts 源码)
27
+ ```
package/es/index.d.ts CHANGED
@@ -19,4 +19,5 @@ export * from './utils/trace';
19
19
  export * from './utils/verify';
20
20
  export * from './utils/url';
21
21
  export * from './utils/events';
22
+ export * from './monitor';
22
23
  export { Client, Context, Reporter, Shell };
package/es/index.js CHANGED
@@ -19,4 +19,5 @@ export * from './utils/trace';
19
19
  export * from './utils/verify';
20
20
  export * from './utils/url';
21
21
  export * from './utils/events';
22
+ export * from './monitor';
22
23
  export { Client, Context, Reporter, Shell };
@@ -4,13 +4,14 @@ import { RumEvent } from '../types/rum-event';
4
4
  import { IProcessor } from '../types/processor';
5
5
  import { ICollector } from '../types/collector';
6
6
  import { IReporter } from '../types/reporter';
7
+ import { IMonitorReporter } from '../monitor/types';
7
8
  declare class Client implements IClient {
8
9
  private emitter;
9
10
  private collectors;
10
11
  private processors;
11
12
  private reporter;
12
13
  private ctx;
13
- init(config: IConfiguration, rumSession?: IRumSession, configManager?: IConfigManager): void;
14
+ init(config: IConfiguration, rumSession?: IRumSession, configManager?: IConfigManager, monitorReporter?: IMonitorReporter): void;
14
15
  sendEvent: (payload: RumEvent) => void;
15
16
  setContext(ctx: IContext): void;
16
17
  getContext(): IContext;
@@ -3,6 +3,7 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
3
3
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
4
4
  import { EventType } from '../types/client';
5
5
  import { EventEmitter } from '../utils/events';
6
+ import { Telemetry } from '../monitor/telemetry';
6
7
  import Context from './context';
7
8
  import { isFunction } from "../utils/is";
8
9
  var Client = /*#__PURE__*/function () {
@@ -18,9 +19,34 @@ var Client = /*#__PURE__*/function () {
18
19
  };
19
20
  }
20
21
  var _proto = Client.prototype;
21
- _proto.init = function init(config, rumSession, configManager) {
22
+ _proto.init = function init(config, rumSession, configManager, monitorReporter) {
22
23
  var _this2 = this;
23
24
  this.ctx = new Context(config, rumSession, configManager);
25
+
26
+ // Telemetry 初始化 —— 统一在 Core 中完成,各平台仅需传入 reporter
27
+ if (monitorReporter) {
28
+ var telemetryConfig = {
29
+ appType: (rumSession === null || rumSession === void 0 ? void 0 : rumSession.appType) || '',
30
+ sdkVersion: (rumSession === null || rumSession === void 0 ? void 0 : rumSession.sdkVersion) || '',
31
+ endpoint: config.endpoint,
32
+ getSessionId: rumSession ? function () {
33
+ return rumSession.getSessionId();
34
+ } : undefined,
35
+ getSessionSampled: rumSession ? function () {
36
+ return rumSession.getSampled();
37
+ } : undefined,
38
+ getViewId: function getViewId() {
39
+ var _this2$ctx;
40
+ var views = (_this2$ctx = _this2.ctx) === null || _this2$ctx === void 0 ? void 0 : _this2$ctx.getViews();
41
+ return views && views.length ? views[views.length - 1].id : undefined;
42
+ },
43
+ selfMonitor: config.selfMonitor
44
+ };
45
+ if (config.pid) {
46
+ telemetryConfig['app.id'] = config.pid;
47
+ }
48
+ Telemetry.init(telemetryConfig, monitorReporter);
49
+ }
24
50
  var ctx = this.ctx,
25
51
  collectors = this.collectors,
26
52
  processors = this.processors,
@@ -101,7 +101,7 @@ export var ConfigManager = /*#__PURE__*/function () {
101
101
  * 获取配置
102
102
  * @returns 配置数据
103
103
  */
104
- ;
104
+ ;
105
105
  _proto.getConfig = function getConfig() {
106
106
  if (!this.currentConfig) {
107
107
  throw new Error('Config not initialized');
@@ -143,7 +143,7 @@ export var ConfigManager = /*#__PURE__*/function () {
143
143
  * @param cachedData 缓存数据
144
144
  * @param cacheTimeout 缓存超时时间
145
145
  */
146
- ;
146
+ ;
147
147
  _proto.isCacheValid = function isCacheValid(cachedData, cacheTimeout) {
148
148
  if (!cachedData || !cachedData.timestamp) {
149
149
  return false;
@@ -1,6 +1,7 @@
1
1
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
2
  import _extends from "@babel/runtime/helpers/extends";
3
3
  import _regeneratorRuntime from "@babel/runtime/regenerator";
4
+ import { logger } from '../monitor/logger';
4
5
  import { RumEventType } from '../types/rum-event';
5
6
  import { getErrorID } from '../utils/exception';
6
7
  import { isNumber, isObject, isString } from "../utils/is";
@@ -217,6 +218,8 @@ var Reporter = /*#__PURE__*/function () {
217
218
  setTimeout(function () {
218
219
  return _this2.tryRequest(bundle, retry + 1);
219
220
  }, retryDelay);
221
+ } else {
222
+ logger.error('reporter', "Request failed after " + (retry + 1) + " attempts", _t);
220
223
  }
221
224
  case 4:
222
225
  case "end":
@@ -232,7 +235,7 @@ var Reporter = /*#__PURE__*/function () {
232
235
  /**
233
236
  * 接口请求由各平台 sdk reporter 实现
234
237
  */
235
- ;
238
+ ;
236
239
  /**
237
240
  * 初始化时
238
241
  */
@@ -0,0 +1,6 @@
1
+ export { logger, callMonitored } from './logger';
2
+ export type { ILogger } from './logger';
3
+ export { Telemetry, convertBundlesToLogGroup } from './telemetry';
4
+ export type { TelemetryContext } from './telemetry';
5
+ export type { MonitorLogEvent, MonitorLogLevel, MonitorEventBundle, IMonitorReporter, ISelfMonitorConfig } from './types';
6
+ export { encodeLogGroup } from '../utils/protobuf';
@@ -0,0 +1,3 @@
1
+ export { logger, callMonitored } from './logger';
2
+ export { Telemetry, convertBundlesToLogGroup } from './telemetry';
3
+ export { encodeLogGroup } from '../utils/protobuf';
@@ -0,0 +1,34 @@
1
+ import { MonitorLogEvent, MonitorLogLevel } from './types';
2
+ type LogArgs = [module: string, message: string, error?: unknown, context?: Record<string, unknown>];
3
+ export interface ILogger {
4
+ debug(...args: LogArgs): void;
5
+ info(...args: LogArgs): void;
6
+ warn(...args: LogArgs): void;
7
+ error(...args: LogArgs): void;
8
+ crash(...args: LogArgs): void;
9
+ }
10
+ declare class Logger implements ILogger {
11
+ private console;
12
+ private reportLevels;
13
+ private onError?;
14
+ setConsole(enabled: boolean): void;
15
+ setReportLevels(levels: MonitorLogLevel[]): void;
16
+ setOnError(handler?: (event: MonitorLogEvent) => void): void;
17
+ debug(...args: LogArgs): void;
18
+ info(...args: LogArgs): void;
19
+ warn(...args: LogArgs): void;
20
+ error(...args: LogArgs): void;
21
+ crash(...args: LogArgs): void;
22
+ private log;
23
+ /**
24
+ * 函数包装器 — 用于箭头函数属性
25
+ * 用法: private handler = logger.wrap((e) => {...}, 'module', 'message?')
26
+ */
27
+ wrap<T extends (...args: any[]) => unknown>(fn: T, module: string, message?: string): T;
28
+ }
29
+ export declare const logger: Logger;
30
+ /**
31
+ * 执行被监控函数,异常时自动上报
32
+ */
33
+ export declare function callMonitored<T extends (...args: any[]) => unknown>(fn: T, context?: any, args?: any, module?: string, message?: string): ReturnType<T> | undefined;
34
+ export {};
@@ -0,0 +1,112 @@
1
+ var DEFAULT_REPORT_LEVELS = ['debug', 'error', 'crash'];
2
+ var Logger = /*#__PURE__*/function () {
3
+ function Logger() {
4
+ this.console = false;
5
+ this.reportLevels = DEFAULT_REPORT_LEVELS;
6
+ this.onError = void 0;
7
+ }
8
+ var _proto = Logger.prototype;
9
+ _proto.setConsole = function setConsole(enabled) {
10
+ this.console = enabled;
11
+ };
12
+ _proto.setReportLevels = function setReportLevels(levels) {
13
+ this.reportLevels = levels;
14
+ };
15
+ _proto.setOnError = function setOnError(handler) {
16
+ this.onError = handler;
17
+ };
18
+ _proto.debug = function debug() {
19
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
20
+ args[_key] = arguments[_key];
21
+ }
22
+ this.log('debug', args);
23
+ };
24
+ _proto.info = function info() {
25
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
26
+ args[_key2] = arguments[_key2];
27
+ }
28
+ this.log('info', args);
29
+ };
30
+ _proto.warn = function warn() {
31
+ for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
32
+ args[_key3] = arguments[_key3];
33
+ }
34
+ this.log('warn', args);
35
+ };
36
+ _proto.error = function error() {
37
+ for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
38
+ args[_key4] = arguments[_key4];
39
+ }
40
+ this.log('error', args);
41
+ };
42
+ _proto.crash = function crash() {
43
+ for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
44
+ args[_key5] = arguments[_key5];
45
+ }
46
+ this.log('crash', args);
47
+ };
48
+ _proto.log = function log(level, _ref) {
49
+ var _this$onError;
50
+ var module = _ref[0],
51
+ message = _ref[1],
52
+ error = _ref[2],
53
+ context = _ref[3];
54
+ if (this.console) {
55
+ var consoleFn = level === 'crash' ? 'error' : level === 'debug' ? 'log' : level;
56
+ console[consoleFn]("[RUM-SDK][" + module + "]", message, error || '');
57
+ }
58
+
59
+ // 仅上报配置中指定的级别
60
+ if (!this.reportLevels.includes(level)) return;
61
+ var stack;
62
+ if (error instanceof Error) {
63
+ stack = error.stack;
64
+ } else if (error && typeof error === 'object' && 'stack' in error) {
65
+ stack = String(error.stack);
66
+ }
67
+
68
+ // 截断过长的 stack(与 content 同等 12KB 上限)
69
+ if (stack && stack.length > 12288) {
70
+ stack = stack.slice(0, 12288);
71
+ }
72
+ (_this$onError = this.onError) === null || _this$onError === void 0 ? void 0 : _this$onError.call(this, Object.assign({
73
+ level: level,
74
+ content: message,
75
+ type: module,
76
+ stack: stack
77
+ }, context));
78
+ }
79
+
80
+ /**
81
+ * 函数包装器 — 用于箭头函数属性
82
+ * 用法: private handler = logger.wrap((e) => {...}, 'module', 'message?')
83
+ */;
84
+ _proto.wrap = function wrap(fn, module, message) {
85
+ return function () {
86
+ for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
87
+ args[_key6] = arguments[_key6];
88
+ }
89
+ return callMonitored(fn, this, args, module, message);
90
+ };
91
+ };
92
+ return Logger;
93
+ }();
94
+ export var logger = new Logger();
95
+
96
+ /**
97
+ * 执行被监控函数,异常时自动上报
98
+ */
99
+ export function callMonitored(fn, context, args, module, message) {
100
+ try {
101
+ var result = fn.apply(context, args);
102
+ // 检测 async 函数返回的 Promise,附加 .catch 处理
103
+ if (result && typeof result["catch"] === 'function') {
104
+ result["catch"](function (e) {
105
+ logger.error(module || 'unknown', message || (e instanceof Error ? e.message : String(e)), e);
106
+ });
107
+ }
108
+ return result;
109
+ } catch (e) {
110
+ logger.error(module || 'unknown', message || (e instanceof Error ? e.message : String(e)), e);
111
+ }
112
+ }
@@ -0,0 +1,42 @@
1
+ import { MonitorLogEvent, MonitorEventBundle, IMonitorReporter, ISelfMonitorConfig } from './types';
2
+ export interface TelemetryContext {
3
+ appType: string;
4
+ sdkVersion: string;
5
+ endpoint: string;
6
+ getSessionId?: () => string | undefined;
7
+ getViewId?: () => string | undefined;
8
+ getSessionSampled?: () => boolean;
9
+ /** 自监控配置 */
10
+ selfMonitor?: ISelfMonitorConfig | boolean;
11
+ [key: string]: unknown;
12
+ }
13
+ export declare class Telemetry {
14
+ private static instance;
15
+ static init(context: TelemetryContext, reporter?: IMonitorReporter): Telemetry;
16
+ static get(): Telemetry | undefined;
17
+ private buffer;
18
+ private queue;
19
+ private sentEvents;
20
+ private started;
21
+ private enabled;
22
+ private sampled;
23
+ private timer;
24
+ private reporter?;
25
+ private context;
26
+ private isReporting;
27
+ private endpointParams;
28
+ constructor(context: TelemetryContext, reporter?: IMonitorReporter);
29
+ private start;
30
+ addEvent(event: MonitorLogEvent): void;
31
+ flush(): void;
32
+ setReporter(reporter: IMonitorReporter): void;
33
+ private flushBuffer;
34
+ private processSnapshot;
35
+ private shouldSend;
36
+ private buildBundle;
37
+ private sendBatch;
38
+ }
39
+ /**
40
+ * 将 MonitorEventBundle 数组转换并编码为 SLS LogGroup Protobuf 格式
41
+ */
42
+ export declare function convertBundlesToLogGroup(data: MonitorEventBundle[]): Uint8Array;
@@ -0,0 +1,210 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ var _Telemetry;
3
+ import { logger } from './logger';
4
+ import { getUrlParams } from '../utils/url';
5
+ import { encodeLogGroup } from '../utils/protobuf';
6
+ import { performDraw } from '../utils/number';
7
+ var MAX_EVENTS_PER_PAGE = 15;
8
+ var BUFFER_SIZE = 100;
9
+ var LOG_CONTENT_MAX_SIZE = 12288;
10
+ var FLUSH_TIME = 5000;
11
+ var MAX_BATCH_SIZE = 10;
12
+ var DEFAULT_SAMPLE_RATE = 100;
13
+
14
+ /** 事件快照:在事件产生时就捕获上下文 */
15
+
16
+ export var Telemetry = /*#__PURE__*/function () {
17
+ function Telemetry(context, reporter) {
18
+ this.buffer = [];
19
+ this.queue = [];
20
+ this.sentEvents = new Set();
21
+ this.started = false;
22
+ this.enabled = true;
23
+ this.sampled = void 0;
24
+ this.timer = null;
25
+ this.reporter = void 0;
26
+ this.context = void 0;
27
+ this.isReporting = false;
28
+ this.endpointParams = void 0;
29
+ this.context = context;
30
+ this.reporter = reporter;
31
+ this.endpointParams = getUrlParams(context.endpoint);
32
+
33
+ // 解析自监控配置
34
+ var selfMonitor = context.selfMonitor;
35
+ if (typeof selfMonitor === 'boolean') {
36
+ this.enabled = selfMonitor;
37
+ this.sampled = performDraw(DEFAULT_SAMPLE_RATE);
38
+ } else if (selfMonitor && typeof selfMonitor === 'object') {
39
+ this.enabled = selfMonitor.enable !== false;
40
+ var rate = selfMonitor.sampling;
41
+ this.sampled = performDraw(typeof rate === 'number' && rate >= 0 && rate <= 100 ? rate : DEFAULT_SAMPLE_RATE);
42
+ if (selfMonitor.console) {
43
+ logger.setConsole(true);
44
+ }
45
+ if (selfMonitor.reportLevels) {
46
+ logger.setReportLevels(selfMonitor.reportLevels);
47
+ }
48
+ } else {
49
+ this.enabled = true;
50
+ this.sampled = performDraw(DEFAULT_SAMPLE_RATE);
51
+ }
52
+ }
53
+ Telemetry.init = function init(context, reporter) {
54
+ if (Telemetry.instance) {
55
+ Telemetry.instance.flush();
56
+ }
57
+ Telemetry.instance = new Telemetry(context, reporter);
58
+ Telemetry.instance.start();
59
+ return Telemetry.instance;
60
+ };
61
+ Telemetry.get = function get() {
62
+ return Telemetry.instance;
63
+ };
64
+ var _proto = Telemetry.prototype;
65
+ _proto.start = function start() {
66
+ var _this = this;
67
+ if (this.started) return;
68
+ this.started = true;
69
+ logger.setOnError(function (event) {
70
+ return _this.addEvent(event);
71
+ });
72
+ this.flushBuffer();
73
+ };
74
+ _proto.addEvent = function addEvent(event) {
75
+ var _this$context$getSess, _this$context, _this$context$getView, _this$context2;
76
+ if (!this.enabled || !event) return;
77
+ if (event.content && event.content.length > LOG_CONTENT_MAX_SIZE) {
78
+ event = _extends({}, event, {
79
+ content: event.content.slice(0, LOG_CONTENT_MAX_SIZE)
80
+ });
81
+ }
82
+ if (event.stack && event.stack.length > LOG_CONTENT_MAX_SIZE) {
83
+ event = _extends({}, event, {
84
+ stack: event.stack.slice(0, LOG_CONTENT_MAX_SIZE)
85
+ });
86
+ }
87
+
88
+ // 在事件产生时就捕获快照
89
+ var snapshot = {
90
+ event: event,
91
+ sessionId: (_this$context$getSess = (_this$context = this.context).getSessionId) === null || _this$context$getSess === void 0 ? void 0 : _this$context$getSess.call(_this$context),
92
+ viewId: (_this$context$getView = (_this$context2 = this.context).getViewId) === null || _this$context$getView === void 0 ? void 0 : _this$context$getView.call(_this$context2),
93
+ timestamp: Date.now()
94
+ };
95
+ if (!this.started || !this.reporter) {
96
+ if (this.buffer.length < BUFFER_SIZE) {
97
+ this.buffer.push(snapshot);
98
+ }
99
+ return;
100
+ }
101
+ this.processSnapshot(snapshot);
102
+ };
103
+ _proto.flush = function flush() {
104
+ if (this.timer) {
105
+ clearTimeout(this.timer);
106
+ this.timer = null;
107
+ }
108
+ this.sendBatch();
109
+ };
110
+ _proto.setReporter = function setReporter(reporter) {
111
+ this.reporter = reporter;
112
+ if (this.started) {
113
+ this.flushBuffer();
114
+ }
115
+ };
116
+ _proto.flushBuffer = function flushBuffer() {
117
+ var _this2 = this;
118
+ var buffered = this.buffer.splice(0);
119
+ buffered.forEach(function (snapshot) {
120
+ return _this2.processSnapshot(snapshot);
121
+ });
122
+ };
123
+ _proto.processSnapshot = function processSnapshot(snapshot) {
124
+ var _this3 = this;
125
+ if (!this.shouldSend(snapshot.event)) return;
126
+ var bundle = this.buildBundle(snapshot);
127
+ this.queue.push(bundle);
128
+ if (this.queue.length >= MAX_BATCH_SIZE) {
129
+ this.flush();
130
+ } else if (!this.timer) {
131
+ this.timer = setTimeout(function () {
132
+ return _this3.flush();
133
+ }, FLUSH_TIME);
134
+ }
135
+ };
136
+ _proto.shouldSend = function shouldSend(event) {
137
+ // 先检查 Session 采样,未命中则不上报
138
+ if (this.context.getSessionSampled && !this.context.getSessionSampled()) return false;
139
+ // 再检查自监控自身采样
140
+ if (!this.sampled) return false;
141
+ if (this.sentEvents.size >= MAX_EVENTS_PER_PAGE) return false;
142
+ var key = (event.content || '') + (event.stack || '');
143
+ if (this.sentEvents.has(key)) return false;
144
+ this.sentEvents.add(key);
145
+ return true;
146
+ };
147
+ _proto.buildBundle = function buildBundle(snapshot) {
148
+ var _this$context3 = this.context,
149
+ appType = _this$context3.appType,
150
+ sdkVersion = _this$context3.sdkVersion,
151
+ endpoint = _this$context3.endpoint;
152
+ return _extends({
153
+ 'app.type': appType,
154
+ _v: sdkVersion,
155
+ endpoint: endpoint,
156
+ 'session.id': snapshot.sessionId,
157
+ 'view.id': snapshot.viewId,
158
+ timestamp: snapshot.timestamp,
159
+ event_type: 'log',
160
+ log: snapshot.event
161
+ }, this.endpointParams);
162
+ };
163
+ _proto.sendBatch = function sendBatch() {
164
+ if (this.queue.length === 0 || !this.reporter) return;
165
+ if (this.isReporting) return;
166
+ var batch = this.queue.splice(0);
167
+ this.isReporting = true;
168
+ try {
169
+ this.reporter.send(batch);
170
+ } catch (e) {
171
+ // 不通过 logger(避免反馈循环),直接 console 仅供开发调试
172
+ try {
173
+ console.warn('[RUM-Telemetry] send failed:', e);
174
+ } catch (_) {}
175
+ } finally {
176
+ this.isReporting = false;
177
+ }
178
+ };
179
+ return Telemetry;
180
+ }();
181
+
182
+ /**
183
+ * 将 MonitorEventBundle 数组转换并编码为 SLS LogGroup Protobuf 格式
184
+ */
185
+ _Telemetry = Telemetry;
186
+ Telemetry.instance = void 0;
187
+ export function convertBundlesToLogGroup(data) {
188
+ var logs = data.map(function (bundle) {
189
+ var contents = [];
190
+
191
+ // 遍历 bundle 顶层字段,跳过 timestamp(映射到 time),对象类型整体序列化
192
+ for (var _i = 0, _Object$entries = Object.entries(bundle); _i < _Object$entries.length; _i++) {
193
+ var _Object$entries$_i = _Object$entries[_i],
194
+ _key = _Object$entries$_i[0],
195
+ val = _Object$entries$_i[1];
196
+ if (_key === 'timestamp') continue;
197
+ if (val !== undefined && val !== null) {
198
+ contents.push({
199
+ key: _key,
200
+ value: typeof val === 'object' ? JSON.stringify(val) : String(val)
201
+ });
202
+ }
203
+ }
204
+ return {
205
+ time: Math.floor(bundle.timestamp / 1000),
206
+ contents: contents
207
+ };
208
+ });
209
+ return encodeLogGroup(logs);
210
+ }
@@ -0,0 +1,46 @@
1
+ export type MonitorLogLevel = 'debug' | 'info' | 'warn' | 'error' | 'crash';
2
+ export interface MonitorLogEvent {
3
+ level: MonitorLogLevel;
4
+ content: string;
5
+ stack?: string;
6
+ type?: string;
7
+ [key: string]: unknown;
8
+ }
9
+ export interface MonitorEventBundle {
10
+ 'app.type': string;
11
+ _v: string;
12
+ endpoint: string;
13
+ 'session.id'?: string;
14
+ 'view.id'?: string;
15
+ timestamp: number;
16
+ event_type: 'log';
17
+ log?: MonitorLogEvent;
18
+ [key: string]: unknown;
19
+ }
20
+ export interface IMonitorReporter {
21
+ send(data: MonitorEventBundle[]): void;
22
+ }
23
+ /**
24
+ * 自监控配置
25
+ */
26
+ export interface ISelfMonitorConfig {
27
+ /**
28
+ * 是否启用自监控,默认 true
29
+ */
30
+ enable?: boolean;
31
+ /**
32
+ * 采样率,取值范围 0 - 100,支持小数(如 50.5 表示 50.5%)
33
+ * 所有级别日志统一受采样率控制
34
+ */
35
+ sampling?: number;
36
+ /**
37
+ * 是否在浏览器控制台输出自监控日志,默认 false
38
+ * 设为 true 时,所有级别日志会同时输出到控制台
39
+ */
40
+ console?: boolean;
41
+ /**
42
+ * 需要上报到 Telemetry 的日志级别列表
43
+ * 默认值: ['debug', 'error', 'crash']
44
+ */
45
+ reportLevels?: MonitorLogLevel[];
46
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -5,6 +5,7 @@ import { RumEvent, RumEventBundle, IViewData } from './rum-event';
5
5
  import { MatchOption } from '../utils/match';
6
6
  import { IConfigManager } from './config';
7
7
  import { EventEmitter } from '../utils/events';
8
+ import { ISelfMonitorConfig, IMonitorReporter } from '../monitor/types';
8
9
  export declare enum EventType {
9
10
  /**
10
11
  * 收集数据
@@ -33,7 +34,15 @@ export interface IContext {
33
34
  [key: string]: any;
34
35
  }
35
36
  export interface SessionConfig {
37
+ /**
38
+ * Session 采样率,取值范围 0 - 1 的小数
39
+ * @deprecated 该字段将在未来版本下线,请使用 {@link SessionConfig.sampling} 替代
40
+ */
36
41
  sampleRate?: number;
42
+ /**
43
+ * Session 采样率,取值范围 0 - 100,支持小数(如 50.5 表示 50.5%)
44
+ */
45
+ sampling?: number;
37
46
  maxDuration?: number;
38
47
  overtime?: number;
39
48
  storage?: string;
@@ -46,6 +55,10 @@ export interface IReportConfig {
46
55
  }
47
56
  export interface IRumSession {
48
57
  init(ctx: IContext): void;
58
+ /** 平台类型标识,如 'browser'/'miniapp' */
59
+ appType: string;
60
+ /** SDK 版本号 */
61
+ sdkVersion: string;
49
62
  sessionConfig: SessionConfig;
50
63
  getSessionId: () => string;
51
64
  getSampled: () => boolean;
@@ -102,7 +115,7 @@ export interface IClient {
102
115
  /**
103
116
  * 初始化
104
117
  */
105
- init: (configuration: IConfiguration, rumSession?: IRumSession, configManager?: IConfigManager) => void;
118
+ init: (configuration: IConfiguration, rumSession?: IRumSession, configManager?: IConfigManager, monitorReporter?: IMonitorReporter) => void;
106
119
  /**
107
120
  * 业务自定义上传数据
108
121
  */
@@ -227,5 +240,13 @@ export interface IConfiguration {
227
240
  attributeName: string;
228
241
  attributeValue?: Array<string | RegExp> | null;
229
242
  }>;
243
+ /**
244
+ * 自监控(Self-Monitor)配置
245
+ * 用于控制 SDK 内部异常和错误的自动上报行为
246
+ * - `boolean`: 简单启用/禁用自监控
247
+ * - `ISelfMonitorConfig`: 详细配置,可指定采样率等
248
+ * @default true
249
+ */
250
+ selfMonitor?: boolean | ISelfMonitorConfig;
230
251
  [key: string]: unknown;
231
252
  }