@arms/rum-core 0.1.2 → 0.1.3

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 CHANGED
@@ -18,4 +18,5 @@ export * from './utils/match';
18
18
  export * from './utils/trace';
19
19
  export * from './utils/verify';
20
20
  export * from './utils/url';
21
+ export * from './utils/events';
21
22
  export { Client, Context, Reporter, Shell };
package/es/index.js CHANGED
@@ -18,4 +18,5 @@ export * from './utils/match';
18
18
  export * from './utils/trace';
19
19
  export * from './utils/verify';
20
20
  export * from './utils/url';
21
+ export * from './utils/events';
21
22
  export { Client, Context, Reporter, Shell };
@@ -32,38 +32,38 @@ export var ConfigManager = /*#__PURE__*/function () {
32
32
  var _init = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(config) {
33
33
  var _this = this;
34
34
  var remoteConfig, cacheConfig, asyncConfigPromise;
35
- return _regeneratorRuntime.wrap(function _callee$(_context) {
35
+ return _regeneratorRuntime.wrap(function (_context) {
36
36
  while (1) switch (_context.prev = _context.next) {
37
37
  case 0:
38
38
  if (!this.initialized) {
39
- _context.next = 2;
39
+ _context.next = 1;
40
40
  break;
41
41
  }
42
42
  return _context.abrupt("return");
43
- case 2:
43
+ case 1:
44
44
  this.currentConfig = _extends({}, config);
45
45
  this.initialized = true;
46
46
  remoteConfig = parseRemoteConfig(config);
47
47
  this.currentConfig.remoteConfig = remoteConfig;
48
48
  if (remoteConfig.enable) {
49
- _context.next = 8;
49
+ _context.next = 2;
50
50
  break;
51
51
  }
52
52
  return _context.abrupt("return");
53
- case 8:
54
- _context.next = 10;
53
+ case 2:
54
+ _context.next = 3;
55
55
  return this.getCacheConfig();
56
- case 10:
56
+ case 3:
57
57
  cacheConfig = _context.sent;
58
58
  if (cacheConfig && cacheConfig.content) {
59
59
  this.currentConfig = this.mergeRemoteCfg(cacheConfig.content);
60
60
  }
61
61
  if (!this.isCacheValid(cacheConfig, remoteConfig.cacheTimeout)) {
62
- _context.next = 14;
62
+ _context.next = 4;
63
63
  break;
64
64
  }
65
65
  return _context.abrupt("return");
66
- case 14:
66
+ case 4:
67
67
  asyncConfigPromise = this.fetchRemoteCfg(this.currentConfig).then(function (resp) {
68
68
  if (!resp) return;
69
69
  var asyncRemoteConfig = _this.parseConfig(resp);
@@ -74,12 +74,12 @@ export var ConfigManager = /*#__PURE__*/function () {
74
74
  });
75
75
  });
76
76
  if (!(remoteConfig.mode === 'remote-first')) {
77
- _context.next = 18;
77
+ _context.next = 5;
78
78
  break;
79
79
  }
80
- _context.next = 18;
80
+ _context.next = 5;
81
81
  return asyncConfigPromise;
82
- case 18:
82
+ case 5:
83
83
  case "end":
84
84
  return _context.stop();
85
85
  }
@@ -110,17 +110,17 @@ export var ConfigManager = /*#__PURE__*/function () {
110
110
  /*#__PURE__*/
111
111
  function () {
112
112
  var _setConfig = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(config) {
113
- return _regeneratorRuntime.wrap(function _callee2$(_context2) {
113
+ return _regeneratorRuntime.wrap(function (_context2) {
114
114
  while (1) switch (_context2.prev = _context2.next) {
115
115
  case 0:
116
116
  if (this.currentConfig) {
117
- _context2.next = 2;
117
+ _context2.next = 1;
118
118
  break;
119
119
  }
120
120
  return _context2.abrupt("return");
121
- case 2:
121
+ case 1:
122
122
  this.currentConfig = _extends({}, this.currentConfig, config);
123
- case 3:
123
+ case 2:
124
124
  case "end":
125
125
  return _context2.stop();
126
126
  }
@@ -1,10 +1,12 @@
1
1
  import { IConfiguration, IContext, IRumSession } from "../types/client";
2
2
  import { RumEvent, IViewData } from "../types/rum-event";
3
3
  import { IConfigManager } from "../types/config";
4
+ import { EventEmitter } from "../utils/events";
4
5
  declare class Context implements IContext {
5
6
  private config;
6
7
  private rumEvent;
7
8
  private views;
9
+ emitter: EventEmitter;
8
10
  session: IRumSession;
9
11
  configManager: IConfigManager;
10
12
  constructor(config: IConfiguration, rumSession?: IRumSession, configManager?: IConfigManager);
@@ -1,8 +1,10 @@
1
+ import { EventEmitter } from "../utils/events";
1
2
  var Context = /*#__PURE__*/function () {
2
3
  function Context(config, rumSession, configManager) {
3
4
  this.config = config;
4
5
  this.rumEvent = void 0;
5
6
  this.views = [];
7
+ this.emitter = new EventEmitter();
6
8
  this.session = void 0;
7
9
  this.configManager = void 0;
8
10
  if (rumSession) {
@@ -193,8 +193,8 @@ var Reporter = /*#__PURE__*/function () {
193
193
  _reportConfig$maxRetr,
194
194
  _reportConfig$retryDe,
195
195
  _this2 = this;
196
- var reportConfig, maxRetryCount, retryDelay;
197
- return _regeneratorRuntime.wrap(function _callee$(_context) {
196
+ var reportConfig, maxRetryCount, retryDelay, _t;
197
+ return _regeneratorRuntime.wrap(function (_context) {
198
198
  while (1) switch (_context.prev = _context.next) {
199
199
  case 0:
200
200
  if (retry === void 0) {
@@ -203,26 +203,26 @@ var Reporter = /*#__PURE__*/function () {
203
203
  reportConfig = (_this$ctx$getConfig = this.ctx.getConfig()) === null || _this$ctx$getConfig === void 0 ? void 0 : _this$ctx$getConfig.reportConfig;
204
204
  maxRetryCount = (_reportConfig$maxRetr = reportConfig === null || reportConfig === void 0 ? void 0 : reportConfig.maxRetryCount) !== null && _reportConfig$maxRetr !== void 0 ? _reportConfig$maxRetr : 0;
205
205
  retryDelay = (_reportConfig$retryDe = reportConfig === null || reportConfig === void 0 ? void 0 : reportConfig.retryDelay) !== null && _reportConfig$retryDe !== void 0 ? _reportConfig$retryDe : 3000;
206
- _context.prev = 4;
206
+ _context.prev = 1;
207
207
  bundle._retry = retry;
208
- _context.next = 8;
208
+ _context.next = 2;
209
209
  return this.request(this.ctx, bundle);
210
- case 8:
211
- _context.next = 13;
210
+ case 2:
211
+ _context.next = 4;
212
212
  break;
213
- case 10:
214
- _context.prev = 10;
215
- _context.t0 = _context["catch"](4);
213
+ case 3:
214
+ _context.prev = 3;
215
+ _t = _context["catch"](1);
216
216
  if (retry < maxRetryCount - 1) {
217
217
  setTimeout(function () {
218
218
  return _this2.tryRequest(bundle, retry + 1);
219
219
  }, retryDelay);
220
220
  }
221
- case 13:
221
+ case 4:
222
222
  case "end":
223
223
  return _context.stop();
224
224
  }
225
- }, _callee, this, [[4, 10]]);
225
+ }, _callee, this, [[1, 3]]);
226
226
  }));
227
227
  function tryRequest(_x, _x2) {
228
228
  return _tryRequest.apply(this, arguments);
@@ -2,8 +2,9 @@ import { ICollector } from './collector';
2
2
  import { IProcessor } from './processor';
3
3
  import { IReporter } from './reporter';
4
4
  import { RumEvent, RumEventBundle, IViewData } from './rum-event';
5
- import { MatchOption } from "../utils/match";
6
- import { IConfigManager } from "./config";
5
+ import { MatchOption } from '../utils/match';
6
+ import { IConfigManager } from './config';
7
+ import { EventEmitter } from '../utils/events';
7
8
  export declare enum EventType {
8
9
  /**
9
10
  * 收集数据
@@ -12,6 +13,7 @@ export declare enum EventType {
12
13
  }
13
14
  export interface IContext {
14
15
  session: IRumSession;
16
+ emitter: EventEmitter;
15
17
  /**
16
18
  * user config
17
19
  */
@@ -90,7 +92,7 @@ export interface IRemoteConfig {
90
92
  [key: string]: unknown;
91
93
  }
92
94
  export interface ICollectorConfig {
93
- name: string;
95
+ name?: string;
94
96
  enable?: boolean;
95
97
  sampling?: number;
96
98
  filters?: MatchOption[];
@@ -218,5 +220,12 @@ export interface IConfiguration {
218
220
  * 检测正则匹配内容
219
221
  */
220
222
  regexp?: string;
223
+ /**
224
+ * 检测元素是否包含特定属性或者属性值的元素,支持正则匹配
225
+ */
226
+ attributeRules?: Array<{
227
+ attributeName: string;
228
+ attributeValue?: Array<string | RegExp> | null;
229
+ }>;
221
230
  [key: string]: unknown;
222
231
  }
@@ -10,9 +10,11 @@ export declare enum RumEventType {
10
10
  export interface BaseObject {
11
11
  [key: string]: BaseObjectValue;
12
12
  }
13
- export interface IViewData {
13
+ export type loading_type = 'initial_load' | 'route_change';
14
+ export interface IViewData extends BaseObject {
14
15
  id: string;
15
16
  name: string;
17
+ loading_type?: loading_type;
16
18
  }
17
19
  export type BaseObjectPrimitiveValue = string | number | boolean | null | undefined;
18
20
  export type BaseObjectValue = BaseObjectPrimitiveValue | BaseObject | BaseObjectPrimitiveValue[] | IViewData;
@@ -26,27 +28,64 @@ export interface RumBaseEvent extends BaseObject {
26
28
  snapshots?: string;
27
29
  properties?: BaseObject;
28
30
  }
31
+ /** 事件类型:页面浏览、性能指标、Web Vitals、自定义指标、会话回放 */
32
+ export type view_type = 'pv' | 'perf' | 'webvitals' | 'custom' | 'replay' | 'view-stats';
29
33
  export interface RumViewEvent extends RumBaseEvent {
30
- loading_type?: 'initial_load' | 'route_change';
31
- type: 'pv' | 'perf' | 'webvitals' | 'custom';
34
+ /** 页面加载类型:初始加载或路由切换 */
35
+ loading_type?: loading_type;
36
+ type: view_type;
37
+ /** 最大内容绘制时间 (LCP) - 页面加载过程中最大文本块或图像元素的渲染时间 */
32
38
  largest_contentful_paint?: number;
39
+ /** 首次输入延迟 (FID) - 用户首次与页面交互到浏览器响应该交互的时间 */
33
40
  first_input_delay?: number;
41
+ /** 累积布局偏移 (CLS) - 页面可见元素意外移动的累积分数 */
34
42
  cumulative_layout_shift?: number;
43
+ /** 首次输入时间 (FIT) - 用户首次与页面交互的时间戳 */
35
44
  first_input_time?: number;
45
+ /** 页面加载时间 - 从开始加载到页面完全加载的时间 */
36
46
  loading_time?: number;
47
+ /** 首次绘制时间 (FP) - 浏览器首次渲染任何内容的时间 */
37
48
  first_paint?: number;
49
+ /** 首次内容绘制时间 (FCP) - 浏览器首次渲染DOM内容的时间 */
38
50
  first_contentful_paint?: number;
51
+ /** DOM 交互时间 - DOM 构建完成且脚本开始执行的时间 */
39
52
  dom_interactive?: number;
53
+ /** DOM 内容加载完成时间 - DOM 和所有子资源加载完成的时间 */
40
54
  dom_content_loaded?: number;
55
+ /** DOM 完成时间 - 页面及其所有资源加载完成的时间 */
41
56
  dom_complete?: number;
57
+ /** 加载事件时间 - load 事件触发的时间 */
42
58
  load_event?: number;
59
+ /** 自定义性能指标 T1 */
43
60
  t1?: number;
61
+ /** 自定义性能指标 T2 */
44
62
  t2?: number;
63
+ /** 自定义性能指标 T3 */
45
64
  t3?: number;
65
+ /** 来源页面 URL */
46
66
  referrer?: string;
67
+ /** 当前页面 URL */
47
68
  url?: string;
69
+ /** 性能时序数据 (JSON 字符串格式) */
48
70
  timing_data?: string;
49
71
  }
72
+ export interface RumReplayEvent extends RumBaseEvent {
73
+ type: 'replay';
74
+ /** 当前Records记录的结束时间 */
75
+ records_end?: number;
76
+ /** 会话回放片段索引 */
77
+ records_index?: number;
78
+ /** 当前会话包含的record数量 */
79
+ records_count?: number;
80
+ /** 创建record原因 */
81
+ records_reason?: string;
82
+ /** 包含的replay数据大小 */
83
+ records_size?: number;
84
+ /** 是否包含完整的Snapshot */
85
+ has_full_snapshot?: number;
86
+ /** 上报的录屏数据 */
87
+ records_data?: string;
88
+ }
50
89
  /**
51
90
  * 枚举值,表示资源是否加载成功
52
91
  */
@@ -96,10 +135,43 @@ export interface RumLongTaskEvent extends RumBaseEvent {
96
135
  snapshots: string;
97
136
  }
98
137
  export interface RumActionEvent extends RumBaseEvent {
138
+ event_type: RumEventType.ACTION;
139
+ /** 行为类型 */
99
140
  type?: string;
141
+ /** 行为名称 */
100
142
  name?: string;
143
+ /** 目标元素名称XPath */
101
144
  target_name?: string;
145
+ /** 操作持续时间(毫秒) */
102
146
  duration?: number;
147
+ /**
148
+ * Heatmap Analysis - 热力图分析
149
+ * 当 trackUserInteractions 开启时才会采集以下数据
150
+ * */
151
+ /** 点击位置信息 */
152
+ position?: {
153
+ /** 点击 X 坐标(相对于文档) */
154
+ x?: number;
155
+ /** 点击 Y 坐标(相对于文档) */
156
+ y?: number;
157
+ /** 元素内相对 X 坐标 */
158
+ ex?: number;
159
+ /** 元素内相对 Y 坐标 */
160
+ ey?: number;
161
+ };
162
+ /** 目标元素信息 */
163
+ target?: {
164
+ /** 元素的 selector:#root > div > button:nth-child(15) */
165
+ selector?: string;
166
+ /** 元素的宽度(像素) */
167
+ width?: number;
168
+ /** 元素的高度(像素) */
169
+ height?: number;
170
+ /** 是否为可交互元素(0=不可交互, 1=可交互),用于无效点击分析 */
171
+ reaction?: number;
172
+ /** 是否可信的交互(0=不可信, 1=可信),用于错误点击分析 */
173
+ trust?: number;
174
+ };
103
175
  }
104
176
  export interface RumCustomEvent extends RumBaseEvent {
105
177
  type: string;
@@ -8,6 +8,9 @@ export var RumEventType = /*#__PURE__*/function (RumEventType) {
8
8
  RumEventType["APPLICATION"] = "application";
9
9
  return RumEventType;
10
10
  }({});
11
+
12
+ /** 事件类型:页面浏览、性能指标、Web Vitals、自定义指标、会话回放 */
13
+
11
14
  /**
12
15
  * 枚举值,表示资源是否加载成功
13
16
  */
@@ -41,17 +41,6 @@ export declare function debounce(func: Function, wait: number): () => void;
41
41
  * @param wait 延迟执行毫秒数
42
42
  */
43
43
  export declare function delay(func: Function, wait: number, ...args: any[]): number;
44
- /**
45
- * @desc 需要严格区分object和array
46
- * @param obj 任意对象
47
- */
48
- export declare function getType(obj: any): any;
49
- /**
50
- * @desc 将字符串转换成正则表达式
51
- * @param str 任意字符串
52
- * 注意,这里只支持 /xxx/ 这种格式,不支持修饰符,例如 /xxx/ig
53
- */
54
- export declare function transStrToReg(str: string): string | RegExp;
55
44
  /**
56
45
  * 解析正则表达式字符串,支持 /pattern/flags 格式
57
46
  * @param str 正则表达式字符串,如 "/a/ig" 或 "a"
package/es/utils/base.js CHANGED
@@ -1,8 +1,5 @@
1
1
  import { isFunction } from "./is";
2
2
 
3
- // 类型匹配正则
4
- var TYPE_REG = /^\[object ([a-z]*)\]$/;
5
-
6
3
  /**
7
4
  * 劫持函数或原型
8
5
  */
@@ -150,30 +147,32 @@ export function delay(func, wait) {
150
147
  return setTimeout.apply(void 0, [func, +wait || 0].concat(args));
151
148
  }
152
149
 
153
- /**
154
- * @desc 需要严格区分object和array
155
- * @param obj 任意对象
156
- */
157
- export function getType(obj) {
158
- var type = Object.prototype.toString.call(obj);
159
- type = type.toLowerCase() || '';
160
- var arr = type.match(TYPE_REG);
161
- return arr === null || arr === void 0 ? void 0 : arr[1];
162
- }
163
-
164
- /**
165
- * @desc 将字符串转换成正则表达式
166
- * @param str 任意字符串
167
- * 注意,这里只支持 /xxx/ 这种格式,不支持修饰符,例如 /xxx/ig
168
- */
169
- export function transStrToReg(str) {
170
- if (getType(str) !== 'string') return str;
171
- if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {
172
- return new RegExp(str.substr(1, str.length - 2));
173
- }
174
- return str;
175
- }
176
-
150
+ // // 类型匹配正则
151
+ // const TYPE_REG = /^\[object ([a-z]*)\]$/;
152
+ // /**
153
+ // * @desc 需要严格区分object和array
154
+ // * @param obj 任意对象
155
+ // */
156
+ // export function getType(obj: any) {
157
+ // let type = Object.prototype.toString.call(obj);
158
+ // type = type.toLowerCase() || '';
159
+ // const arr = type.match(TYPE_REG);
160
+ // return arr?.[1];
161
+ // }
162
+ //
163
+ // /**
164
+ // * @desc 将字符串转换成正则表达式
165
+ // * @param str 任意字符串
166
+ // * 注意,这里只支持 /xxx/ 这种格式,不支持修饰符,例如 /xxx/ig
167
+ // */
168
+ // export function transStrToReg(str: string) {
169
+ // if (getType(str) !== 'string') return str;
170
+ // if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {
171
+ // return new RegExp(str.substr(1, str.length - 2));
172
+ // }
173
+ // return str;
174
+ // }
175
+ //
177
176
  // /**
178
177
  // *
179
178
  // * @param config 配置
@@ -1,4 +1,4 @@
1
- type EventHandler = (...args: any[]) => void;
1
+ export type EventHandler = (...args: any[]) => void;
2
2
  export declare class EventEmitter {
3
3
  private events;
4
4
  /**
@@ -26,4 +26,3 @@ export declare class EventEmitter {
26
26
  */
27
27
  once(eventName: string, handler: EventHandler): void;
28
28
  }
29
- export {};
package/lib/index.d.ts CHANGED
@@ -18,4 +18,5 @@ export * from './utils/match';
18
18
  export * from './utils/trace';
19
19
  export * from './utils/verify';
20
20
  export * from './utils/url';
21
+ export * from './utils/events';
21
22
  export { Client, Context, Reporter, Shell };
package/lib/index.js CHANGED
@@ -127,4 +127,11 @@ Object.keys(_url).forEach(function (key) {
127
127
  if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
128
128
  if (key in exports && exports[key] === _url[key]) return;
129
129
  exports[key] = _url[key];
130
+ });
131
+ var _events = require("./utils/events");
132
+ Object.keys(_events).forEach(function (key) {
133
+ if (key === "default" || key === "__esModule") return;
134
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
135
+ if (key in exports && exports[key] === _events[key]) return;
136
+ exports[key] = _events[key];
130
137
  });
@@ -37,38 +37,38 @@ var ConfigManager = exports.ConfigManager = /*#__PURE__*/function () {
37
37
  var _init = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee(config) {
38
38
  var _this = this;
39
39
  var remoteConfig, cacheConfig, asyncConfigPromise;
40
- return _regenerator["default"].wrap(function _callee$(_context) {
40
+ return _regenerator["default"].wrap(function (_context) {
41
41
  while (1) switch (_context.prev = _context.next) {
42
42
  case 0:
43
43
  if (!this.initialized) {
44
- _context.next = 2;
44
+ _context.next = 1;
45
45
  break;
46
46
  }
47
47
  return _context.abrupt("return");
48
- case 2:
48
+ case 1:
49
49
  this.currentConfig = (0, _extends2["default"])({}, config);
50
50
  this.initialized = true;
51
51
  remoteConfig = parseRemoteConfig(config);
52
52
  this.currentConfig.remoteConfig = remoteConfig;
53
53
  if (remoteConfig.enable) {
54
- _context.next = 8;
54
+ _context.next = 2;
55
55
  break;
56
56
  }
57
57
  return _context.abrupt("return");
58
- case 8:
59
- _context.next = 10;
58
+ case 2:
59
+ _context.next = 3;
60
60
  return this.getCacheConfig();
61
- case 10:
61
+ case 3:
62
62
  cacheConfig = _context.sent;
63
63
  if (cacheConfig && cacheConfig.content) {
64
64
  this.currentConfig = this.mergeRemoteCfg(cacheConfig.content);
65
65
  }
66
66
  if (!this.isCacheValid(cacheConfig, remoteConfig.cacheTimeout)) {
67
- _context.next = 14;
67
+ _context.next = 4;
68
68
  break;
69
69
  }
70
70
  return _context.abrupt("return");
71
- case 14:
71
+ case 4:
72
72
  asyncConfigPromise = this.fetchRemoteCfg(this.currentConfig).then(function (resp) {
73
73
  if (!resp) return;
74
74
  var asyncRemoteConfig = _this.parseConfig(resp);
@@ -79,12 +79,12 @@ var ConfigManager = exports.ConfigManager = /*#__PURE__*/function () {
79
79
  });
80
80
  });
81
81
  if (!(remoteConfig.mode === 'remote-first')) {
82
- _context.next = 18;
82
+ _context.next = 5;
83
83
  break;
84
84
  }
85
- _context.next = 18;
85
+ _context.next = 5;
86
86
  return asyncConfigPromise;
87
- case 18:
87
+ case 5:
88
88
  case "end":
89
89
  return _context.stop();
90
90
  }
@@ -115,17 +115,17 @@ var ConfigManager = exports.ConfigManager = /*#__PURE__*/function () {
115
115
  /*#__PURE__*/
116
116
  function () {
117
117
  var _setConfig = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee2(config) {
118
- return _regenerator["default"].wrap(function _callee2$(_context2) {
118
+ return _regenerator["default"].wrap(function (_context2) {
119
119
  while (1) switch (_context2.prev = _context2.next) {
120
120
  case 0:
121
121
  if (this.currentConfig) {
122
- _context2.next = 2;
122
+ _context2.next = 1;
123
123
  break;
124
124
  }
125
125
  return _context2.abrupt("return");
126
- case 2:
126
+ case 1:
127
127
  this.currentConfig = (0, _extends2["default"])({}, this.currentConfig, config);
128
- case 3:
128
+ case 2:
129
129
  case "end":
130
130
  return _context2.stop();
131
131
  }
@@ -1,10 +1,12 @@
1
1
  import { IConfiguration, IContext, IRumSession } from "../types/client";
2
2
  import { RumEvent, IViewData } from "../types/rum-event";
3
3
  import { IConfigManager } from "../types/config";
4
+ import { EventEmitter } from "../utils/events";
4
5
  declare class Context implements IContext {
5
6
  private config;
6
7
  private rumEvent;
7
8
  private views;
9
+ emitter: EventEmitter;
8
10
  session: IRumSession;
9
11
  configManager: IConfigManager;
10
12
  constructor(config: IConfiguration, rumSession?: IRumSession, configManager?: IConfigManager);
@@ -2,11 +2,13 @@
2
2
 
3
3
  exports.__esModule = true;
4
4
  exports["default"] = void 0;
5
+ var _events = require("../utils/events");
5
6
  var Context = /*#__PURE__*/function () {
6
7
  function Context(config, rumSession, configManager) {
7
8
  this.config = config;
8
9
  this.rumEvent = void 0;
9
10
  this.views = [];
11
+ this.emitter = new _events.EventEmitter();
10
12
  this.session = void 0;
11
13
  this.configManager = void 0;
12
14
  if (rumSession) {
@@ -198,8 +198,8 @@ var Reporter = exports["default"] = /*#__PURE__*/function () {
198
198
  _reportConfig$maxRetr,
199
199
  _reportConfig$retryDe,
200
200
  _this2 = this;
201
- var reportConfig, maxRetryCount, retryDelay;
202
- return _regenerator["default"].wrap(function _callee$(_context) {
201
+ var reportConfig, maxRetryCount, retryDelay, _t;
202
+ return _regenerator["default"].wrap(function (_context) {
203
203
  while (1) switch (_context.prev = _context.next) {
204
204
  case 0:
205
205
  if (retry === void 0) {
@@ -208,26 +208,26 @@ var Reporter = exports["default"] = /*#__PURE__*/function () {
208
208
  reportConfig = (_this$ctx$getConfig = this.ctx.getConfig()) === null || _this$ctx$getConfig === void 0 ? void 0 : _this$ctx$getConfig.reportConfig;
209
209
  maxRetryCount = (_reportConfig$maxRetr = reportConfig === null || reportConfig === void 0 ? void 0 : reportConfig.maxRetryCount) !== null && _reportConfig$maxRetr !== void 0 ? _reportConfig$maxRetr : 0;
210
210
  retryDelay = (_reportConfig$retryDe = reportConfig === null || reportConfig === void 0 ? void 0 : reportConfig.retryDelay) !== null && _reportConfig$retryDe !== void 0 ? _reportConfig$retryDe : 3000;
211
- _context.prev = 4;
211
+ _context.prev = 1;
212
212
  bundle._retry = retry;
213
- _context.next = 8;
213
+ _context.next = 2;
214
214
  return this.request(this.ctx, bundle);
215
- case 8:
216
- _context.next = 13;
215
+ case 2:
216
+ _context.next = 4;
217
217
  break;
218
- case 10:
219
- _context.prev = 10;
220
- _context.t0 = _context["catch"](4);
218
+ case 3:
219
+ _context.prev = 3;
220
+ _t = _context["catch"](1);
221
221
  if (retry < maxRetryCount - 1) {
222
222
  setTimeout(function () {
223
223
  return _this2.tryRequest(bundle, retry + 1);
224
224
  }, retryDelay);
225
225
  }
226
- case 13:
226
+ case 4:
227
227
  case "end":
228
228
  return _context.stop();
229
229
  }
230
- }, _callee, this, [[4, 10]]);
230
+ }, _callee, this, [[1, 3]]);
231
231
  }));
232
232
  function tryRequest(_x, _x2) {
233
233
  return _tryRequest.apply(this, arguments);
@@ -2,8 +2,9 @@ import { ICollector } from './collector';
2
2
  import { IProcessor } from './processor';
3
3
  import { IReporter } from './reporter';
4
4
  import { RumEvent, RumEventBundle, IViewData } from './rum-event';
5
- import { MatchOption } from "../utils/match";
6
- import { IConfigManager } from "./config";
5
+ import { MatchOption } from '../utils/match';
6
+ import { IConfigManager } from './config';
7
+ import { EventEmitter } from '../utils/events';
7
8
  export declare enum EventType {
8
9
  /**
9
10
  * 收集数据
@@ -12,6 +13,7 @@ export declare enum EventType {
12
13
  }
13
14
  export interface IContext {
14
15
  session: IRumSession;
16
+ emitter: EventEmitter;
15
17
  /**
16
18
  * user config
17
19
  */
@@ -90,7 +92,7 @@ export interface IRemoteConfig {
90
92
  [key: string]: unknown;
91
93
  }
92
94
  export interface ICollectorConfig {
93
- name: string;
95
+ name?: string;
94
96
  enable?: boolean;
95
97
  sampling?: number;
96
98
  filters?: MatchOption[];
@@ -218,5 +220,12 @@ export interface IConfiguration {
218
220
  * 检测正则匹配内容
219
221
  */
220
222
  regexp?: string;
223
+ /**
224
+ * 检测元素是否包含特定属性或者属性值的元素,支持正则匹配
225
+ */
226
+ attributeRules?: Array<{
227
+ attributeName: string;
228
+ attributeValue?: Array<string | RegExp> | null;
229
+ }>;
221
230
  [key: string]: unknown;
222
231
  }
@@ -10,9 +10,11 @@ export declare enum RumEventType {
10
10
  export interface BaseObject {
11
11
  [key: string]: BaseObjectValue;
12
12
  }
13
- export interface IViewData {
13
+ export type loading_type = 'initial_load' | 'route_change';
14
+ export interface IViewData extends BaseObject {
14
15
  id: string;
15
16
  name: string;
17
+ loading_type?: loading_type;
16
18
  }
17
19
  export type BaseObjectPrimitiveValue = string | number | boolean | null | undefined;
18
20
  export type BaseObjectValue = BaseObjectPrimitiveValue | BaseObject | BaseObjectPrimitiveValue[] | IViewData;
@@ -26,27 +28,64 @@ export interface RumBaseEvent extends BaseObject {
26
28
  snapshots?: string;
27
29
  properties?: BaseObject;
28
30
  }
31
+ /** 事件类型:页面浏览、性能指标、Web Vitals、自定义指标、会话回放 */
32
+ export type view_type = 'pv' | 'perf' | 'webvitals' | 'custom' | 'replay' | 'view-stats';
29
33
  export interface RumViewEvent extends RumBaseEvent {
30
- loading_type?: 'initial_load' | 'route_change';
31
- type: 'pv' | 'perf' | 'webvitals' | 'custom';
34
+ /** 页面加载类型:初始加载或路由切换 */
35
+ loading_type?: loading_type;
36
+ type: view_type;
37
+ /** 最大内容绘制时间 (LCP) - 页面加载过程中最大文本块或图像元素的渲染时间 */
32
38
  largest_contentful_paint?: number;
39
+ /** 首次输入延迟 (FID) - 用户首次与页面交互到浏览器响应该交互的时间 */
33
40
  first_input_delay?: number;
41
+ /** 累积布局偏移 (CLS) - 页面可见元素意外移动的累积分数 */
34
42
  cumulative_layout_shift?: number;
43
+ /** 首次输入时间 (FIT) - 用户首次与页面交互的时间戳 */
35
44
  first_input_time?: number;
45
+ /** 页面加载时间 - 从开始加载到页面完全加载的时间 */
36
46
  loading_time?: number;
47
+ /** 首次绘制时间 (FP) - 浏览器首次渲染任何内容的时间 */
37
48
  first_paint?: number;
49
+ /** 首次内容绘制时间 (FCP) - 浏览器首次渲染DOM内容的时间 */
38
50
  first_contentful_paint?: number;
51
+ /** DOM 交互时间 - DOM 构建完成且脚本开始执行的时间 */
39
52
  dom_interactive?: number;
53
+ /** DOM 内容加载完成时间 - DOM 和所有子资源加载完成的时间 */
40
54
  dom_content_loaded?: number;
55
+ /** DOM 完成时间 - 页面及其所有资源加载完成的时间 */
41
56
  dom_complete?: number;
57
+ /** 加载事件时间 - load 事件触发的时间 */
42
58
  load_event?: number;
59
+ /** 自定义性能指标 T1 */
43
60
  t1?: number;
61
+ /** 自定义性能指标 T2 */
44
62
  t2?: number;
63
+ /** 自定义性能指标 T3 */
45
64
  t3?: number;
65
+ /** 来源页面 URL */
46
66
  referrer?: string;
67
+ /** 当前页面 URL */
47
68
  url?: string;
69
+ /** 性能时序数据 (JSON 字符串格式) */
48
70
  timing_data?: string;
49
71
  }
72
+ export interface RumReplayEvent extends RumBaseEvent {
73
+ type: 'replay';
74
+ /** 当前Records记录的结束时间 */
75
+ records_end?: number;
76
+ /** 会话回放片段索引 */
77
+ records_index?: number;
78
+ /** 当前会话包含的record数量 */
79
+ records_count?: number;
80
+ /** 创建record原因 */
81
+ records_reason?: string;
82
+ /** 包含的replay数据大小 */
83
+ records_size?: number;
84
+ /** 是否包含完整的Snapshot */
85
+ has_full_snapshot?: number;
86
+ /** 上报的录屏数据 */
87
+ records_data?: string;
88
+ }
50
89
  /**
51
90
  * 枚举值,表示资源是否加载成功
52
91
  */
@@ -96,10 +135,43 @@ export interface RumLongTaskEvent extends RumBaseEvent {
96
135
  snapshots: string;
97
136
  }
98
137
  export interface RumActionEvent extends RumBaseEvent {
138
+ event_type: RumEventType.ACTION;
139
+ /** 行为类型 */
99
140
  type?: string;
141
+ /** 行为名称 */
100
142
  name?: string;
143
+ /** 目标元素名称XPath */
101
144
  target_name?: string;
145
+ /** 操作持续时间(毫秒) */
102
146
  duration?: number;
147
+ /**
148
+ * Heatmap Analysis - 热力图分析
149
+ * 当 trackUserInteractions 开启时才会采集以下数据
150
+ * */
151
+ /** 点击位置信息 */
152
+ position?: {
153
+ /** 点击 X 坐标(相对于文档) */
154
+ x?: number;
155
+ /** 点击 Y 坐标(相对于文档) */
156
+ y?: number;
157
+ /** 元素内相对 X 坐标 */
158
+ ex?: number;
159
+ /** 元素内相对 Y 坐标 */
160
+ ey?: number;
161
+ };
162
+ /** 目标元素信息 */
163
+ target?: {
164
+ /** 元素的 selector:#root > div > button:nth-child(15) */
165
+ selector?: string;
166
+ /** 元素的宽度(像素) */
167
+ width?: number;
168
+ /** 元素的高度(像素) */
169
+ height?: number;
170
+ /** 是否为可交互元素(0=不可交互, 1=可交互),用于无效点击分析 */
171
+ reaction?: number;
172
+ /** 是否可信的交互(0=不可信, 1=可信),用于错误点击分析 */
173
+ trust?: number;
174
+ };
103
175
  }
104
176
  export interface RumCustomEvent extends RumBaseEvent {
105
177
  type: string;
@@ -12,6 +12,7 @@ var RumEventType = exports.RumEventType = /*#__PURE__*/function (RumEventType) {
12
12
  RumEventType["APPLICATION"] = "application";
13
13
  return RumEventType;
14
14
  }({});
15
+ /** 事件类型:页面浏览、性能指标、Web Vitals、自定义指标、会话回放 */
15
16
  /**
16
17
  * 枚举值,表示资源是否加载成功
17
18
  */
@@ -41,17 +41,6 @@ export declare function debounce(func: Function, wait: number): () => void;
41
41
  * @param wait 延迟执行毫秒数
42
42
  */
43
43
  export declare function delay(func: Function, wait: number, ...args: any[]): number;
44
- /**
45
- * @desc 需要严格区分object和array
46
- * @param obj 任意对象
47
- */
48
- export declare function getType(obj: any): any;
49
- /**
50
- * @desc 将字符串转换成正则表达式
51
- * @param str 任意字符串
52
- * 注意,这里只支持 /xxx/ 这种格式,不支持修饰符,例如 /xxx/ig
53
- */
54
- export declare function transStrToReg(str: string): string | RegExp;
55
44
  /**
56
45
  * 解析正则表达式字符串,支持 /pattern/flags 格式
57
46
  * @param str 正则表达式字符串,如 "/a/ig" 或 "a"
package/lib/utils/base.js CHANGED
@@ -7,15 +7,10 @@ exports.generateEventId = generateEventId;
7
7
  exports.generateGUID = generateGUID;
8
8
  exports.generateSpanId = generateSpanId;
9
9
  exports.generateTraceId = generateTraceId;
10
- exports.getType = getType;
11
10
  exports.interceptFunction = interceptFunction;
12
11
  exports.parseRegExpString = parseRegExpString;
13
12
  exports.restoreFunction = restoreFunction;
14
- exports.transStrToReg = transStrToReg;
15
13
  var _is = require("./is");
16
- // 类型匹配正则
17
- var TYPE_REG = /^\[object ([a-z]*)\]$/;
18
-
19
14
  /**
20
15
  * 劫持函数或原型
21
16
  */
@@ -163,30 +158,32 @@ function delay(func, wait) {
163
158
  return setTimeout.apply(void 0, [func, +wait || 0].concat(args));
164
159
  }
165
160
 
166
- /**
167
- * @desc 需要严格区分object和array
168
- * @param obj 任意对象
169
- */
170
- function getType(obj) {
171
- var type = Object.prototype.toString.call(obj);
172
- type = type.toLowerCase() || '';
173
- var arr = type.match(TYPE_REG);
174
- return arr === null || arr === void 0 ? void 0 : arr[1];
175
- }
176
-
177
- /**
178
- * @desc 将字符串转换成正则表达式
179
- * @param str 任意字符串
180
- * 注意,这里只支持 /xxx/ 这种格式,不支持修饰符,例如 /xxx/ig
181
- */
182
- function transStrToReg(str) {
183
- if (getType(str) !== 'string') return str;
184
- if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {
185
- return new RegExp(str.substr(1, str.length - 2));
186
- }
187
- return str;
188
- }
189
-
161
+ // // 类型匹配正则
162
+ // const TYPE_REG = /^\[object ([a-z]*)\]$/;
163
+ // /**
164
+ // * @desc 需要严格区分object和array
165
+ // * @param obj 任意对象
166
+ // */
167
+ // export function getType(obj: any) {
168
+ // let type = Object.prototype.toString.call(obj);
169
+ // type = type.toLowerCase() || '';
170
+ // const arr = type.match(TYPE_REG);
171
+ // return arr?.[1];
172
+ // }
173
+ //
174
+ // /**
175
+ // * @desc 将字符串转换成正则表达式
176
+ // * @param str 任意字符串
177
+ // * 注意,这里只支持 /xxx/ 这种格式,不支持修饰符,例如 /xxx/ig
178
+ // */
179
+ // export function transStrToReg(str: string) {
180
+ // if (getType(str) !== 'string') return str;
181
+ // if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {
182
+ // return new RegExp(str.substr(1, str.length - 2));
183
+ // }
184
+ // return str;
185
+ // }
186
+ //
190
187
  // /**
191
188
  // *
192
189
  // * @param config 配置
@@ -1,4 +1,4 @@
1
- type EventHandler = (...args: any[]) => void;
1
+ export type EventHandler = (...args: any[]) => void;
2
2
  export declare class EventEmitter {
3
3
  private events;
4
4
  /**
@@ -26,4 +26,3 @@ export declare class EventEmitter {
26
26
  */
27
27
  once(eventName: string, handler: EventHandler): void;
28
28
  }
29
- export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arms/rum-core",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "arms rum javascript sdk core",
5
5
  "author": "guangli.fj <guangli.fj@alibaba-inc.com>",
6
6
  "license": "ISC",