@arms/rum-core 0.1.6 → 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 +2 -0
- package/es/index.js +2 -0
- package/es/model/client.d.ts +3 -3
- package/es/model/client.js +5 -5
- package/es/model/reporter.d.ts +30 -7
- package/es/model/reporter.js +80 -25
- package/es/model/shell.d.ts +4 -4
- package/es/model/shell.js +13 -10
- package/es/types/client.d.ts +2 -2
- 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/disposable.d.ts +12 -0
- package/es/utils/disposable.js +20 -0
- package/es/utils/throttle.d.ts +14 -0
- package/es/utils/throttle.js +40 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +14 -0
- package/lib/model/client.d.ts +3 -3
- package/lib/model/client.js +4 -4
- package/lib/model/reporter.d.ts +30 -7
- package/lib/model/reporter.js +77 -22
- package/lib/model/shell.d.ts +4 -4
- package/lib/model/shell.js +11 -8
- package/lib/types/client.d.ts +2 -2
- 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/disposable.d.ts +12 -0
- package/lib/utils/disposable.js +24 -0
- package/lib/utils/throttle.d.ts +14 -0
- package/lib/utils/throttle.js +44 -0
- package/package.json +1 -1
package/es/index.d.ts
CHANGED
|
@@ -19,5 +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';
|
|
22
24
|
export * from './monitor';
|
|
23
25
|
export { Client, Context, Reporter, Shell };
|
package/es/index.js
CHANGED
|
@@ -19,5 +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';
|
|
22
24
|
export * from './monitor';
|
|
23
25
|
export { Client, Context, Reporter, Shell };
|
package/es/model/client.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IClient, IConfiguration, IContext, IRumSession } from '../types/client';
|
|
2
|
-
import { IConfigManager } from
|
|
3
|
-
import { RumEvent } from '../types/rum-event';
|
|
2
|
+
import { IConfigManager } from '../types/config';
|
|
3
|
+
import { RumEvent, SendEventOptions } 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';
|
|
@@ -12,7 +12,7 @@ declare class Client implements IClient {
|
|
|
12
12
|
private reporter;
|
|
13
13
|
private ctx;
|
|
14
14
|
init(config: IConfiguration, rumSession?: IRumSession, configManager?: IConfigManager, monitorReporter?: IMonitorReporter): void;
|
|
15
|
-
sendEvent: (payload: RumEvent) => void;
|
|
15
|
+
sendEvent: (payload: RumEvent, options?: SendEventOptions) => void;
|
|
16
16
|
setContext(ctx: IContext): void;
|
|
17
17
|
getContext(): IContext;
|
|
18
18
|
useCollectors(collectors: ICollector[]): void;
|
package/es/model/client.js
CHANGED
|
@@ -5,7 +5,7 @@ import { EventType } from '../types/client';
|
|
|
5
5
|
import { EventEmitter } from '../utils/events';
|
|
6
6
|
import { Telemetry } from '../monitor/telemetry';
|
|
7
7
|
import Context from './context';
|
|
8
|
-
import { isFunction } from
|
|
8
|
+
import { isFunction } from '../utils/is';
|
|
9
9
|
var Client = /*#__PURE__*/function () {
|
|
10
10
|
function Client() {
|
|
11
11
|
var _this = this;
|
|
@@ -14,8 +14,8 @@ var Client = /*#__PURE__*/function () {
|
|
|
14
14
|
this.processors = void 0;
|
|
15
15
|
this.reporter = void 0;
|
|
16
16
|
this.ctx = void 0;
|
|
17
|
-
this.sendEvent = function (payload) {
|
|
18
|
-
_this.emitter.emit(EventType.collect, payload);
|
|
17
|
+
this.sendEvent = function (payload, options) {
|
|
18
|
+
_this.emitter.emit(EventType.collect, payload, options);
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
21
|
var _proto = Client.prototype;
|
|
@@ -56,7 +56,7 @@ var Client = /*#__PURE__*/function () {
|
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
// collector 收集数据统一 push 到各匹配 processor
|
|
59
|
-
this.emitter.on(EventType.collect, function (payload) {
|
|
59
|
+
this.emitter.on(EventType.collect, function (payload, options) {
|
|
60
60
|
ctx.setRumEvent(payload);
|
|
61
61
|
for (var _iterator = _createForOfIteratorHelperLoose(processors), _step; !(_step = _iterator()).done;) {
|
|
62
62
|
var processor = _step.value;
|
|
@@ -73,7 +73,7 @@ var Client = /*#__PURE__*/function () {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
-
reporter.report(ctx);
|
|
76
|
+
reporter.report(ctx, options);
|
|
77
77
|
});
|
|
78
78
|
collectors.forEach(function (collector) {
|
|
79
79
|
collector.setup(ctx, _this2.sendEvent);
|
package/es/model/reporter.d.ts
CHANGED
|
@@ -1,23 +1,46 @@
|
|
|
1
1
|
import { IContext } from '../types/client';
|
|
2
|
-
import { RumEvent, IViewData, RumEventBundle } from '../types/rum-event';
|
|
2
|
+
import { RumEvent, IViewData, RumEventBundle, SendEventOptions } from '../types/rum-event';
|
|
3
|
+
/**
|
|
4
|
+
* 抽象上报器,负责事件排队、批量打包与发送。
|
|
5
|
+
*
|
|
6
|
+
* 上报模式(通过 SendEventOptions 控制):
|
|
7
|
+
* - 默认:事件进入队列,等待定时器或队列满后批量 flush
|
|
8
|
+
* - immediate:事件进入队列后立即 flush 整个队列
|
|
9
|
+
* - single:事件不进队列,独立打包立即上报
|
|
10
|
+
*/
|
|
3
11
|
export default abstract class Reporter {
|
|
4
12
|
name: string;
|
|
5
|
-
/**
|
|
6
|
-
* 新上报事件优先检测队列是否超过 50 条,如果超过立即 report。
|
|
7
|
-
* 如果没超过则检测 FlushTime 内有无新上报事件,如果有新事件,重置 timer,无则 report
|
|
8
|
-
*/
|
|
9
13
|
protected eventQueue: RumEvent[];
|
|
10
14
|
protected ctx: IContext;
|
|
11
15
|
private timer;
|
|
12
16
|
private _init;
|
|
13
17
|
getReportCfg(): import("../types/client").IReportConfig;
|
|
14
|
-
|
|
18
|
+
/**
|
|
19
|
+
* 上报入口,根据 options 决定上报策略:
|
|
20
|
+
* - single: 当前事件独立打包立即发送,不影响队列
|
|
21
|
+
* - immediate: 当前事件入队后立即 flush 整个队列
|
|
22
|
+
* - 默认: 当前事件入队,等待定时器或队列满后批量 flush
|
|
23
|
+
*/
|
|
24
|
+
report(ctx: IContext, options?: SendEventOptions): void;
|
|
25
|
+
/**
|
|
26
|
+
* 当前事件独立打包上报,不进入批量队列,不重置队列定时器
|
|
27
|
+
*/
|
|
28
|
+
private flushSingleEvent;
|
|
15
29
|
private pushToQueue;
|
|
16
30
|
/**
|
|
17
31
|
* eventQueue 提取最新 View 作为公共 View,event 中不同 View Event 保留 View id
|
|
18
32
|
*/
|
|
19
33
|
protected flushEventQueue(): void;
|
|
20
|
-
|
|
34
|
+
/**
|
|
35
|
+
* 按 session_id 分组事件并分别打包上报:
|
|
36
|
+
* - 当前 session 的事件统一打包
|
|
37
|
+
* - 非当前 session 的事件按各自 session_id 单独打包
|
|
38
|
+
*/
|
|
39
|
+
protected dispatchEvents(ctx: IContext, events: RumEvent[], view: IViewData): void;
|
|
40
|
+
/**
|
|
41
|
+
* 构建 bundle 并发送请求
|
|
42
|
+
*/
|
|
43
|
+
private buildAndSend;
|
|
21
44
|
private tryRequest;
|
|
22
45
|
/**
|
|
23
46
|
* 接口请求由各平台 sdk reporter 实现
|
package/es/model/reporter.js
CHANGED
|
@@ -4,19 +4,24 @@ import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
|
4
4
|
import { logger } from '../monitor/logger';
|
|
5
5
|
import { RumEventType } from '../types/rum-event';
|
|
6
6
|
import { getErrorID } from '../utils/exception';
|
|
7
|
-
import { isNumber, isObject, isString } from
|
|
8
|
-
import { verifyProperties } from
|
|
9
|
-
import { getUrlParams } from
|
|
7
|
+
import { isNumber, isObject, isString } from '../utils/is';
|
|
8
|
+
import { verifyProperties } from '../utils/verify';
|
|
9
|
+
import { getUrlParams } from '../utils/url';
|
|
10
10
|
var FLUSH_TIME = 3000;
|
|
11
11
|
var MAX_EVENT_COUNT = 20;
|
|
12
12
|
var attrs = ['app', 'user', 'device', 'os', 'geo', 'isp', 'net', 'properties'];
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 抽象上报器,负责事件排队、批量打包与发送。
|
|
16
|
+
*
|
|
17
|
+
* 上报模式(通过 SendEventOptions 控制):
|
|
18
|
+
* - 默认:事件进入队列,等待定时器或队列满后批量 flush
|
|
19
|
+
* - immediate:事件进入队列后立即 flush 整个队列
|
|
20
|
+
* - single:事件不进队列,独立打包立即上报
|
|
21
|
+
*/
|
|
13
22
|
var Reporter = /*#__PURE__*/function () {
|
|
14
23
|
function Reporter() {
|
|
15
24
|
this.name = 'reporter';
|
|
16
|
-
/**
|
|
17
|
-
* 新上报事件优先检测队列是否超过 50 条,如果超过立即 report。
|
|
18
|
-
* 如果没超过则检测 FlushTime 内有无新上报事件,如果有新事件,重置 timer,无则 report
|
|
19
|
-
*/
|
|
20
25
|
this.eventQueue = [];
|
|
21
26
|
this.ctx = void 0;
|
|
22
27
|
this.timer = void 0;
|
|
@@ -35,25 +40,54 @@ var Reporter = /*#__PURE__*/function () {
|
|
|
35
40
|
cfg.maxEventCount = MAX_EVENT_COUNT;
|
|
36
41
|
}
|
|
37
42
|
return cfg;
|
|
38
|
-
}
|
|
39
|
-
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 上报入口,根据 options 决定上报策略:
|
|
47
|
+
* - single: 当前事件独立打包立即发送,不影响队列
|
|
48
|
+
* - immediate: 当前事件入队后立即 flush 整个队列
|
|
49
|
+
* - 默认: 当前事件入队,等待定时器或队列满后批量 flush
|
|
50
|
+
*/;
|
|
51
|
+
_proto.report = function report(ctx, options) {
|
|
40
52
|
var _this = this;
|
|
41
53
|
this.ctx = ctx;
|
|
42
54
|
if (!this._init) {
|
|
43
55
|
this.init(ctx);
|
|
44
56
|
this._init = true;
|
|
45
57
|
}
|
|
58
|
+
|
|
59
|
+
// single 优先级最高:当前事件单独上报,不影响队列
|
|
60
|
+
if (options && options.single) {
|
|
61
|
+
this.flushSingleEvent(ctx);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
46
64
|
clearTimeout(this.timer);
|
|
47
65
|
this.pushToQueue();
|
|
48
66
|
var reportConfig = this.getReportCfg();
|
|
49
|
-
|
|
50
|
-
if (this.eventQueue.length >= reportConfig.maxEventCount) {
|
|
67
|
+
if (options && options.immediate || this.eventQueue.length >= reportConfig.maxEventCount) {
|
|
51
68
|
this.flushEventQueue();
|
|
52
69
|
} else {
|
|
53
70
|
this.timer = setTimeout(function () {
|
|
54
71
|
_this.flushEventQueue();
|
|
55
72
|
}, reportConfig.flushTime);
|
|
56
73
|
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 当前事件独立打包上报,不进入批量队列,不重置队列定时器
|
|
78
|
+
*/;
|
|
79
|
+
_proto.flushSingleEvent = function flushSingleEvent(ctx) {
|
|
80
|
+
var _event$view;
|
|
81
|
+
var session = ctx.session;
|
|
82
|
+
var sampled = session ? session.getSampled() : true;
|
|
83
|
+
if (!sampled) return;
|
|
84
|
+
var event = ctx.getRumEvent();
|
|
85
|
+
var views = ctx.getViews();
|
|
86
|
+
var curView = views[views.length - 1];
|
|
87
|
+
if (((_event$view = event.view) === null || _event$view === void 0 ? void 0 : _event$view.id) === curView.id) {
|
|
88
|
+
delete event.view;
|
|
89
|
+
}
|
|
90
|
+
this.dispatchEvents(ctx, [event], curView);
|
|
57
91
|
};
|
|
58
92
|
_proto.pushToQueue = function pushToQueue() {
|
|
59
93
|
var ctx = this.ctx,
|
|
@@ -116,8 +150,8 @@ var Reporter = /*#__PURE__*/function () {
|
|
|
116
150
|
views.forEach(function (view) {
|
|
117
151
|
if (view.id === curView.id) {
|
|
118
152
|
var events = eventQueue.filter(function (event) {
|
|
119
|
-
var _event$
|
|
120
|
-
return ((_event$
|
|
153
|
+
var _event$view2;
|
|
154
|
+
return ((_event$view2 = event.view) === null || _event$view2 === void 0 ? void 0 : _event$view2.id) === view.id;
|
|
121
155
|
});
|
|
122
156
|
events.forEach(function (event) {
|
|
123
157
|
delete event.view;
|
|
@@ -126,28 +160,49 @@ var Reporter = /*#__PURE__*/function () {
|
|
|
126
160
|
});
|
|
127
161
|
var session = ctx.session;
|
|
128
162
|
var sampled = session ? session.getSampled() : true;
|
|
129
|
-
sampled && this.
|
|
163
|
+
sampled && this.dispatchEvents(ctx, eventQueue, curView);
|
|
130
164
|
this.eventQueue = [];
|
|
131
|
-
}
|
|
132
|
-
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* 按 session_id 分组事件并分别打包上报:
|
|
169
|
+
* - 当前 session 的事件统一打包
|
|
170
|
+
* - 非当前 session 的事件按各自 session_id 单独打包
|
|
171
|
+
*/;
|
|
172
|
+
_proto.dispatchEvents = function dispatchEvents(ctx, events, view) {
|
|
133
173
|
var config = ctx.getConfig();
|
|
134
174
|
var session = ctx.session;
|
|
135
175
|
var sessionId = session.getSessionId();
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
// delete event.session_id;
|
|
139
|
-
// }
|
|
140
|
-
// });
|
|
176
|
+
var currentSessionEvents = [];
|
|
177
|
+
var otherSessionEventsMap = {};
|
|
141
178
|
for (var i = 0; i < events.length; i++) {
|
|
142
179
|
var e = events[i];
|
|
143
|
-
if (e.session_id === sessionId) {
|
|
180
|
+
if (!e.session_id || e.session_id === sessionId) {
|
|
144
181
|
delete e.session_id;
|
|
182
|
+
currentSessionEvents.push(e);
|
|
145
183
|
} else {
|
|
146
|
-
|
|
147
|
-
|
|
184
|
+
var sid = e.session_id;
|
|
185
|
+
if (!otherSessionEventsMap[sid]) {
|
|
186
|
+
otherSessionEventsMap[sid] = [];
|
|
187
|
+
}
|
|
188
|
+
delete e.session_id;
|
|
189
|
+
otherSessionEventsMap[sid].push(e);
|
|
148
190
|
}
|
|
149
191
|
}
|
|
150
|
-
if (
|
|
192
|
+
if (currentSessionEvents.length > 0) {
|
|
193
|
+
this.buildAndSend(ctx, config, session, sessionId, currentSessionEvents, view);
|
|
194
|
+
}
|
|
195
|
+
var otherSessionIds = Object.keys(otherSessionEventsMap);
|
|
196
|
+
for (var _i = 0; _i < otherSessionIds.length; _i++) {
|
|
197
|
+
var _sid = otherSessionIds[_i];
|
|
198
|
+
this.buildAndSend(ctx, config, session, _sid, otherSessionEventsMap[_sid], view);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* 构建 bundle 并发送请求
|
|
204
|
+
*/;
|
|
205
|
+
_proto.buildAndSend = function buildAndSend(ctx, config, session, sessionId, events, view) {
|
|
151
206
|
var extend = getUrlParams(config.endpoint);
|
|
152
207
|
var bundle = _extends({
|
|
153
208
|
app: {
|
package/es/model/shell.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { IClient, IConfiguration } from
|
|
2
|
-
import { RumCustomEvent, RumEvent, RumExceptionEvent, RumResourceEvent, RumViewEvent } from
|
|
3
|
-
import { IShell } from
|
|
1
|
+
import { IClient, IConfiguration } from '../types/client';
|
|
2
|
+
import { RumCustomEvent, RumEvent, RumExceptionEvent, RumResourceEvent, RumViewEvent, SendEventOptions } from '../types/rum-event';
|
|
3
|
+
import { IShell } from '../types/shell';
|
|
4
4
|
export default abstract class Shell implements IShell {
|
|
5
5
|
client: IClient;
|
|
6
6
|
constructor(config?: IConfiguration);
|
|
@@ -8,7 +8,7 @@ export default abstract class Shell implements IShell {
|
|
|
8
8
|
* 初始化
|
|
9
9
|
*/
|
|
10
10
|
abstract init(configuration: IConfiguration): Promise<Shell> | Shell;
|
|
11
|
-
sendEvent(payload: RumEvent): void;
|
|
11
|
+
sendEvent(payload: RumEvent, options?: SendEventOptions): void;
|
|
12
12
|
/**
|
|
13
13
|
* get config
|
|
14
14
|
*/
|
package/es/model/shell.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
-
import { RumEventType } from
|
|
2
|
+
import { RumEventType } from '../types/rum-event';
|
|
3
3
|
import Client from '../model/client';
|
|
4
|
-
import { isNumber, isObject } from
|
|
4
|
+
import { isNumber, isObject } from '../utils/is';
|
|
5
5
|
var Shell = /*#__PURE__*/function () {
|
|
6
6
|
function Shell(config) {
|
|
7
7
|
// private callbacks: Function[] = [];
|
|
@@ -35,9 +35,9 @@ var Shell = /*#__PURE__*/function () {
|
|
|
35
35
|
* 初始化
|
|
36
36
|
*/
|
|
37
37
|
var _proto = Shell.prototype;
|
|
38
|
-
_proto.sendEvent = function sendEvent(payload) {
|
|
38
|
+
_proto.sendEvent = function sendEvent(payload, options) {
|
|
39
39
|
if (this.client) {
|
|
40
|
-
this.client.sendEvent(payload);
|
|
40
|
+
this.client.sendEvent(payload, options);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -64,10 +64,11 @@ var Shell = /*#__PURE__*/function () {
|
|
|
64
64
|
event_type: RumEventType.CUSTOM
|
|
65
65
|
});
|
|
66
66
|
this.sendEvent(data);
|
|
67
|
-
}
|
|
67
|
+
}
|
|
68
|
+
|
|
68
69
|
/**
|
|
69
70
|
* 自定义视图上报
|
|
70
|
-
|
|
71
|
+
*/;
|
|
71
72
|
_proto.sendView = function sendView(payload) {
|
|
72
73
|
if (!isObject(payload)) {
|
|
73
74
|
return;
|
|
@@ -89,10 +90,11 @@ var Shell = /*#__PURE__*/function () {
|
|
|
89
90
|
event_type: RumEventType.VIEW
|
|
90
91
|
});
|
|
91
92
|
this.sendEvent(data);
|
|
92
|
-
}
|
|
93
|
+
}
|
|
94
|
+
|
|
93
95
|
/**
|
|
94
96
|
* 自定义异常上报
|
|
95
|
-
|
|
97
|
+
*/;
|
|
96
98
|
_proto.sendException = function sendException(payload) {
|
|
97
99
|
if (!payload.name || !payload.message) {
|
|
98
100
|
return;
|
|
@@ -111,10 +113,11 @@ var Shell = /*#__PURE__*/function () {
|
|
|
111
113
|
source: 'custom'
|
|
112
114
|
});
|
|
113
115
|
this.sendEvent(data);
|
|
114
|
-
}
|
|
116
|
+
}
|
|
117
|
+
|
|
115
118
|
/**
|
|
116
119
|
* 自定义资源上报
|
|
117
|
-
|
|
120
|
+
*/;
|
|
118
121
|
_proto.sendResource = function sendResource(payload) {
|
|
119
122
|
if (!payload.name || !payload.type || !isNumber(payload.duration)) {
|
|
120
123
|
return;
|
package/es/types/client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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';
|
|
@@ -119,7 +119,7 @@ export interface IClient {
|
|
|
119
119
|
/**
|
|
120
120
|
* 业务自定义上传数据
|
|
121
121
|
*/
|
|
122
|
-
sendEvent(payload: RumEvent): void;
|
|
122
|
+
sendEvent(payload: RumEvent, options?: SendEventOptions): void;
|
|
123
123
|
/**
|
|
124
124
|
* 修改运行时上下文
|
|
125
125
|
*/
|
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
|
*/
|
|
@@ -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
|
+
}
|
|
@@ -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,5 +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';
|
|
22
24
|
export * from './monitor';
|
|
23
25
|
export { Client, Context, Reporter, Shell };
|
package/lib/index.js
CHANGED
|
@@ -135,6 +135,20 @@ Object.keys(_events).forEach(function (key) {
|
|
|
135
135
|
if (key in exports && exports[key] === _events[key]) return;
|
|
136
136
|
exports[key] = _events[key];
|
|
137
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
|
+
});
|
|
138
152
|
var _monitor = require("./monitor");
|
|
139
153
|
Object.keys(_monitor).forEach(function (key) {
|
|
140
154
|
if (key === "default" || key === "__esModule") return;
|
package/lib/model/client.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IClient, IConfiguration, IContext, IRumSession } from '../types/client';
|
|
2
|
-
import { IConfigManager } from
|
|
3
|
-
import { RumEvent } from '../types/rum-event';
|
|
2
|
+
import { IConfigManager } from '../types/config';
|
|
3
|
+
import { RumEvent, SendEventOptions } 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';
|
|
@@ -12,7 +12,7 @@ declare class Client implements IClient {
|
|
|
12
12
|
private reporter;
|
|
13
13
|
private ctx;
|
|
14
14
|
init(config: IConfiguration, rumSession?: IRumSession, configManager?: IConfigManager, monitorReporter?: IMonitorReporter): void;
|
|
15
|
-
sendEvent: (payload: RumEvent) => void;
|
|
15
|
+
sendEvent: (payload: RumEvent, options?: SendEventOptions) => void;
|
|
16
16
|
setContext(ctx: IContext): void;
|
|
17
17
|
getContext(): IContext;
|
|
18
18
|
useCollectors(collectors: ICollector[]): void;
|
package/lib/model/client.js
CHANGED
|
@@ -19,8 +19,8 @@ var Client = /*#__PURE__*/function () {
|
|
|
19
19
|
this.processors = void 0;
|
|
20
20
|
this.reporter = void 0;
|
|
21
21
|
this.ctx = void 0;
|
|
22
|
-
this.sendEvent = function (payload) {
|
|
23
|
-
_this.emitter.emit(_client.EventType.collect, payload);
|
|
22
|
+
this.sendEvent = function (payload, options) {
|
|
23
|
+
_this.emitter.emit(_client.EventType.collect, payload, options);
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
var _proto = Client.prototype;
|
|
@@ -61,7 +61,7 @@ var Client = /*#__PURE__*/function () {
|
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
// collector 收集数据统一 push 到各匹配 processor
|
|
64
|
-
this.emitter.on(_client.EventType.collect, function (payload) {
|
|
64
|
+
this.emitter.on(_client.EventType.collect, function (payload, options) {
|
|
65
65
|
ctx.setRumEvent(payload);
|
|
66
66
|
for (var _iterator = _createForOfIteratorHelperLoose(processors), _step; !(_step = _iterator()).done;) {
|
|
67
67
|
var processor = _step.value;
|
|
@@ -78,7 +78,7 @@ var Client = /*#__PURE__*/function () {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
-
reporter.report(ctx);
|
|
81
|
+
reporter.report(ctx, options);
|
|
82
82
|
});
|
|
83
83
|
collectors.forEach(function (collector) {
|
|
84
84
|
collector.setup(ctx, _this2.sendEvent);
|
package/lib/model/reporter.d.ts
CHANGED
|
@@ -1,23 +1,46 @@
|
|
|
1
1
|
import { IContext } from '../types/client';
|
|
2
|
-
import { RumEvent, IViewData, RumEventBundle } from '../types/rum-event';
|
|
2
|
+
import { RumEvent, IViewData, RumEventBundle, SendEventOptions } from '../types/rum-event';
|
|
3
|
+
/**
|
|
4
|
+
* 抽象上报器,负责事件排队、批量打包与发送。
|
|
5
|
+
*
|
|
6
|
+
* 上报模式(通过 SendEventOptions 控制):
|
|
7
|
+
* - 默认:事件进入队列,等待定时器或队列满后批量 flush
|
|
8
|
+
* - immediate:事件进入队列后立即 flush 整个队列
|
|
9
|
+
* - single:事件不进队列,独立打包立即上报
|
|
10
|
+
*/
|
|
3
11
|
export default abstract class Reporter {
|
|
4
12
|
name: string;
|
|
5
|
-
/**
|
|
6
|
-
* 新上报事件优先检测队列是否超过 50 条,如果超过立即 report。
|
|
7
|
-
* 如果没超过则检测 FlushTime 内有无新上报事件,如果有新事件,重置 timer,无则 report
|
|
8
|
-
*/
|
|
9
13
|
protected eventQueue: RumEvent[];
|
|
10
14
|
protected ctx: IContext;
|
|
11
15
|
private timer;
|
|
12
16
|
private _init;
|
|
13
17
|
getReportCfg(): import("../types/client").IReportConfig;
|
|
14
|
-
|
|
18
|
+
/**
|
|
19
|
+
* 上报入口,根据 options 决定上报策略:
|
|
20
|
+
* - single: 当前事件独立打包立即发送,不影响队列
|
|
21
|
+
* - immediate: 当前事件入队后立即 flush 整个队列
|
|
22
|
+
* - 默认: 当前事件入队,等待定时器或队列满后批量 flush
|
|
23
|
+
*/
|
|
24
|
+
report(ctx: IContext, options?: SendEventOptions): void;
|
|
25
|
+
/**
|
|
26
|
+
* 当前事件独立打包上报,不进入批量队列,不重置队列定时器
|
|
27
|
+
*/
|
|
28
|
+
private flushSingleEvent;
|
|
15
29
|
private pushToQueue;
|
|
16
30
|
/**
|
|
17
31
|
* eventQueue 提取最新 View 作为公共 View,event 中不同 View Event 保留 View id
|
|
18
32
|
*/
|
|
19
33
|
protected flushEventQueue(): void;
|
|
20
|
-
|
|
34
|
+
/**
|
|
35
|
+
* 按 session_id 分组事件并分别打包上报:
|
|
36
|
+
* - 当前 session 的事件统一打包
|
|
37
|
+
* - 非当前 session 的事件按各自 session_id 单独打包
|
|
38
|
+
*/
|
|
39
|
+
protected dispatchEvents(ctx: IContext, events: RumEvent[], view: IViewData): void;
|
|
40
|
+
/**
|
|
41
|
+
* 构建 bundle 并发送请求
|
|
42
|
+
*/
|
|
43
|
+
private buildAndSend;
|
|
21
44
|
private tryRequest;
|
|
22
45
|
/**
|
|
23
46
|
* 接口请求由各平台 sdk reporter 实现
|
package/lib/model/reporter.js
CHANGED
|
@@ -15,13 +15,18 @@ var _url = require("../utils/url");
|
|
|
15
15
|
var FLUSH_TIME = 3000;
|
|
16
16
|
var MAX_EVENT_COUNT = 20;
|
|
17
17
|
var attrs = ['app', 'user', 'device', 'os', 'geo', 'isp', 'net', 'properties'];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 抽象上报器,负责事件排队、批量打包与发送。
|
|
21
|
+
*
|
|
22
|
+
* 上报模式(通过 SendEventOptions 控制):
|
|
23
|
+
* - 默认:事件进入队列,等待定时器或队列满后批量 flush
|
|
24
|
+
* - immediate:事件进入队列后立即 flush 整个队列
|
|
25
|
+
* - single:事件不进队列,独立打包立即上报
|
|
26
|
+
*/
|
|
18
27
|
var Reporter = exports["default"] = /*#__PURE__*/function () {
|
|
19
28
|
function Reporter() {
|
|
20
29
|
this.name = 'reporter';
|
|
21
|
-
/**
|
|
22
|
-
* 新上报事件优先检测队列是否超过 50 条,如果超过立即 report。
|
|
23
|
-
* 如果没超过则检测 FlushTime 内有无新上报事件,如果有新事件,重置 timer,无则 report
|
|
24
|
-
*/
|
|
25
30
|
this.eventQueue = [];
|
|
26
31
|
this.ctx = void 0;
|
|
27
32
|
this.timer = void 0;
|
|
@@ -40,25 +45,54 @@ var Reporter = exports["default"] = /*#__PURE__*/function () {
|
|
|
40
45
|
cfg.maxEventCount = MAX_EVENT_COUNT;
|
|
41
46
|
}
|
|
42
47
|
return cfg;
|
|
43
|
-
}
|
|
44
|
-
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 上报入口,根据 options 决定上报策略:
|
|
52
|
+
* - single: 当前事件独立打包立即发送,不影响队列
|
|
53
|
+
* - immediate: 当前事件入队后立即 flush 整个队列
|
|
54
|
+
* - 默认: 当前事件入队,等待定时器或队列满后批量 flush
|
|
55
|
+
*/;
|
|
56
|
+
_proto.report = function report(ctx, options) {
|
|
45
57
|
var _this = this;
|
|
46
58
|
this.ctx = ctx;
|
|
47
59
|
if (!this._init) {
|
|
48
60
|
this.init(ctx);
|
|
49
61
|
this._init = true;
|
|
50
62
|
}
|
|
63
|
+
|
|
64
|
+
// single 优先级最高:当前事件单独上报,不影响队列
|
|
65
|
+
if (options && options.single) {
|
|
66
|
+
this.flushSingleEvent(ctx);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
51
69
|
clearTimeout(this.timer);
|
|
52
70
|
this.pushToQueue();
|
|
53
71
|
var reportConfig = this.getReportCfg();
|
|
54
|
-
|
|
55
|
-
if (this.eventQueue.length >= reportConfig.maxEventCount) {
|
|
72
|
+
if (options && options.immediate || this.eventQueue.length >= reportConfig.maxEventCount) {
|
|
56
73
|
this.flushEventQueue();
|
|
57
74
|
} else {
|
|
58
75
|
this.timer = setTimeout(function () {
|
|
59
76
|
_this.flushEventQueue();
|
|
60
77
|
}, reportConfig.flushTime);
|
|
61
78
|
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* 当前事件独立打包上报,不进入批量队列,不重置队列定时器
|
|
83
|
+
*/;
|
|
84
|
+
_proto.flushSingleEvent = function flushSingleEvent(ctx) {
|
|
85
|
+
var _event$view;
|
|
86
|
+
var session = ctx.session;
|
|
87
|
+
var sampled = session ? session.getSampled() : true;
|
|
88
|
+
if (!sampled) return;
|
|
89
|
+
var event = ctx.getRumEvent();
|
|
90
|
+
var views = ctx.getViews();
|
|
91
|
+
var curView = views[views.length - 1];
|
|
92
|
+
if (((_event$view = event.view) === null || _event$view === void 0 ? void 0 : _event$view.id) === curView.id) {
|
|
93
|
+
delete event.view;
|
|
94
|
+
}
|
|
95
|
+
this.dispatchEvents(ctx, [event], curView);
|
|
62
96
|
};
|
|
63
97
|
_proto.pushToQueue = function pushToQueue() {
|
|
64
98
|
var ctx = this.ctx,
|
|
@@ -121,8 +155,8 @@ var Reporter = exports["default"] = /*#__PURE__*/function () {
|
|
|
121
155
|
views.forEach(function (view) {
|
|
122
156
|
if (view.id === curView.id) {
|
|
123
157
|
var events = eventQueue.filter(function (event) {
|
|
124
|
-
var _event$
|
|
125
|
-
return ((_event$
|
|
158
|
+
var _event$view2;
|
|
159
|
+
return ((_event$view2 = event.view) === null || _event$view2 === void 0 ? void 0 : _event$view2.id) === view.id;
|
|
126
160
|
});
|
|
127
161
|
events.forEach(function (event) {
|
|
128
162
|
delete event.view;
|
|
@@ -131,28 +165,49 @@ var Reporter = exports["default"] = /*#__PURE__*/function () {
|
|
|
131
165
|
});
|
|
132
166
|
var session = ctx.session;
|
|
133
167
|
var sampled = session ? session.getSampled() : true;
|
|
134
|
-
sampled && this.
|
|
168
|
+
sampled && this.dispatchEvents(ctx, eventQueue, curView);
|
|
135
169
|
this.eventQueue = [];
|
|
136
|
-
}
|
|
137
|
-
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* 按 session_id 分组事件并分别打包上报:
|
|
174
|
+
* - 当前 session 的事件统一打包
|
|
175
|
+
* - 非当前 session 的事件按各自 session_id 单独打包
|
|
176
|
+
*/;
|
|
177
|
+
_proto.dispatchEvents = function dispatchEvents(ctx, events, view) {
|
|
138
178
|
var config = ctx.getConfig();
|
|
139
179
|
var session = ctx.session;
|
|
140
180
|
var sessionId = session.getSessionId();
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
// delete event.session_id;
|
|
144
|
-
// }
|
|
145
|
-
// });
|
|
181
|
+
var currentSessionEvents = [];
|
|
182
|
+
var otherSessionEventsMap = {};
|
|
146
183
|
for (var i = 0; i < events.length; i++) {
|
|
147
184
|
var e = events[i];
|
|
148
|
-
if (e.session_id === sessionId) {
|
|
185
|
+
if (!e.session_id || e.session_id === sessionId) {
|
|
149
186
|
delete e.session_id;
|
|
187
|
+
currentSessionEvents.push(e);
|
|
150
188
|
} else {
|
|
151
|
-
|
|
152
|
-
|
|
189
|
+
var sid = e.session_id;
|
|
190
|
+
if (!otherSessionEventsMap[sid]) {
|
|
191
|
+
otherSessionEventsMap[sid] = [];
|
|
192
|
+
}
|
|
193
|
+
delete e.session_id;
|
|
194
|
+
otherSessionEventsMap[sid].push(e);
|
|
153
195
|
}
|
|
154
196
|
}
|
|
155
|
-
if (
|
|
197
|
+
if (currentSessionEvents.length > 0) {
|
|
198
|
+
this.buildAndSend(ctx, config, session, sessionId, currentSessionEvents, view);
|
|
199
|
+
}
|
|
200
|
+
var otherSessionIds = Object.keys(otherSessionEventsMap);
|
|
201
|
+
for (var _i = 0; _i < otherSessionIds.length; _i++) {
|
|
202
|
+
var _sid = otherSessionIds[_i];
|
|
203
|
+
this.buildAndSend(ctx, config, session, _sid, otherSessionEventsMap[_sid], view);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* 构建 bundle 并发送请求
|
|
209
|
+
*/;
|
|
210
|
+
_proto.buildAndSend = function buildAndSend(ctx, config, session, sessionId, events, view) {
|
|
156
211
|
var extend = (0, _url.getUrlParams)(config.endpoint);
|
|
157
212
|
var bundle = (0, _extends2["default"])({
|
|
158
213
|
app: {
|
package/lib/model/shell.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { IClient, IConfiguration } from
|
|
2
|
-
import { RumCustomEvent, RumEvent, RumExceptionEvent, RumResourceEvent, RumViewEvent } from
|
|
3
|
-
import { IShell } from
|
|
1
|
+
import { IClient, IConfiguration } from '../types/client';
|
|
2
|
+
import { RumCustomEvent, RumEvent, RumExceptionEvent, RumResourceEvent, RumViewEvent, SendEventOptions } from '../types/rum-event';
|
|
3
|
+
import { IShell } from '../types/shell';
|
|
4
4
|
export default abstract class Shell implements IShell {
|
|
5
5
|
client: IClient;
|
|
6
6
|
constructor(config?: IConfiguration);
|
|
@@ -8,7 +8,7 @@ export default abstract class Shell implements IShell {
|
|
|
8
8
|
* 初始化
|
|
9
9
|
*/
|
|
10
10
|
abstract init(configuration: IConfiguration): Promise<Shell> | Shell;
|
|
11
|
-
sendEvent(payload: RumEvent): void;
|
|
11
|
+
sendEvent(payload: RumEvent, options?: SendEventOptions): void;
|
|
12
12
|
/**
|
|
13
13
|
* get config
|
|
14
14
|
*/
|
package/lib/model/shell.js
CHANGED
|
@@ -40,9 +40,9 @@ var Shell = exports["default"] = /*#__PURE__*/function () {
|
|
|
40
40
|
* 初始化
|
|
41
41
|
*/
|
|
42
42
|
var _proto = Shell.prototype;
|
|
43
|
-
_proto.sendEvent = function sendEvent(payload) {
|
|
43
|
+
_proto.sendEvent = function sendEvent(payload, options) {
|
|
44
44
|
if (this.client) {
|
|
45
|
-
this.client.sendEvent(payload);
|
|
45
|
+
this.client.sendEvent(payload, options);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
@@ -69,10 +69,11 @@ var Shell = exports["default"] = /*#__PURE__*/function () {
|
|
|
69
69
|
event_type: _rumEvent.RumEventType.CUSTOM
|
|
70
70
|
});
|
|
71
71
|
this.sendEvent(data);
|
|
72
|
-
}
|
|
72
|
+
}
|
|
73
|
+
|
|
73
74
|
/**
|
|
74
75
|
* 自定义视图上报
|
|
75
|
-
|
|
76
|
+
*/;
|
|
76
77
|
_proto.sendView = function sendView(payload) {
|
|
77
78
|
if (!(0, _is.isObject)(payload)) {
|
|
78
79
|
return;
|
|
@@ -94,10 +95,11 @@ var Shell = exports["default"] = /*#__PURE__*/function () {
|
|
|
94
95
|
event_type: _rumEvent.RumEventType.VIEW
|
|
95
96
|
});
|
|
96
97
|
this.sendEvent(data);
|
|
97
|
-
}
|
|
98
|
+
}
|
|
99
|
+
|
|
98
100
|
/**
|
|
99
101
|
* 自定义异常上报
|
|
100
|
-
|
|
102
|
+
*/;
|
|
101
103
|
_proto.sendException = function sendException(payload) {
|
|
102
104
|
if (!payload.name || !payload.message) {
|
|
103
105
|
return;
|
|
@@ -116,10 +118,11 @@ var Shell = exports["default"] = /*#__PURE__*/function () {
|
|
|
116
118
|
source: 'custom'
|
|
117
119
|
});
|
|
118
120
|
this.sendEvent(data);
|
|
119
|
-
}
|
|
121
|
+
}
|
|
122
|
+
|
|
120
123
|
/**
|
|
121
124
|
* 自定义资源上报
|
|
122
|
-
|
|
125
|
+
*/;
|
|
123
126
|
_proto.sendResource = function sendResource(payload) {
|
|
124
127
|
if (!payload.name || !payload.type || !(0, _is.isNumber)(payload.duration)) {
|
|
125
128
|
return;
|
package/lib/types/client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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';
|
|
@@ -119,7 +119,7 @@ export interface IClient {
|
|
|
119
119
|
/**
|
|
120
120
|
* 业务自定义上传数据
|
|
121
121
|
*/
|
|
122
|
-
sendEvent(payload: RumEvent): void;
|
|
122
|
+
sendEvent(payload: RumEvent, options?: SendEventOptions): void;
|
|
123
123
|
/**
|
|
124
124
|
* 修改运行时上下文
|
|
125
125
|
*/
|
package/lib/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/lib/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/lib/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/lib/types/rum-event.js
CHANGED
|
@@ -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
|
/** 内存信息 */
|
package/lib/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
|
*/
|
|
@@ -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
|
+
}
|
|
@@ -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
|
+
}
|