@player-ui/metrics-plugin 0.8.0--canary.307.9645 → 0.8.0-next.1
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/dist/MetricsPlugin.native.js +8078 -0
- package/dist/MetricsPlugin.native.js.map +1 -0
- package/dist/{index.cjs.js → cjs/index.cjs} +137 -124
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/{index.esm.js → index.legacy-esm.js} +96 -106
- package/dist/index.mjs +330 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +23 -60
- package/src/index.test.ts +271 -0
- package/src/index.ts +2 -2
- package/src/metrics.ts +35 -35
- package/src/symbols.ts +2 -2
- package/types/index.d.ts +3 -0
- package/{dist/index.d.ts → types/metrics.d.ts} +16 -19
- package/types/symbols.d.ts +3 -0
- package/dist/metrics-plugin.dev.js +0 -11110
- package/dist/metrics-plugin.prod.js +0 -2
|
@@ -1,54 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
var tapableTs = require('tapable-ts');
|
|
6
|
-
var beaconPlugin = require('@player-ui/beacon-plugin');
|
|
7
|
-
|
|
8
|
-
const MetricsCorePluginSymbol = Symbol.for("MetricsCorePlugin");
|
|
9
|
-
const MetricsViewBeaconPluginContextSymbol = Symbol.for("MetricsViewBeaconPluginContext");
|
|
10
|
-
|
|
1
|
+
"use strict";
|
|
11
2
|
var __defProp = Object.defineProperty;
|
|
12
|
-
var
|
|
13
|
-
var
|
|
14
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
15
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
16
|
-
var
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
for (var prop in b || (b = {}))
|
|
20
|
-
if (__hasOwnProp.call(b, prop))
|
|
21
|
-
__defNormalProp(a, prop, b[prop]);
|
|
22
|
-
if (__getOwnPropSymbols)
|
|
23
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
24
|
-
if (__propIsEnum.call(b, prop))
|
|
25
|
-
__defNormalProp(a, prop, b[prop]);
|
|
26
|
-
}
|
|
27
|
-
return a;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
28
9
|
};
|
|
29
|
-
var
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
reject(e);
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
var rejected = (value) => {
|
|
40
|
-
try {
|
|
41
|
-
step(generator.throw(value));
|
|
42
|
-
} catch (e) {
|
|
43
|
-
reject(e);
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
47
|
-
step((generator = generator.apply(__this, __arguments)).next());
|
|
48
|
-
});
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
49
17
|
};
|
|
50
|
-
|
|
51
|
-
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/metrics/core/src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
MetricsCorePlugin: () => MetricsCorePlugin,
|
|
24
|
+
MetricsCorePluginSymbol: () => MetricsCorePluginSymbol,
|
|
25
|
+
MetricsViewBeaconPlugin: () => MetricsViewBeaconPlugin,
|
|
26
|
+
MetricsViewBeaconPluginContextSymbol: () => MetricsViewBeaconPluginContextSymbol,
|
|
27
|
+
RequestTimeWebPlugin: () => RequestTimeWebPlugin,
|
|
28
|
+
defaultGetTime: () => defaultGetTime
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(src_exports);
|
|
31
|
+
|
|
32
|
+
// ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/metrics/core/src/metrics.ts
|
|
33
|
+
var import_tapable_ts = require("tapable-ts");
|
|
34
|
+
var import_beacon_plugin = require("@player-ui/beacon-plugin");
|
|
35
|
+
|
|
36
|
+
// ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/metrics/core/src/symbols.ts
|
|
37
|
+
var MetricsCorePluginSymbol = Symbol.for("MetricsCorePlugin");
|
|
38
|
+
var MetricsViewBeaconPluginContextSymbol = Symbol.for(
|
|
39
|
+
"MetricsViewBeaconPluginContext"
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
// ../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/metrics/core/src/metrics.ts
|
|
43
|
+
var defaultGetTime = typeof performance === "undefined" ? () => Date.now() : () => performance.now();
|
|
44
|
+
var callbacks = [
|
|
52
45
|
"onFlowBegin",
|
|
53
46
|
"onFlowEnd",
|
|
54
47
|
"onInteractive",
|
|
@@ -60,16 +53,19 @@ const callbacks = [
|
|
|
60
53
|
"onUpdateEnd",
|
|
61
54
|
"onUpdate"
|
|
62
55
|
];
|
|
63
|
-
|
|
56
|
+
var _MetricsViewBeaconPlugin = class _MetricsViewBeaconPlugin {
|
|
64
57
|
constructor(metricsPlugin) {
|
|
65
58
|
this.symbol = _MetricsViewBeaconPlugin.Symbol;
|
|
66
59
|
this.metricsPlugin = metricsPlugin;
|
|
67
|
-
this.metricsPlugin.hooks.onRenderEnd.tap(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
this.resolvePendingRenderTime
|
|
60
|
+
this.metricsPlugin.hooks.onRenderEnd.tap(
|
|
61
|
+
"MetricsViewBeaconPlugin",
|
|
62
|
+
(timing) => {
|
|
63
|
+
if (timing.completed && this.resolvePendingRenderTime) {
|
|
64
|
+
this.resolvePendingRenderTime(timing.duration);
|
|
65
|
+
this.resolvePendingRenderTime = void 0;
|
|
66
|
+
}
|
|
71
67
|
}
|
|
72
|
-
|
|
68
|
+
);
|
|
73
69
|
}
|
|
74
70
|
apply(beaconPlugin) {
|
|
75
71
|
beaconPlugin.hooks.buildBeacon.intercept({
|
|
@@ -81,36 +77,32 @@ const _MetricsViewBeaconPlugin = class {
|
|
|
81
77
|
}
|
|
82
78
|
});
|
|
83
79
|
}
|
|
84
|
-
buildContext() {
|
|
85
|
-
return
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
};
|
|
90
|
-
});
|
|
80
|
+
async buildContext() {
|
|
81
|
+
return {
|
|
82
|
+
renderTime: await this.getRenderTime(),
|
|
83
|
+
requestTime: this.getRequestTime()
|
|
84
|
+
};
|
|
91
85
|
}
|
|
92
|
-
getRenderTime() {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return lastItem.render.duration;
|
|
99
|
-
}
|
|
86
|
+
async getRenderTime() {
|
|
87
|
+
const { flow } = this.metricsPlugin.getMetrics();
|
|
88
|
+
if (flow) {
|
|
89
|
+
const lastItem = flow.timeline[flow.timeline.length - 1];
|
|
90
|
+
if ("render" in lastItem && lastItem.render.completed) {
|
|
91
|
+
return lastItem.render.duration;
|
|
100
92
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
93
|
+
}
|
|
94
|
+
return new Promise((resolve) => {
|
|
95
|
+
this.resolvePendingRenderTime = resolve;
|
|
104
96
|
});
|
|
105
97
|
}
|
|
106
98
|
getRequestTime() {
|
|
107
99
|
const { flow } = this.metricsPlugin.getMetrics();
|
|
108
|
-
return flow
|
|
100
|
+
return flow?.requestTime;
|
|
109
101
|
}
|
|
110
102
|
};
|
|
111
|
-
|
|
112
|
-
MetricsViewBeaconPlugin
|
|
113
|
-
|
|
103
|
+
_MetricsViewBeaconPlugin.Symbol = MetricsViewBeaconPluginContextSymbol;
|
|
104
|
+
var MetricsViewBeaconPlugin = _MetricsViewBeaconPlugin;
|
|
105
|
+
var RequestTimeWebPlugin = class {
|
|
114
106
|
constructor(getRequestTime) {
|
|
115
107
|
this.name = "RequestTimeWebPlugin";
|
|
116
108
|
this.getRequestTime = getRequestTime;
|
|
@@ -120,29 +112,28 @@ class RequestTimeWebPlugin {
|
|
|
120
112
|
return this.getRequestTime();
|
|
121
113
|
});
|
|
122
114
|
}
|
|
123
|
-
}
|
|
124
|
-
|
|
115
|
+
};
|
|
116
|
+
var MetricsCorePlugin = class {
|
|
125
117
|
constructor(options) {
|
|
126
118
|
this.name = "metrics";
|
|
127
119
|
this.symbol = MetricsCorePluginSymbol;
|
|
128
120
|
this.hooks = {
|
|
129
|
-
resolveRequestTime: new
|
|
130
|
-
onFlowBegin: new
|
|
131
|
-
onFlowEnd: new
|
|
132
|
-
onInteractive: new
|
|
133
|
-
onNodeStart: new
|
|
134
|
-
onNodeEnd: new
|
|
135
|
-
onRenderStart: new
|
|
136
|
-
onRenderEnd: new
|
|
137
|
-
onUpdateStart: new
|
|
138
|
-
onUpdateEnd: new
|
|
139
|
-
onUpdate: new
|
|
121
|
+
resolveRequestTime: new import_tapable_ts.SyncBailHook(),
|
|
122
|
+
onFlowBegin: new import_tapable_ts.SyncHook(),
|
|
123
|
+
onFlowEnd: new import_tapable_ts.SyncHook(),
|
|
124
|
+
onInteractive: new import_tapable_ts.SyncHook(),
|
|
125
|
+
onNodeStart: new import_tapable_ts.SyncHook(),
|
|
126
|
+
onNodeEnd: new import_tapable_ts.SyncHook(),
|
|
127
|
+
onRenderStart: new import_tapable_ts.SyncHook(),
|
|
128
|
+
onRenderEnd: new import_tapable_ts.SyncHook(),
|
|
129
|
+
onUpdateStart: new import_tapable_ts.SyncHook(),
|
|
130
|
+
onUpdateEnd: new import_tapable_ts.SyncHook(),
|
|
131
|
+
onUpdate: new import_tapable_ts.SyncHook()
|
|
140
132
|
};
|
|
141
133
|
this.metrics = {};
|
|
142
|
-
|
|
143
|
-
this.
|
|
144
|
-
this.
|
|
145
|
-
this.getTime = (_c = options == null ? void 0 : options.getTime) != null ? _c : defaultGetTime;
|
|
134
|
+
this.trackRender = options?.trackRenderTime ?? false;
|
|
135
|
+
this.trackUpdate = options?.trackUpdateTime ?? false;
|
|
136
|
+
this.getTime = options?.getTime ?? defaultGetTime;
|
|
146
137
|
const callOnUpdate = () => {
|
|
147
138
|
this.hooks.onUpdate.call(this.metrics);
|
|
148
139
|
};
|
|
@@ -156,17 +147,20 @@ class MetricsCorePlugin {
|
|
|
156
147
|
this.hooks.onUpdateStart.tap(this.name, callOnUpdate);
|
|
157
148
|
this.hooks.onUpdateEnd.tap(this.name, callOnUpdate);
|
|
158
149
|
callbacks.forEach((hookName) => {
|
|
159
|
-
if (
|
|
160
|
-
this.hooks[hookName].tap("options", options
|
|
150
|
+
if (options?.[hookName] !== void 0) {
|
|
151
|
+
this.hooks[hookName].tap("options", options?.[hookName]);
|
|
161
152
|
}
|
|
162
153
|
});
|
|
163
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Fetch the metrics of the current flow
|
|
157
|
+
*/
|
|
164
158
|
getMetrics() {
|
|
165
159
|
return this.metrics;
|
|
166
160
|
}
|
|
161
|
+
/** Called when the UI layer wishes to start a timer for rendering */
|
|
167
162
|
renderStart() {
|
|
168
|
-
|
|
169
|
-
const timeline = (_a = this.metrics.flow) == null ? void 0 : _a.timeline;
|
|
163
|
+
const timeline = this.metrics.flow?.timeline;
|
|
170
164
|
if (!timeline || timeline.length === 0) {
|
|
171
165
|
return;
|
|
172
166
|
}
|
|
@@ -188,20 +182,28 @@ class MetricsCorePlugin {
|
|
|
188
182
|
lastItem.updates.push(update);
|
|
189
183
|
this.hooks.onUpdateStart.call(update, lastItem, this.metrics);
|
|
190
184
|
} else {
|
|
191
|
-
const renderInfo =
|
|
185
|
+
const renderInfo = {
|
|
186
|
+
...lastItem,
|
|
192
187
|
render: {
|
|
193
188
|
completed: false,
|
|
194
189
|
startTime: defaultGetTime()
|
|
195
190
|
},
|
|
196
191
|
updates: []
|
|
197
|
-
}
|
|
192
|
+
};
|
|
198
193
|
timeline[timeline.length - 1] = renderInfo;
|
|
199
|
-
this.hooks.onRenderStart.call(
|
|
194
|
+
this.hooks.onRenderStart.call(
|
|
195
|
+
renderInfo.render,
|
|
196
|
+
renderInfo,
|
|
197
|
+
this.metrics
|
|
198
|
+
);
|
|
200
199
|
}
|
|
201
200
|
}
|
|
201
|
+
/** Called when the UI layer wants to end the rendering timer */
|
|
202
202
|
renderEnd() {
|
|
203
203
|
if (!this.trackRender) {
|
|
204
|
-
throw new Error(
|
|
204
|
+
throw new Error(
|
|
205
|
+
"Must start the metrics-plugin with render tracking enabled"
|
|
206
|
+
);
|
|
205
207
|
}
|
|
206
208
|
const { flow } = this.metrics;
|
|
207
209
|
if (!flow) {
|
|
@@ -224,26 +226,29 @@ class MetricsCorePlugin {
|
|
|
224
226
|
if (lastUpdate.completed === true) {
|
|
225
227
|
return;
|
|
226
228
|
}
|
|
227
|
-
const update =
|
|
229
|
+
const update = {
|
|
230
|
+
...lastUpdate,
|
|
228
231
|
completed: true,
|
|
229
232
|
endTime,
|
|
230
233
|
duration: endTime - lastUpdate.startTime
|
|
231
|
-
}
|
|
234
|
+
};
|
|
232
235
|
lastItem.updates[lastItem.updates.length - 1] = update;
|
|
233
236
|
this.hooks.onUpdateEnd.call(update, lastItem, this.metrics);
|
|
234
237
|
} else {
|
|
235
|
-
lastItem.render =
|
|
238
|
+
lastItem.render = {
|
|
239
|
+
...lastItem.render,
|
|
236
240
|
completed: true,
|
|
237
241
|
endTime,
|
|
238
242
|
duration: endTime - lastItem.startTime
|
|
239
|
-
}
|
|
243
|
+
};
|
|
240
244
|
this.hooks.onRenderEnd.call(lastItem.render, lastItem, this.metrics);
|
|
241
245
|
if (!interactive.completed) {
|
|
242
|
-
flow.interactive =
|
|
246
|
+
flow.interactive = {
|
|
247
|
+
...interactive,
|
|
243
248
|
completed: true,
|
|
244
249
|
duration: endTime - interactive.startTime,
|
|
245
250
|
endTime
|
|
246
|
-
}
|
|
251
|
+
};
|
|
247
252
|
this.hooks.onInteractive.call(flow.interactive, this.metrics);
|
|
248
253
|
}
|
|
249
254
|
}
|
|
@@ -255,7 +260,7 @@ class MetricsCorePlugin {
|
|
|
255
260
|
this.metrics = {
|
|
256
261
|
flow: {
|
|
257
262
|
id: flow.id,
|
|
258
|
-
requestTime: requestTime
|
|
263
|
+
requestTime: requestTime ?? void 0,
|
|
259
264
|
timeline: [],
|
|
260
265
|
startTime,
|
|
261
266
|
completed: false,
|
|
@@ -271,23 +276,25 @@ class MetricsCorePlugin {
|
|
|
271
276
|
if (state.status === "completed" || state.status === "error") {
|
|
272
277
|
const endTime = defaultGetTime();
|
|
273
278
|
const { flow } = this.metrics;
|
|
274
|
-
if (flow === void 0 ||
|
|
279
|
+
if (flow === void 0 || flow?.completed === true) {
|
|
275
280
|
return;
|
|
276
281
|
}
|
|
277
282
|
this.metrics = {
|
|
278
|
-
flow:
|
|
283
|
+
flow: {
|
|
284
|
+
...flow,
|
|
279
285
|
completed: true,
|
|
280
286
|
endTime,
|
|
281
287
|
duration: endTime - flow.startTime
|
|
282
|
-
}
|
|
288
|
+
}
|
|
283
289
|
};
|
|
284
290
|
const lastUpdate = flow.timeline[flow.timeline.length - 1];
|
|
285
291
|
if (lastUpdate && !lastUpdate.completed) {
|
|
286
|
-
this.metrics.flow.timeline[flow.timeline.length - 1] =
|
|
292
|
+
this.metrics.flow.timeline[flow.timeline.length - 1] = {
|
|
293
|
+
...lastUpdate,
|
|
287
294
|
completed: true,
|
|
288
295
|
endTime,
|
|
289
296
|
duration: endTime - lastUpdate.startTime
|
|
290
|
-
}
|
|
297
|
+
};
|
|
291
298
|
}
|
|
292
299
|
this.hooks.onFlowEnd.call(this.metrics);
|
|
293
300
|
}
|
|
@@ -306,11 +313,12 @@ class MetricsCorePlugin {
|
|
|
306
313
|
if (prev.completed) {
|
|
307
314
|
throw new Error("Completing a state that's already done.");
|
|
308
315
|
}
|
|
309
|
-
timeline[timeline.length - 1] =
|
|
316
|
+
timeline[timeline.length - 1] = {
|
|
317
|
+
...prev,
|
|
310
318
|
completed: true,
|
|
311
319
|
endTime: time,
|
|
312
320
|
duration: time - prev.startTime
|
|
313
|
-
}
|
|
321
|
+
};
|
|
314
322
|
this.hooks.onNodeEnd.call(timeline[timeline.length - 1]);
|
|
315
323
|
}
|
|
316
324
|
const nodeMetrics = {
|
|
@@ -334,16 +342,21 @@ class MetricsCorePlugin {
|
|
|
334
342
|
this.renderStart();
|
|
335
343
|
}
|
|
336
344
|
});
|
|
337
|
-
player.applyTo(
|
|
345
|
+
player.applyTo(
|
|
346
|
+
import_beacon_plugin.BeaconPlugin.Symbol,
|
|
347
|
+
(beaconPlugin) => new MetricsViewBeaconPlugin(this).apply(beaconPlugin)
|
|
348
|
+
);
|
|
338
349
|
}
|
|
339
350
|
}
|
|
340
|
-
}
|
|
351
|
+
};
|
|
341
352
|
MetricsCorePlugin.Symbol = MetricsCorePluginSymbol;
|
|
342
|
-
|
|
343
|
-
exports
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
353
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
354
|
+
0 && (module.exports = {
|
|
355
|
+
MetricsCorePlugin,
|
|
356
|
+
MetricsCorePluginSymbol,
|
|
357
|
+
MetricsViewBeaconPlugin,
|
|
358
|
+
MetricsViewBeaconPluginContextSymbol,
|
|
359
|
+
RequestTimeWebPlugin,
|
|
360
|
+
defaultGetTime
|
|
361
|
+
});
|
|
362
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/metrics/core/src/index.ts","../../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/metrics/core/src/metrics.ts","../../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/plugins/metrics/core/src/symbols.ts"],"sourcesContent":["export * from \"./metrics\";\nexport * from \"./symbols\";\n","import type { Player, PlayerPlugin } from \"@player-ui/player\";\nimport { SyncHook, SyncBailHook } from \"tapable-ts\";\nimport type { BeaconPluginPlugin, BeaconArgs } from \"@player-ui/beacon-plugin\";\nimport { BeaconPlugin } from \"@player-ui/beacon-plugin\";\nimport {\n MetricsCorePluginSymbol,\n MetricsViewBeaconPluginContextSymbol,\n} from \"./symbols\";\n\n// Try to use performance.now() but fall back to Date.now() if you can't\nexport const defaultGetTime =\n typeof performance === \"undefined\"\n ? () => Date.now()\n : () => performance.now();\n\nexport type Timing = {\n /** Time this duration started (ms) */\n startTime: number;\n} & (\n | {\n /** Flag set if this is currently in progress */\n completed: false;\n }\n | {\n /** The stopwatch has stopped */\n completed: true;\n\n /** The time in (ms) that the process ended */\n endTime: number;\n\n /** The elapsed time of this event (ms) */\n duration: number;\n }\n);\n\nexport type NodeMetrics = Timing & {\n /** The type of the flow-state */\n stateType: string;\n\n /** The name of the flow-state */\n stateName: string;\n};\n\nexport type NodeRenderMetrics = NodeMetrics & {\n /** Timing representing the initial render */\n render: Timing;\n\n /** An array of timings representing updates to the view */\n updates: Array<Timing>;\n};\n\nexport interface PlayerFlowMetrics {\n /** All metrics about a running flow */\n flow?: {\n /** The id of the flow these metrics are for */\n id: string;\n\n /** request time */\n requestTime?: number;\n\n /** A timeline of events for each node-state */\n timeline: Array<NodeMetrics | NodeRenderMetrics>;\n\n /** A timing measuring until the first interactive render */\n interactive: Timing;\n } & Timing;\n}\n\nconst callbacks = [\n \"onFlowBegin\",\n \"onFlowEnd\",\n \"onInteractive\",\n \"onNodeStart\",\n \"onNodeEnd\",\n \"onRenderStart\",\n \"onRenderEnd\",\n \"onUpdateStart\",\n \"onUpdateEnd\",\n \"onUpdate\",\n] as const;\n\n/** Context structure for 'viewed' beacons rendering metrics */\nexport interface MetricsViewBeaconPluginContext {\n /** Represents the time taken before the view is first rendered */\n renderTime?: number;\n /** request time */\n requestTime?: number;\n}\n\n/** Simple [BeaconPluginPlugin] that adds renderTime to 'viewed' beacons data */\nexport class MetricsViewBeaconPlugin implements BeaconPluginPlugin {\n static Symbol = MetricsViewBeaconPluginContextSymbol;\n public readonly symbol = MetricsViewBeaconPlugin.Symbol;\n\n private metricsPlugin: MetricsCorePlugin;\n\n private resolvePendingRenderTime: ((renderTime: number) => void) | undefined;\n\n constructor(metricsPlugin: MetricsCorePlugin) {\n this.metricsPlugin = metricsPlugin;\n this.metricsPlugin.hooks.onRenderEnd.tap(\n \"MetricsViewBeaconPlugin\",\n (timing) => {\n if (timing.completed && this.resolvePendingRenderTime) {\n this.resolvePendingRenderTime(timing.duration);\n this.resolvePendingRenderTime = undefined;\n }\n },\n );\n }\n\n apply(beaconPlugin: BeaconPlugin) {\n beaconPlugin.hooks.buildBeacon.intercept({\n context: true,\n call: (context: any, beacon) => {\n if (context && (beacon as BeaconArgs).action === \"viewed\") {\n context[this.symbol] = this.buildContext();\n }\n },\n });\n }\n\n private async buildContext(): Promise<MetricsViewBeaconPluginContext> {\n return {\n renderTime: await this.getRenderTime(),\n requestTime: this.getRequestTime(),\n };\n }\n\n private async getRenderTime(): Promise<number> {\n const { flow } = this.metricsPlugin.getMetrics();\n\n if (flow) {\n const lastItem = flow.timeline[flow.timeline.length - 1];\n\n if (\"render\" in lastItem && lastItem.render.completed) {\n return lastItem.render.duration;\n }\n }\n\n return new Promise((resolve) => {\n this.resolvePendingRenderTime = resolve;\n });\n }\n\n private getRequestTime(): number | undefined {\n const { flow } = this.metricsPlugin.getMetrics();\n\n return flow?.requestTime;\n }\n}\n\nexport interface MetricsWebPluginOptions {\n /** Called when a flow starts */\n onFlowBegin?: (update: PlayerFlowMetrics) => void;\n\n /** Called when a flow ends */\n onFlowEnd?: (update: PlayerFlowMetrics) => void;\n\n /** Called when a flow becomes interactive for the first time */\n onInteractive?: (timing: Timing, update: PlayerFlowMetrics) => void;\n\n /** Called when a new node is started */\n onNodeStart?: (\n nodeMetrics: NodeMetrics | NodeRenderMetrics,\n update: PlayerFlowMetrics,\n ) => void;\n\n /** Called when a node is ended */\n onNodeEnd?: (\n nodeMetrics: NodeMetrics | NodeRenderMetrics,\n update: PlayerFlowMetrics,\n ) => void;\n\n /** Called when rendering for a node begins */\n onRenderStart?: (\n timing: Timing,\n nodeMetrics: NodeRenderMetrics,\n update: PlayerFlowMetrics,\n ) => void;\n\n /** Called when rendering for a node ends */\n onRenderEnd?: (\n timing: Timing,\n nodeMetrics: NodeRenderMetrics,\n update: PlayerFlowMetrics,\n ) => void;\n\n /** Called when an update for a node begins */\n onUpdateStart?: (\n timing: Timing,\n nodeMetrics: NodeRenderMetrics,\n update: PlayerFlowMetrics,\n ) => void;\n\n /** Called when an update for a node ends */\n onUpdateEnd?: (\n timing: Timing,\n nodeMetrics: NodeRenderMetrics,\n update: PlayerFlowMetrics,\n ) => void;\n\n /** Callback to subscribe to updates for any metric */\n onUpdate?: (metrics: PlayerFlowMetrics) => void;\n\n /**\n * A flag to set if you want to track render times for nodes\n * This requires that the UI calls `renderEnd()` when the view is painted.\n */\n trackRenderTime?: boolean;\n\n /**\n * A flag to set if you want to track update times for nodes\n * This requires that the UI calls `renderEnd()` when the view is painted.\n */\n trackUpdateTime?: boolean;\n\n /** A function to get the current time (in ms) */\n getTime?: () => number;\n}\n\n/**\n * A plugin that enables request time metrics\n */\nexport class RequestTimeWebPlugin {\n getRequestTime: () => number | undefined;\n name = \"RequestTimeWebPlugin\";\n\n constructor(getRequestTime: () => number | undefined) {\n this.getRequestTime = getRequestTime;\n }\n\n apply(metricsCorePlugin: MetricsCorePlugin) {\n metricsCorePlugin.hooks.resolveRequestTime.tap(this.name, () => {\n return this.getRequestTime();\n });\n }\n}\n\n/**\n * A plugin that enables gathering of render metrics\n */\nexport class MetricsCorePlugin implements PlayerPlugin {\n name = \"metrics\";\n\n static Symbol = MetricsCorePluginSymbol;\n public readonly symbol = MetricsCorePluginSymbol;\n\n protected trackRender: boolean;\n protected trackUpdate: boolean;\n protected getTime: () => number;\n\n public readonly hooks = {\n resolveRequestTime: new SyncBailHook<[], number>(),\n\n onFlowBegin: new SyncHook<[PlayerFlowMetrics]>(),\n onFlowEnd: new SyncHook<[PlayerFlowMetrics]>(),\n\n onInteractive: new SyncHook<[Timing, PlayerFlowMetrics]>(),\n\n onNodeStart: new SyncHook<[NodeMetrics | NodeRenderMetrics]>(),\n onNodeEnd: new SyncHook<[NodeMetrics | NodeRenderMetrics]>(),\n\n onRenderStart: new SyncHook<\n [Timing, NodeRenderMetrics, PlayerFlowMetrics]\n >(),\n onRenderEnd: new SyncHook<[Timing, NodeRenderMetrics, PlayerFlowMetrics]>(),\n\n onUpdateStart: new SyncHook<\n [Timing, NodeRenderMetrics, PlayerFlowMetrics]\n >(),\n onUpdateEnd: new SyncHook<[Timing, NodeRenderMetrics, PlayerFlowMetrics]>(),\n\n onUpdate: new SyncHook<[PlayerFlowMetrics]>(),\n };\n\n private metrics: PlayerFlowMetrics = {};\n\n constructor(options?: MetricsWebPluginOptions) {\n this.trackRender = options?.trackRenderTime ?? false;\n this.trackUpdate = options?.trackUpdateTime ?? false;\n this.getTime = options?.getTime ?? defaultGetTime;\n\n /** fn to call the update hook */\n const callOnUpdate = () => {\n this.hooks.onUpdate.call(this.metrics);\n };\n\n this.hooks.onFlowBegin.tap(this.name, callOnUpdate);\n this.hooks.onFlowEnd.tap(this.name, callOnUpdate);\n this.hooks.onInteractive.tap(this.name, callOnUpdate);\n this.hooks.onNodeStart.tap(this.name, callOnUpdate);\n this.hooks.onNodeEnd.tap(this.name, callOnUpdate);\n\n this.hooks.onRenderStart.tap(this.name, callOnUpdate);\n this.hooks.onRenderEnd.tap(this.name, callOnUpdate);\n\n this.hooks.onUpdateStart.tap(this.name, callOnUpdate);\n this.hooks.onUpdateEnd.tap(this.name, callOnUpdate);\n\n callbacks.forEach((hookName) => {\n if (options?.[hookName] !== undefined) {\n (this.hooks[hookName] as any).tap(\"options\", options?.[hookName]);\n }\n });\n }\n\n /**\n * Fetch the metrics of the current flow\n */\n public getMetrics(): PlayerFlowMetrics {\n return this.metrics;\n }\n\n /** Called when the UI layer wishes to start a timer for rendering */\n private renderStart(): void {\n // Grab the last update\n const timeline = this.metrics.flow?.timeline;\n\n if (!timeline || timeline.length === 0) {\n return;\n }\n\n const lastItem = timeline[timeline.length - 1];\n\n if (\"updates\" in lastItem) {\n // Get the last update, make sure it's completed\n if (lastItem.updates.length > 0) {\n const lastUpdate = lastItem.updates[lastItem.updates.length - 1];\n\n if (lastUpdate.completed === false) {\n // Starting a new render before the last one was finished.\n // Just ignore it and include as part of 1 render time\n return;\n }\n }\n\n if (!lastItem.render.completed) {\n // Starting a new render before the last one was finished.\n // Just ignore it and include as part of 1 render time\n return;\n }\n\n const update: Timing = {\n completed: false,\n startTime: defaultGetTime(),\n };\n\n lastItem.updates.push(update);\n\n this.hooks.onUpdateStart.call(update, lastItem, this.metrics);\n } else {\n const renderInfo = {\n ...lastItem,\n render: {\n completed: false,\n startTime: defaultGetTime(),\n },\n updates: [],\n } as NodeRenderMetrics;\n\n timeline[timeline.length - 1] = renderInfo;\n\n this.hooks.onRenderStart.call(\n renderInfo.render,\n renderInfo,\n this.metrics,\n );\n }\n }\n\n /** Called when the UI layer wants to end the rendering timer */\n public renderEnd(): void {\n if (!this.trackRender) {\n throw new Error(\n \"Must start the metrics-plugin with render tracking enabled\",\n );\n }\n\n const { flow } = this.metrics;\n\n if (!flow) {\n return;\n }\n\n const { timeline, interactive } = flow;\n\n if (!timeline || !interactive || timeline.length === 0) {\n return;\n }\n\n const lastItem = timeline[timeline.length - 1];\n\n if (!(\"render\" in lastItem)) {\n return;\n }\n\n // Check if this is an update or render\n const endTime = defaultGetTime();\n\n if (lastItem.render.completed) {\n // This is the end of an existing update\n\n if (lastItem.updates.length === 0) {\n // throw new Error(\"Trying to end an update that's not in progress\");\n return;\n }\n\n const lastUpdate = lastItem.updates[lastItem.updates.length - 1];\n\n if (lastUpdate.completed === true) {\n // throw new Error(\"Trying to end an update that's not in progress\");\n return;\n }\n\n const update = {\n ...lastUpdate,\n completed: true,\n endTime,\n duration: endTime - lastUpdate.startTime,\n };\n\n lastItem.updates[lastItem.updates.length - 1] = update;\n this.hooks.onUpdateEnd.call(update, lastItem, this.metrics);\n } else {\n lastItem.render = {\n ...lastItem.render,\n completed: true,\n endTime,\n duration: endTime - lastItem.startTime,\n };\n this.hooks.onRenderEnd.call(lastItem.render, lastItem, this.metrics);\n\n if (!interactive.completed) {\n flow.interactive = {\n ...interactive,\n completed: true,\n duration: endTime - interactive.startTime,\n endTime,\n };\n\n this.hooks.onInteractive.call(flow.interactive, this.metrics);\n }\n }\n }\n\n apply(player: Player): void {\n player.hooks.onStart.tap(this.name, (flow) => {\n const requestTime = this.hooks.resolveRequestTime.call();\n const startTime = defaultGetTime();\n this.metrics = {\n flow: {\n id: flow.id,\n requestTime: requestTime ?? undefined,\n timeline: [],\n startTime,\n completed: false,\n interactive: {\n completed: false,\n startTime,\n },\n },\n };\n\n this.hooks.onFlowBegin.call(this.metrics);\n });\n\n player.hooks.state.tap(this.name, (state) => {\n if (state.status === \"completed\" || state.status === \"error\") {\n const endTime = defaultGetTime();\n const { flow } = this.metrics;\n\n if (flow === undefined || flow?.completed === true) {\n return;\n }\n\n this.metrics = {\n flow: {\n ...flow,\n completed: true,\n endTime,\n duration: endTime - flow.startTime,\n },\n };\n\n // get the last update\n\n const lastUpdate = flow.timeline[flow.timeline.length - 1];\n\n if (lastUpdate && !lastUpdate.completed) {\n (this.metrics.flow as any).timeline[flow.timeline.length - 1] = {\n ...lastUpdate,\n completed: true,\n endTime,\n duration: endTime - lastUpdate.startTime,\n };\n }\n\n this.hooks.onFlowEnd.call(this.metrics);\n }\n });\n\n player.hooks.flowController.tap(this.name, (fc) => {\n fc.hooks.flow.tap(this.name, (f) => {\n f.hooks.transition.tap(this.name, (from, to) => {\n const time = defaultGetTime();\n const { flow } = this.metrics;\n\n if (!flow) {\n return;\n }\n\n const { timeline } = flow;\n\n // End the last state, and start the next one\n\n if (timeline.length > 0) {\n const prev = timeline[timeline.length - 1];\n\n if (prev.completed) {\n throw new Error(\"Completing a state that's already done.\");\n }\n\n timeline[timeline.length - 1] = {\n ...prev,\n completed: true,\n endTime: time,\n duration: time - prev.startTime,\n };\n\n this.hooks.onNodeEnd.call(timeline[timeline.length - 1]);\n }\n\n const nodeMetrics = {\n completed: false,\n startTime: time,\n stateName: to.name,\n stateType: to.value.state_type,\n } as const;\n\n timeline.push(nodeMetrics);\n this.hooks.onNodeStart.call(nodeMetrics);\n });\n });\n });\n\n if (this.trackRender) {\n player.hooks.view.tap(this.name, (v) => {\n if (this.trackUpdate) {\n v.hooks.onUpdate.tap(this.name, () => {\n this.renderStart();\n });\n } else {\n this.renderStart();\n }\n });\n\n player.applyTo<BeaconPlugin>(BeaconPlugin.Symbol, (beaconPlugin) =>\n new MetricsViewBeaconPlugin(this).apply(beaconPlugin),\n );\n }\n }\n}\n\nexport default MetricsCorePlugin;\n","export const MetricsCorePluginSymbol = Symbol.for(\"MetricsCorePlugin\");\nexport const MetricsViewBeaconPluginContextSymbol = Symbol.for(\n \"MetricsViewBeaconPluginContext\",\n);\n"],"mappings":"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","names":[]}
|