@arms/rum-core 0.1.5 → 0.1.7

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 (61) hide show
  1. package/es/index.d.ts +3 -0
  2. package/es/index.js +3 -0
  3. package/es/model/client.d.ts +5 -4
  4. package/es/model/client.js +32 -6
  5. package/es/model/reporter.d.ts +30 -7
  6. package/es/model/reporter.js +83 -25
  7. package/es/model/shell.d.ts +4 -4
  8. package/es/model/shell.js +13 -10
  9. package/es/monitor/index.d.ts +6 -0
  10. package/es/monitor/index.js +3 -0
  11. package/es/monitor/logger.d.ts +34 -0
  12. package/es/monitor/logger.js +112 -0
  13. package/es/monitor/telemetry.d.ts +42 -0
  14. package/es/monitor/telemetry.js +210 -0
  15. package/es/monitor/types.d.ts +46 -0
  16. package/es/monitor/types.js +1 -0
  17. package/es/types/client.d.ts +16 -3
  18. package/es/types/collector.d.ts +2 -2
  19. package/es/types/reporter.d.ts +2 -2
  20. package/es/types/rum-event.d.ts +9 -0
  21. package/es/types/rum-event.js +4 -0
  22. package/es/types/shell.d.ts +3 -3
  23. package/es/utils/base.js +2 -2
  24. package/es/utils/disposable.d.ts +12 -0
  25. package/es/utils/disposable.js +20 -0
  26. package/es/utils/events.js +2 -1
  27. package/es/utils/protobuf.d.ts +24 -0
  28. package/es/utils/protobuf.js +123 -0
  29. package/es/utils/throttle.d.ts +14 -0
  30. package/es/utils/throttle.js +40 -0
  31. package/lib/index.d.ts +3 -0
  32. package/lib/index.js +21 -0
  33. package/lib/model/client.d.ts +5 -4
  34. package/lib/model/client.js +31 -5
  35. package/lib/model/reporter.d.ts +30 -7
  36. package/lib/model/reporter.js +80 -22
  37. package/lib/model/shell.d.ts +4 -4
  38. package/lib/model/shell.js +11 -8
  39. package/lib/monitor/index.d.ts +6 -0
  40. package/lib/monitor/index.js +12 -0
  41. package/lib/monitor/logger.d.ts +34 -0
  42. package/lib/monitor/logger.js +117 -0
  43. package/lib/monitor/telemetry.d.ts +42 -0
  44. package/lib/monitor/telemetry.js +214 -0
  45. package/lib/monitor/types.d.ts +46 -0
  46. package/lib/monitor/types.js +3 -0
  47. package/lib/types/client.d.ts +16 -3
  48. package/lib/types/collector.d.ts +2 -2
  49. package/lib/types/reporter.d.ts +2 -2
  50. package/lib/types/rum-event.d.ts +9 -0
  51. package/lib/types/rum-event.js +2 -0
  52. package/lib/types/shell.d.ts +3 -3
  53. package/lib/utils/base.js +2 -2
  54. package/lib/utils/disposable.d.ts +12 -0
  55. package/lib/utils/disposable.js +24 -0
  56. package/lib/utils/events.js +2 -1
  57. package/lib/utils/protobuf.d.ts +24 -0
  58. package/lib/utils/protobuf.js +127 -0
  59. package/lib/utils/throttle.d.ts +14 -0
  60. package/lib/utils/throttle.js +44 -0
  61. package/package.json +10 -1
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ exports.__esModule = true;
5
+ exports.Telemetry = void 0;
6
+ exports.convertBundlesToLogGroup = convertBundlesToLogGroup;
7
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
8
+ var _logger = require("./logger");
9
+ var _url = require("../utils/url");
10
+ var _protobuf = require("../utils/protobuf");
11
+ var _number = require("../utils/number");
12
+ var _Telemetry;
13
+ var MAX_EVENTS_PER_PAGE = 15;
14
+ var BUFFER_SIZE = 100;
15
+ var LOG_CONTENT_MAX_SIZE = 12288;
16
+ var FLUSH_TIME = 5000;
17
+ var MAX_BATCH_SIZE = 10;
18
+ var DEFAULT_SAMPLE_RATE = 100;
19
+
20
+ /** 事件快照:在事件产生时就捕获上下文 */
21
+ var Telemetry = exports.Telemetry = /*#__PURE__*/function () {
22
+ function Telemetry(context, reporter) {
23
+ this.buffer = [];
24
+ this.queue = [];
25
+ this.sentEvents = new Set();
26
+ this.started = false;
27
+ this.enabled = true;
28
+ this.sampled = void 0;
29
+ this.timer = null;
30
+ this.reporter = void 0;
31
+ this.context = void 0;
32
+ this.isReporting = false;
33
+ this.endpointParams = void 0;
34
+ this.context = context;
35
+ this.reporter = reporter;
36
+ this.endpointParams = (0, _url.getUrlParams)(context.endpoint);
37
+
38
+ // 解析自监控配置
39
+ var selfMonitor = context.selfMonitor;
40
+ if (typeof selfMonitor === 'boolean') {
41
+ this.enabled = selfMonitor;
42
+ this.sampled = (0, _number.performDraw)(DEFAULT_SAMPLE_RATE);
43
+ } else if (selfMonitor && typeof selfMonitor === 'object') {
44
+ this.enabled = selfMonitor.enable !== false;
45
+ var rate = selfMonitor.sampling;
46
+ this.sampled = (0, _number.performDraw)(typeof rate === 'number' && rate >= 0 && rate <= 100 ? rate : DEFAULT_SAMPLE_RATE);
47
+ if (selfMonitor.console) {
48
+ _logger.logger.setConsole(true);
49
+ }
50
+ if (selfMonitor.reportLevels) {
51
+ _logger.logger.setReportLevels(selfMonitor.reportLevels);
52
+ }
53
+ } else {
54
+ this.enabled = true;
55
+ this.sampled = (0, _number.performDraw)(DEFAULT_SAMPLE_RATE);
56
+ }
57
+ }
58
+ Telemetry.init = function init(context, reporter) {
59
+ if (Telemetry.instance) {
60
+ Telemetry.instance.flush();
61
+ }
62
+ Telemetry.instance = new Telemetry(context, reporter);
63
+ Telemetry.instance.start();
64
+ return Telemetry.instance;
65
+ };
66
+ Telemetry.get = function get() {
67
+ return Telemetry.instance;
68
+ };
69
+ var _proto = Telemetry.prototype;
70
+ _proto.start = function start() {
71
+ var _this = this;
72
+ if (this.started) return;
73
+ this.started = true;
74
+ _logger.logger.setOnError(function (event) {
75
+ return _this.addEvent(event);
76
+ });
77
+ this.flushBuffer();
78
+ };
79
+ _proto.addEvent = function addEvent(event) {
80
+ var _this$context$getSess, _this$context, _this$context$getView, _this$context2;
81
+ if (!this.enabled || !event) return;
82
+ if (event.content && event.content.length > LOG_CONTENT_MAX_SIZE) {
83
+ event = (0, _extends2["default"])({}, event, {
84
+ content: event.content.slice(0, LOG_CONTENT_MAX_SIZE)
85
+ });
86
+ }
87
+ if (event.stack && event.stack.length > LOG_CONTENT_MAX_SIZE) {
88
+ event = (0, _extends2["default"])({}, event, {
89
+ stack: event.stack.slice(0, LOG_CONTENT_MAX_SIZE)
90
+ });
91
+ }
92
+
93
+ // 在事件产生时就捕获快照
94
+ var snapshot = {
95
+ event: event,
96
+ sessionId: (_this$context$getSess = (_this$context = this.context).getSessionId) === null || _this$context$getSess === void 0 ? void 0 : _this$context$getSess.call(_this$context),
97
+ viewId: (_this$context$getView = (_this$context2 = this.context).getViewId) === null || _this$context$getView === void 0 ? void 0 : _this$context$getView.call(_this$context2),
98
+ timestamp: Date.now()
99
+ };
100
+ if (!this.started || !this.reporter) {
101
+ if (this.buffer.length < BUFFER_SIZE) {
102
+ this.buffer.push(snapshot);
103
+ }
104
+ return;
105
+ }
106
+ this.processSnapshot(snapshot);
107
+ };
108
+ _proto.flush = function flush() {
109
+ if (this.timer) {
110
+ clearTimeout(this.timer);
111
+ this.timer = null;
112
+ }
113
+ this.sendBatch();
114
+ };
115
+ _proto.setReporter = function setReporter(reporter) {
116
+ this.reporter = reporter;
117
+ if (this.started) {
118
+ this.flushBuffer();
119
+ }
120
+ };
121
+ _proto.flushBuffer = function flushBuffer() {
122
+ var _this2 = this;
123
+ var buffered = this.buffer.splice(0);
124
+ buffered.forEach(function (snapshot) {
125
+ return _this2.processSnapshot(snapshot);
126
+ });
127
+ };
128
+ _proto.processSnapshot = function processSnapshot(snapshot) {
129
+ var _this3 = this;
130
+ if (!this.shouldSend(snapshot.event)) return;
131
+ var bundle = this.buildBundle(snapshot);
132
+ this.queue.push(bundle);
133
+ if (this.queue.length >= MAX_BATCH_SIZE) {
134
+ this.flush();
135
+ } else if (!this.timer) {
136
+ this.timer = setTimeout(function () {
137
+ return _this3.flush();
138
+ }, FLUSH_TIME);
139
+ }
140
+ };
141
+ _proto.shouldSend = function shouldSend(event) {
142
+ // 先检查 Session 采样,未命中则不上报
143
+ if (this.context.getSessionSampled && !this.context.getSessionSampled()) return false;
144
+ // 再检查自监控自身采样
145
+ if (!this.sampled) return false;
146
+ if (this.sentEvents.size >= MAX_EVENTS_PER_PAGE) return false;
147
+ var key = (event.content || '') + (event.stack || '');
148
+ if (this.sentEvents.has(key)) return false;
149
+ this.sentEvents.add(key);
150
+ return true;
151
+ };
152
+ _proto.buildBundle = function buildBundle(snapshot) {
153
+ var _this$context3 = this.context,
154
+ appType = _this$context3.appType,
155
+ sdkVersion = _this$context3.sdkVersion,
156
+ endpoint = _this$context3.endpoint;
157
+ return (0, _extends2["default"])({
158
+ 'app.type': appType,
159
+ _v: sdkVersion,
160
+ endpoint: endpoint,
161
+ 'session.id': snapshot.sessionId,
162
+ 'view.id': snapshot.viewId,
163
+ timestamp: snapshot.timestamp,
164
+ event_type: 'log',
165
+ log: snapshot.event
166
+ }, this.endpointParams);
167
+ };
168
+ _proto.sendBatch = function sendBatch() {
169
+ if (this.queue.length === 0 || !this.reporter) return;
170
+ if (this.isReporting) return;
171
+ var batch = this.queue.splice(0);
172
+ this.isReporting = true;
173
+ try {
174
+ this.reporter.send(batch);
175
+ } catch (e) {
176
+ // 不通过 logger(避免反馈循环),直接 console 仅供开发调试
177
+ try {
178
+ console.warn('[RUM-Telemetry] send failed:', e);
179
+ } catch (_) {}
180
+ } finally {
181
+ this.isReporting = false;
182
+ }
183
+ };
184
+ return Telemetry;
185
+ }();
186
+ /**
187
+ * 将 MonitorEventBundle 数组转换并编码为 SLS LogGroup Protobuf 格式
188
+ */
189
+ _Telemetry = Telemetry;
190
+ Telemetry.instance = void 0;
191
+ function convertBundlesToLogGroup(data) {
192
+ var logs = data.map(function (bundle) {
193
+ var contents = [];
194
+
195
+ // 遍历 bundle 顶层字段,跳过 timestamp(映射到 time),对象类型整体序列化
196
+ for (var _i = 0, _Object$entries = Object.entries(bundle); _i < _Object$entries.length; _i++) {
197
+ var _Object$entries$_i = _Object$entries[_i],
198
+ _key = _Object$entries$_i[0],
199
+ val = _Object$entries$_i[1];
200
+ if (_key === 'timestamp') continue;
201
+ if (val !== undefined && val !== null) {
202
+ contents.push({
203
+ key: _key,
204
+ value: typeof val === 'object' ? JSON.stringify(val) : String(val)
205
+ });
206
+ }
207
+ }
208
+ return {
209
+ time: Math.floor(bundle.timestamp / 1000),
210
+ contents: contents
211
+ };
212
+ });
213
+ return (0, _protobuf.encodeLogGroup)(logs);
214
+ }
@@ -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,3 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
@@ -1,10 +1,11 @@
1
1
  import { ICollector } from './collector';
