@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.
- package/es/index.d.ts +3 -0
- package/es/index.js +3 -0
- package/es/model/client.d.ts +5 -4
- package/es/model/client.js +32 -6
- package/es/model/reporter.d.ts +30 -7
- package/es/model/reporter.js +83 -25
- package/es/model/shell.d.ts +4 -4
- package/es/model/shell.js +13 -10
- package/es/monitor/index.d.ts +6 -0
- package/es/monitor/index.js +3 -0
- package/es/monitor/logger.d.ts +34 -0
- package/es/monitor/logger.js +112 -0
- package/es/monitor/telemetry.d.ts +42 -0
- package/es/monitor/telemetry.js +210 -0
- package/es/monitor/types.d.ts +46 -0
- package/es/monitor/types.js +1 -0
- package/es/types/client.d.ts +16 -3
- package/es/types/collector.d.ts +2 -2
- package/es/types/reporter.d.ts +2 -2
- package/es/types/rum-event.d.ts +9 -0
- package/es/types/rum-event.js +4 -0
- package/es/types/shell.d.ts +3 -3
- package/es/utils/base.js +2 -2
- package/es/utils/disposable.d.ts +12 -0
- package/es/utils/disposable.js +20 -0
- package/es/utils/events.js +2 -1
- package/es/utils/protobuf.d.ts +24 -0
- package/es/utils/protobuf.js +123 -0
- package/es/utils/throttle.d.ts +14 -0
- package/es/utils/throttle.js +40 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +21 -0
- package/lib/model/client.d.ts +5 -4
- package/lib/model/client.js +31 -5
- package/lib/model/reporter.d.ts +30 -7
- package/lib/model/reporter.js +80 -22
- package/lib/model/shell.d.ts +4 -4
- package/lib/model/shell.js +11 -8
- package/lib/monitor/index.d.ts +6 -0
- package/lib/monitor/index.js +12 -0
- package/lib/monitor/logger.d.ts +34 -0
- package/lib/monitor/logger.js +117 -0
- package/lib/monitor/telemetry.d.ts +42 -0
- package/lib/monitor/telemetry.js +214 -0
- package/lib/monitor/types.d.ts +46 -0
- package/lib/monitor/types.js +3 -0
- package/lib/types/client.d.ts +16 -3
- package/lib/types/collector.d.ts +2 -2
- package/lib/types/reporter.d.ts +2 -2
- package/lib/types/rum-event.d.ts +9 -0
- package/lib/types/rum-event.js +2 -0
- package/lib/types/shell.d.ts +3 -3
- package/lib/utils/base.js +2 -2
- package/lib/utils/disposable.d.ts +12 -0
- package/lib/utils/disposable.js +24 -0
- package/lib/utils/events.js +2 -1
- package/lib/utils/protobuf.d.ts +24 -0
- package/lib/utils/protobuf.js +127 -0
- package/lib/utils/throttle.d.ts +14 -0
- package/lib/utils/throttle.js +44 -0
- package/package.json +10 -1
|
@@ -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 {};
|
package/es/types/client.d.ts
CHANGED
|
@@ -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
|
}
|
package/es/types/collector.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IContext } from './client';
|
|
2
|
-
import {
|
|
2
|
+
import { SendEventFn } from './rum-event';
|
|
3
3
|
export interface ICollector {
|
|
4
4
|
name: string;
|
|
5
|
-
setup(ctx: IContext, sendEvent:
|
|
5
|
+
setup(ctx: IContext, sendEvent: SendEventFn): void;
|
|
6
6
|
destroy?(): void;
|
|
7
7
|
}
|
package/es/types/reporter.d.ts
CHANGED
|
@@ -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
|
}
|
package/es/types/rum-event.d.ts
CHANGED
|
@@ -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
|
}
|
package/es/types/rum-event.js
CHANGED
package/es/types/shell.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IConfiguration } from
|
|
2
|
-
import { RumEvent } from
|
|
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/es/utils/base.js
CHANGED
|
@@ -27,9 +27,9 @@ export function interceptFunction(target, name, callback, isPrototype) {
|
|
|
27
27
|
*/
|
|
28
28
|
export function restoreFunction(target, name) {
|
|
29
29
|
var proxyMethod = target[name];
|
|
30
|
-
if (isFunction(proxyMethod)) return;
|
|
30
|
+
if (!isFunction(proxyMethod)) return;
|
|
31
31
|
var originalMethod = proxyMethod._rum_intercepted;
|
|
32
|
-
if (isFunction(originalMethod)) return;
|
|
32
|
+
if (!isFunction(originalMethod)) return;
|
|
33
33
|
target[name] = originalMethod;
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -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,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 资源清理组:统一管理多个清理函数的生命周期
|
|
3
|
+
*
|
|
4
|
+
* 用于收敛采集器中常见的 cleanup 数组模式,
|
|
5
|
+
* 避免每个采集器重复实现 push + forEach 逻辑
|
|
6
|
+
*/
|
|
7
|
+
export function createDisposableGroup() {
|
|
8
|
+
var cleanups = [];
|
|
9
|
+
return {
|
|
10
|
+
/** 注册一个或多个清理函数 */add: function add() {
|
|
11
|
+
cleanups.push.apply(cleanups, arguments);
|
|
12
|
+
},
|
|
13
|
+
/** 执行所有清理函数并重置 */dispose: function dispose() {
|
|
14
|
+
cleanups.forEach(function (fn) {
|
|
15
|
+
return fn();
|
|
16
|
+
});
|
|
17
|
+
cleanups.length = 0;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
package/es/utils/events.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { logger } from '../monitor/logger';
|
|
1
2
|
export var EventEmitter = /*#__PURE__*/function () {
|
|
2
3
|
function EventEmitter() {
|
|
3
4
|
this.events = {};
|
|
@@ -32,7 +33,7 @@ export var EventEmitter = /*#__PURE__*/function () {
|
|
|
32
33
|
try {
|
|
33
34
|
handlersCopy[i].apply(handlersCopy, args);
|
|
34
35
|
} catch (err) {
|
|
35
|
-
|
|
36
|
+
logger.error('EventEmitter', "Error in handler for \"" + eventName + "\"", err);
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
}
|
|
@@ -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,123 @@
|
|
|
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
|
+
|
|
19
|
+
var WIRE_TYPE_VARINT = 0;
|
|
20
|
+
var WIRE_TYPE_LEN = 2;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* UTF-8 编码 fallback(当 TextEncoder 不可用时使用,如部分小程序环境)
|
|
24
|
+
*/
|
|
25
|
+
function encodeUtf8Fallback(str) {
|
|
26
|
+
var bytes = [];
|
|
27
|
+
for (var i = 0; i < str.length; i++) {
|
|
28
|
+
var charCode = str.charCodeAt(i);
|
|
29
|
+
if (charCode < 0x80) {
|
|
30
|
+
bytes.push(charCode);
|
|
31
|
+
} else if (charCode < 0x800) {
|
|
32
|
+
bytes.push(0xc0 | charCode >> 6);
|
|
33
|
+
bytes.push(0x80 | charCode & 0x3f);
|
|
34
|
+
} else if (charCode >= 0xd800 && charCode <= 0xdbff) {
|
|
35
|
+
// 代理对处理
|
|
36
|
+
i++;
|
|
37
|
+
var low = str.charCodeAt(i);
|
|
38
|
+
charCode = 0x10000 + (charCode - 0xd800 << 10) + (low - 0xdc00);
|
|
39
|
+
bytes.push(0xf0 | charCode >> 18);
|
|
40
|
+
bytes.push(0x80 | charCode >> 12 & 0x3f);
|
|
41
|
+
bytes.push(0x80 | charCode >> 6 & 0x3f);
|
|
42
|
+
bytes.push(0x80 | charCode & 0x3f);
|
|
43
|
+
} else {
|
|
44
|
+
bytes.push(0xe0 | charCode >> 12);
|
|
45
|
+
bytes.push(0x80 | charCode >> 6 & 0x3f);
|
|
46
|
+
bytes.push(0x80 | charCode & 0x3f);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return new Uint8Array(bytes);
|
|
50
|
+
}
|
|
51
|
+
var utf8Encoder = typeof TextEncoder !== 'undefined' ? new TextEncoder() : {
|
|
52
|
+
encode: encodeUtf8Fallback
|
|
53
|
+
};
|
|
54
|
+
var ProtobufWriter = /*#__PURE__*/function () {
|
|
55
|
+
function ProtobufWriter() {
|
|
56
|
+
this.buf = [];
|
|
57
|
+
}
|
|
58
|
+
var _proto = ProtobufWriter.prototype;
|
|
59
|
+
_proto.writeVarint = function writeVarint(value) {
|
|
60
|
+
// Base-128 可变长整数编码(仅处理非负整数)
|
|
61
|
+
var v = value >>> 0;
|
|
62
|
+
while (v > 0x7f) {
|
|
63
|
+
this.buf.push(v & 0x7f | 0x80);
|
|
64
|
+
v = v >>> 7;
|
|
65
|
+
}
|
|
66
|
+
this.buf.push(v & 0x7f);
|
|
67
|
+
};
|
|
68
|
+
_proto.writeTag = function writeTag(fieldNumber, wireType) {
|
|
69
|
+
this.writeVarint(fieldNumber << 3 | wireType);
|
|
70
|
+
};
|
|
71
|
+
_proto.writeString = function writeString(fieldNumber, value) {
|
|
72
|
+
var bytes = utf8Encoder.encode(value);
|
|
73
|
+
this.writeTag(fieldNumber, WIRE_TYPE_LEN);
|
|
74
|
+
this.writeVarint(bytes.length);
|
|
75
|
+
for (var i = 0; i < bytes.length; i++) {
|
|
76
|
+
this.buf.push(bytes[i]);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
_proto.writeUint32 = function writeUint32(fieldNumber, value) {
|
|
80
|
+
this.writeTag(fieldNumber, WIRE_TYPE_VARINT);
|
|
81
|
+
this.writeVarint(value);
|
|
82
|
+
};
|
|
83
|
+
_proto.writeBytes = function writeBytes(fieldNumber, data) {
|
|
84
|
+
this.writeTag(fieldNumber, WIRE_TYPE_LEN);
|
|
85
|
+
this.writeVarint(data.length);
|
|
86
|
+
for (var i = 0; i < data.length; i++) {
|
|
87
|
+
this.buf.push(data[i]);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
_proto.finish = function finish() {
|
|
91
|
+
return new Uint8Array(this.buf);
|
|
92
|
+
};
|
|
93
|
+
return ProtobufWriter;
|
|
94
|
+
}();
|
|
95
|
+
function encodeContent(key, value) {
|
|
96
|
+
var w = new ProtobufWriter();
|
|
97
|
+
w.writeString(1, key);
|
|
98
|
+
w.writeString(2, value);
|
|
99
|
+
return w.finish();
|
|
100
|
+
}
|
|
101
|
+
function encodeLog(time, contents) {
|
|
102
|
+
var w = new ProtobufWriter();
|
|
103
|
+
w.writeUint32(1, time);
|
|
104
|
+
for (var i = 0; i < contents.length; i++) {
|
|
105
|
+
var c = contents[i];
|
|
106
|
+
w.writeBytes(2, encodeContent(c.key, c.value));
|
|
107
|
+
}
|
|
108
|
+
return w.finish();
|
|
109
|
+
}
|
|
110
|
+
export function encodeLogGroup(logs, topic, source) {
|
|
111
|
+
var w = new ProtobufWriter();
|
|
112
|
+
for (var i = 0; i < logs.length; i++) {
|
|
113
|
+
var log = logs[i];
|
|
114
|
+
w.writeBytes(1, encodeLog(log.time, log.contents));
|
|
115
|
+
}
|
|
116
|
+
if (topic !== undefined) {
|
|
117
|
+
w.writeString(3, topic);
|
|
118
|
+
}
|
|
119
|
+
if (source !== undefined) {
|
|
120
|
+
w.writeString(4, source);
|
|
121
|
+
}
|
|
122
|
+
return w.finish();
|
|
123
|
+
}
|
|
@@ -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,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 带 cancel 的 leading + trailing 节流函数
|
|
3
|
+
*
|
|
4
|
+
* - leading:连续调用时立即触发首次
|
|
5
|
+
* - trailing:保证最后一次在 wait 内补发
|
|
6
|
+
* - cancel:丢弃尾调用并重置节流窗口,防止跨 view 串数据
|
|
7
|
+
*
|
|
8
|
+
* @param fn 需要节流的函数
|
|
9
|
+
* @param wait 节流间隔(毫秒)
|
|
10
|
+
*/
|
|
11
|
+
export function throttle(fn, wait) {
|
|
12
|
+
var lastInvoke = 0;
|
|
13
|
+
var timer = null;
|
|
14
|
+
var invoke = function invoke() {
|
|
15
|
+
lastInvoke = Date.now();
|
|
16
|
+
timer = null;
|
|
17
|
+
fn();
|
|
18
|
+
};
|
|
19
|
+
var wrapped = function wrapped() {
|
|
20
|
+
var remaining = wait - (Date.now() - lastInvoke);
|
|
21
|
+
if (remaining <= 0) {
|
|
22
|
+
if (timer) {
|
|
23
|
+
clearTimeout(timer);
|
|
24
|
+
timer = null;
|
|
25
|
+
}
|
|
26
|
+
invoke();
|
|
27
|
+
} else if (!timer) {
|
|
28
|
+
timer = setTimeout(invoke, remaining);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
wrapped.cancel = function () {
|
|
32
|
+
if (timer) {
|
|
33
|
+
clearTimeout(timer);
|
|
34
|
+
timer = null;
|
|
35
|
+
}
|
|
36
|
+
// 重置 leading 窗口,让下次调用立刻触发,避免跨 view 共享上次的节流窗口
|
|
37
|
+
lastInvoke = 0;
|
|
38
|
+
};
|
|
39
|
+
return wrapped;
|
|
40
|
+
}
|
package/lib/index.d.ts
CHANGED
|
@@ -19,4 +19,7 @@ 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 './utils/throttle';
|
|
23
|
+
export * from './utils/disposable';
|
|
24
|
+
export * from './monitor';
|
|
22
25
|
export { Client, Context, Reporter, Shell };
|
package/lib/index.js
CHANGED
|
@@ -134,4 +134,25 @@ Object.keys(_events).forEach(function (key) {
|
|
|
134
134
|
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
135
135
|
if (key in exports && exports[key] === _events[key]) return;
|
|
136
136
|
exports[key] = _events[key];
|
|
137
|
+
});
|
|
138
|
+
var _throttle = require("./utils/throttle");
|
|
139
|
+
Object.keys(_throttle).forEach(function (key) {
|
|
140
|
+
if (key === "default" || key === "__esModule") return;
|
|
141
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
142
|
+
if (key in exports && exports[key] === _throttle[key]) return;
|
|
143
|
+
exports[key] = _throttle[key];
|
|
144
|
+
});
|
|
145
|
+
var _disposable = require("./utils/disposable");
|
|
146
|
+
Object.keys(_disposable).forEach(function (key) {
|
|
147
|
+
if (key === "default" || key === "__esModule") return;
|
|
148
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
149
|
+
if (key in exports && exports[key] === _disposable[key]) return;
|
|
150
|
+
exports[key] = _disposable[key];
|
|
151
|
+
});
|
|
152
|
+
var _monitor = require("./monitor");
|
|
153
|
+
Object.keys(_monitor).forEach(function (key) {
|
|
154
|
+
if (key === "default" || key === "__esModule") return;
|
|
155
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
156
|
+
if (key in exports && exports[key] === _monitor[key]) return;
|
|
157
|
+
exports[key] = _monitor[key];
|
|
137
158
|
});
|