2
2
  import { IProcessor } from './processor';
3
3
  import { IReporter } from './reporter';
4
- import { RumEvent, RumEventBundle, IViewData } from './rum-event';
4
+ import { RumEvent, RumEventBundle, IViewData, SendEventOptions } 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
  * 收集数据
@@ -54,6 +55,10 @@ export interface IReportConfig {
54
55
  }
55
56
  export interface IRumSession {
56
57
  init(ctx: IContext): void;
58
+ /** 平台类型标识,如 'browser'/'miniapp' */
59
+ appType: string;
60
+ /** SDK 版本号 */
61
+ sdkVersion: string;
57
62
  sessionConfig: SessionConfig;
58
63
  getSessionId: () => string;
59
64
  getSampled: () => boolean;
@@ -110,11 +115,11 @@ export interface IClient {
110
115
  /**
111
116
  * 初始化
112
117
  */
113
- init: (configuration: IConfiguration, rumSession?: IRumSession, configManager?: IConfigManager) => void;
118
+ init: (configuration: IConfiguration, rumSession?: IRumSession, configManager?: IConfigManager, monitorReporter?: IMonitorReporter) => void;
114
119
  /**
115
120
  * 业务自定义上传数据
116
121
  */
117
- sendEvent(payload: RumEvent): void;
122
+ sendEvent(payload: RumEvent, options?: SendEventOptions): void;
118
123
  /**
119
124
  * 修改运行时上下文
120
125
  */
@@ -235,5 +240,13 @@ export interface IConfiguration {
235
240
  attributeName: string;
236
241
  attributeValue?: Array<string | RegExp> | null;
237
242
  }>;
243
+ /**
244
+ * 自监控(Self-Monitor)配置
245
+ * 用于控制 SDK 内部异常和错误的自动上报行为
246
+ * - `boolean`: 简单启用/禁用自监控
247
+ * - `ISelfMonitorConfig`: 详细配置,可指定采样率等
248
+ * @default true
249
+ */
250
+ selfMonitor?: boolean | ISelfMonitorConfig;
238
251
  [key: string]: unknown;
239
252
  }
@@ -1,7 +1,7 @@
1
1
  import { IContext } from './client';
2
- import { RumEvent } from './rum-event';
2
+ import { SendEventFn } from './rum-event';
3
3
  export interface ICollector {
4
4
  name: string;
5
- setup(ctx: IContext, sendEvent: (payload: RumEvent) => void): void;
5
+ setup(ctx: IContext, sendEvent: SendEventFn): void;
6
6
  destroy?(): void;
7
7
  }
@@ -1,8 +1,8 @@
1
1
  import { IContext } from './client';
2
- import { RumEventBundle } from './rum-event';
2
+ import { RumEventBundle, SendEventOptions } from './rum-event';
3
3
  export interface IReporter {
4
4
  name: string;
5
5
  init(ctx: IContext): void;
6
6
  request(ctx: IContext, bundle: RumEventBundle): void;
7
- report(ctx: IContext): void;
7
+ report(ctx: IContext, options?: SendEventOptions): void;
8
8
  }
@@ -7,6 +7,15 @@ export declare enum RumEventType {
7
7
  CUSTOM = "custom",
8
8
  APPLICATION = "application"
9
9
  }
10
+ /** sendEvent 方法的可选配置 */
11
+ export interface SendEventOptions {
12
+ /** 是否立即上报,将当前事件加入队列后立即 flush 整个队列 */
13
+ immediate?: boolean;
14
+ /** 是否单独上报,当前事件不入队列,独立打包发送 */
15
+ single?: boolean;
16
+ }
17
+ /** 采集器向上层发送事件的统一回调签名 */
18
+ export type SendEventFn = (payload: RumEvent, options?: SendEventOptions) => void;
10
19
  export interface BaseObject {
11
20
  [key: string]: BaseObjectValue;
12
21
  }
@@ -12,6 +12,8 @@ var RumEventType = exports.RumEventType = /*#__PURE__*/function (RumEventType) {
12
12
  RumEventType["APPLICATION"] = "application";
13
13
  return RumEventType;
14
14
  }({});
15
+ /** sendEvent 方法的可选配置 */
16
+ /** 采集器向上层发送事件的统一回调签名 */
15
17
  /** 电池信息 */
16
18
  /** 设备信息 */
17
19
  /** 内存信息 */
@@ -1,5 +1,5 @@
1
- import { IConfiguration } from "./client";
2
- import { RumEvent } from "./rum-event";
1
+ import { IConfiguration } from './client';
2
+ import { RumEvent, SendEventOptions } from './rum-event';
3
3
  /**
4
4
  * 每个 sdk shell 导出固定需要实现的基础 api
5
5
  * 对外导出 shell 层, 所有 shell 层模型的 API 设计约定:
@@ -15,7 +15,7 @@ export interface IShell {
15
15
  /**
16
16
  * 自定义上传数据
17
17
  */
18
- sendEvent(payload: RumEvent): void;
18
+ sendEvent(payload: RumEvent, options?: SendEventOptions): void;
19
19
  /**
20
20
  * get config
21
21
  */
package/lib/utils/base.js CHANGED
@@ -38,9 +38,9 @@ function interceptFunction(target, name, callback, isPrototype) {
38
38
  */
39
39
  function restoreFunction(target, name) {
40
40
  var proxyMethod = target[name];
41
- if ((0, _is.isFunction)(proxyMethod)) return;
41
+ if (!(0, _is.isFunction)(proxyMethod)) return;
42
42
  var originalMethod = proxyMethod._rum_intercepted;
43
- if ((0, _is.isFunction)(originalMethod)) return;
43
+ if (!(0, _is.isFunction)(originalMethod)) return;
44
44
  target[name] = originalMethod;
45
45
  }
46
46
 
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 资源清理组:统一管理多个清理函数的生命周期
3
+ *
4
+ * 用于收敛采集器中常见的 cleanup 数组模式,
5
+ * 避免每个采集器重复实现 push + forEach 逻辑
6
+ */
7
+ export declare function createDisposableGroup(): {
8
+ /** 注册一个或多个清理函数 */
9
+ add(...fns: Array<() => void>): void;
10
+ /** 执行所有清理函数并重置 */
11
+ dispose(): void;
12
+ };
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.createDisposableGroup = createDisposableGroup;
5
+ /**
6
+ * 资源清理组:统一管理多个清理函数的生命周期
7
+ *
8
+ * 用于收敛采集器中常见的 cleanup 数组模式,
9
+ * 避免每个采集器重复实现 push + forEach 逻辑
10
+ */
11
+ function createDisposableGroup() {
12
+ var cleanups = [];
13
+ return {
14
+ /** 注册一个或多个清理函数 */add: function add() {
15
+ cleanups.push.apply(cleanups, arguments);
16
+ },
17
+ /** 执行所有清理函数并重置 */dispose: function dispose() {
18
+ cleanups.forEach(function (fn) {
19
+ return fn();
20
+ });
21
+ cleanups.length = 0;
22
+ }
23
+ };
24
+ }
@@ -2,6 +2,7 @@
2
2
 
3
3
  exports.__esModule = true;
4
4
  exports.EventEmitter = void 0;
5
+ var _logger = require("../monitor/logger");
5
6
  var EventEmitter = exports.EventEmitter = /*#__PURE__*/function () {
6
7
  function EventEmitter() {
7
8
  this.events = {};
@@ -36,7 +37,7 @@ var EventEmitter = exports.EventEmitter = /*#__PURE__*/function () {
36
37
  try {
37
38
  handlersCopy[i].apply(handlersCopy, args);
38
39
  } catch (err) {
39
- console.error("Error in handler for \"" + eventName + "\":", err);
40
+ _logger.logger.error('EventEmitter', "Error in handler for \"" + eventName + "\"", err);
40
41
  }
41
42
  }
42
43
  }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * SLS LogGroup Protobuf 编码器(最小化实现,零外部依赖)
3
+ *
4
+ * Schema:
5
+ * message Log {
6
+ * required uint32 Time = 1;
7
+ * message Content { required string Key = 1; required string Value = 2; }
8
+ * repeated Content Contents = 2;
9
+ * }
10
+ * message LogTag { required string Key = 1; required string Value = 2; }
11
+ * message LogGroup {
12
+ * repeated Log Logs = 1;
13
+ * optional string Topic = 3;
14
+ * optional string Source = 4;
15
+ * repeated LogTag LogTags = 6;
16
+ * }
17
+ */
18
+ export declare function encodeLogGroup(logs: Array<{
19
+ time: number;
20
+ contents: Array<{
21
+ key: string;
22
+ value: string;
23
+ }>;
24
+ }>, topic?: string, source?: string): Uint8Array;
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.encodeLogGroup = encodeLogGroup;
5
+ /**
6
+ * SLS LogGroup Protobuf 编码器(最小化实现,零外部依赖)
7
+ *
8
+ * Schema:
9
+ * message Log {
10
+ * required uint32 Time = 1;
11
+ * message Content { required string Key = 1; required string Value = 2; }
12
+ * repeated Content Contents = 2;
13
+ * }
14
+ * message LogTag { required string Key = 1; required string Value = 2; }
15
+ * message LogGroup {
16
+ * repeated Log Logs = 1;
17
+ * optional string Topic = 3;
18
+ * optional string Source = 4;
19
+ * repeated LogTag LogTags = 6;
20
+ * }
21
+ */
22
+
23
+ var WIRE_TYPE_VARINT = 0;
24
+ var WIRE_TYPE_LEN = 2;
25
+
26
+ /**
27
+ * UTF-8 编码 fallback(当 TextEncoder 不可用时使用,如部分小程序环境)
28
+ */
29
+ function encodeUtf8Fallback(str) {
30
+ var bytes = [];
31
+ for (var i = 0; i < str.length; i++) {
32
+ var charCode = str.charCodeAt(i);
33
+ if (charCode < 0x80) {
34
+ bytes.push(charCode);
35
+ } else if (charCode < 0x800) {
36
+ bytes.push(0xc0 | charCode >> 6);
37
+ bytes.push(0x80 | charCode & 0x3f);
38
+ } else if (charCode >= 0xd800 && charCode <= 0xdbff) {
39
+ // 代理对处理
40
+ i++;
41
+ var low = str.charCodeAt(i);
42
+ charCode = 0x10000 + (charCode - 0xd800 << 10) + (low - 0xdc00);
43
+ bytes.push(0xf0 | charCode >> 18);
44
+ bytes.push(0x80 | charCode >> 12 & 0x3f);
45
+ bytes.push(0x80 | charCode >> 6 & 0x3f);
46
+ bytes.push(0x80 | charCode & 0x3f);
47
+ } else {
48
+ bytes.push(0xe0 | charCode >> 12);
49
+ bytes.push(0x80 | charCode >> 6 & 0x3f);
50
+ bytes.push(0x80 | charCode & 0x3f);
51
+ }
52
+ }
53
+ return new Uint8Array(bytes);
54
+ }
55
+ var utf8Encoder = typeof TextEncoder !== 'undefined' ? new TextEncoder() : {
56
+ encode: encodeUtf8Fallback
57
+ };
58
+ var ProtobufWriter = /*#__PURE__*/function () {
59
+ function ProtobufWriter() {
60
+ this.buf = [];
61
+ }
62
+ var _proto = ProtobufWriter.prototype;
63
+ _proto.writeVarint = function writeVarint(value) {
64
+ // Base-128 可变长整数编码(仅处理非负整数)
65
+ var v = value >>> 0;
66
+ while (v > 0x7f) {
67
+ this.buf.push(v & 0x7f | 0x80);
68
+ v = v >>> 7;
69
+ }
70
+ this.buf.push(v & 0x7f);
71
+ };
72
+ _proto.writeTag = function writeTag(fieldNumber, wireType) {
73
+ this.writeVarint(fieldNumber << 3 | wireType);
74
+ };
75
+ _proto.writeString = function writeString(fieldNumber, value) {
76
+ var bytes = utf8Encoder.encode(value);
77
+ this.writeTag(fieldNumber, WIRE_TYPE_LEN);
78
+ this.writeVarint(bytes.length);
79
+ for (var i = 0; i < bytes.length; i++) {
80
+ this.buf.push(bytes[i]);
81
+ }
82
+ };
83
+ _proto.writeUint32 = function writeUint32(fieldNumber, value) {
84
+ this.writeTag(fieldNumber, WIRE_TYPE_VARINT);
85
+ this.writeVarint(value);
86
+ };
87
+ _proto.writeBytes = function writeBytes(fieldNumber, data) {
88
+ this.writeTag(fieldNumber, WIRE_TYPE_LEN);
89
+ this.writeVarint(data.length);
90
+ for (var i = 0; i < data.length; i++) {
91
+ this.buf.push(data[i]);
92
+ }
93
+ };
94
+ _proto.finish = function finish() {
95
+ return new Uint8Array(this.buf);
96
+ };
97
+ return ProtobufWriter;
98
+ }();
99
+ function encodeContent(key, value) {
100
+ var w = new ProtobufWriter();
101
+ w.writeString(1, key);
102
+ w.writeString(2, value);
103
+ return w.finish();
104
+ }
105
+ function encodeLog(time, contents) {
106
+ var w = new ProtobufWriter();
107
+ w.writeUint32(1, time);
108
+ for (var i = 0; i < contents.length; i++) {
109
+ var c = contents[i];
110
+ w.writeBytes(2, encodeContent(c.key, c.value));
111
+ }
112
+ return w.finish();
113
+ }
114
+ function encodeLogGroup(logs, topic, source) {
115
+ var w = new ProtobufWriter();
116
+ for (var i = 0; i < logs.length; i++) {
117
+ var log = logs[i];
118
+ w.writeBytes(1, encodeLog(log.time, log.contents));
119
+ }
120
+ if (topic !== undefined) {
121
+ w.writeString(3, topic);
122
+ }
123
+ if (source !== undefined) {
124
+ w.writeString(4, source);
125
+ }
126
+ return w.finish();
127
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * 带 cancel 的 leading + trailing 节流函数
3
+ *
4
+ * - leading:连续调用时立即触发首次
5
+ * - trailing:保证最后一次在 wait 内补发
6
+ * - cancel:丢弃尾调用并重置节流窗口,防止跨 view 串数据
7
+ *
8
+ * @param fn 需要节流的函数
9
+ * @param wait 节流间隔(毫秒)
10
+ */
11
+ export declare function throttle(fn: () => void, wait: number): {
12
+ (): void;
13
+ cancel: () => void;
14
+ };
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.throttle = throttle;
5
+ /**
6
+ * 带 cancel 的 leading + trailing 节流函数
7
+ *
8
+ * - leading:连续调用时立即触发首次
9
+ * - trailing:保证最后一次在 wait 内补发
10
+ * - cancel:丢弃尾调用并重置节流窗口,防止跨 view 串数据
11
+ *
12
+ * @param fn 需要节流的函数
13
+ * @param wait 节流间隔(毫秒)
14
+ */
15
+ function throttle(fn, wait) {
16
+ var lastInvoke = 0;
17
+ var timer = null;
18
+ var invoke = function invoke() {
19
+ lastInvoke = Date.now();
20
+ timer = null;
21
+ fn();
22
+ };
23
+ var wrapped = function wrapped() {
24
+ var remaining = wait - (Date.now() - lastInvoke);
25
+ if (remaining <= 0) {
26
+ if (timer) {
27
+ clearTimeout(timer);
28
+ timer = null;
29
+ }
30
+ invoke();
31
+ } else if (!timer) {
32
+ timer = setTimeout(invoke, remaining);
33
+ }
34
+ };
35
+ wrapped.cancel = function () {
36
+ if (timer) {
37
+ clearTimeout(timer);
38
+ timer = null;
39
+ }
40
+ // 重置 leading 窗口,让下次调用立刻触发,避免跨 view 共享上次的节流窗口
41
+ lastInvoke = 0;
42
+ };
43
+ return wrapped;
44
+ }
package/package.json CHANGED
@@ -1,11 +1,20 @@
1
1
  {
2
2
  "name": "@arms/rum-core",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "arms rum javascript sdk core",
5
5
  "author": "guangli.fj <guangli.fj@alibaba-inc.com>",
6
6
  "license": "ISC",
7
7
  "main": "lib/index.js",
8
8
  "module": "es/index.js",
9
+ "types": "es/index.d.ts",
10
+ "sideEffects": false,
11
+ "exports": {
12
+ ".": {
13
+ "types": "./es/index.d.ts",
14
+ "import": "./es/index.js",
15
+ "require": "./lib/index.js"
16
+ }
17
+ },
9
18
  "directories": {
10
19
  "lib": "lib",
11
20
  "es": "es",