@atlaskit/insm 0.1.3 → 0.2.0
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/CHANGELOG.md +11 -0
- package/README.md +3 -0
- package/dist/cjs/insm-period.js +20 -2
- package/dist/cjs/insm-session.js +26 -9
- package/dist/cjs/insm.js +26 -12
- package/dist/cjs/session-measurers/LongAnimationFrameMeasurer.js +76 -34
- package/dist/es2019/insm-period.js +19 -1
- package/dist/es2019/insm-session.js +21 -6
- package/dist/es2019/insm.js +26 -12
- package/dist/es2019/session-measurers/LongAnimationFrameMeasurer.js +61 -34
- package/dist/esm/insm-period.js +19 -1
- package/dist/esm/insm-session.js +26 -9
- package/dist/esm/insm.js +26 -12
- package/dist/esm/session-measurers/LongAnimationFrameMeasurer.js +77 -34
- package/dist/types/insm-period.d.ts +21 -2
- package/dist/types/insm-session.d.ts +8 -0
- package/dist/types/insm.d.ts +11 -4
- package/dist/types/session-measurers/LongAnimationFrameMeasurer.d.ts +26 -24
- package/dist/types/types.d.ts +25 -25
- package/dist/types-ts4.5/insm-period.d.ts +21 -2
- package/dist/types-ts4.5/insm-session.d.ts +8 -0
- package/dist/types-ts4.5/insm.d.ts +11 -4
- package/dist/types-ts4.5/session-measurers/LongAnimationFrameMeasurer.d.ts +26 -24
- package/dist/types-ts4.5/types.d.ts +25 -25
- package/package.json +8 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @atlaskit/insm
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`c6c113481c118`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/c6c113481c118) -
|
|
8
|
+
Updates limited mode to include lcm sizes in decision to engage.
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- Updated dependencies
|
|
13
|
+
|
|
3
14
|
## 0.1.3
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -38,6 +38,9 @@ insm.session.startHeavyTask('paste-handler');
|
|
|
38
38
|
insm.session.endHeavyTask('paste-handler');
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
+
Note: For tracking page initialisation - if you use the special `PageLoad` key, the duration will be
|
|
42
|
+
tracked on the resulting session event.
|
|
43
|
+
|
|
41
44
|
### Adding additional information to the session
|
|
42
45
|
|
|
43
46
|
Additional session information can be added through the `addProperties` api.
|
package/dist/cjs/insm-period.js
CHANGED
|
@@ -8,10 +8,10 @@ exports.PeriodTracking = void 0;
|
|
|
8
8
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
9
9
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
10
10
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
11
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
11
12
|
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
12
13
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
13
|
-
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
14
|
-
/* eslint-disable @repo/internal/dom-events/no-unsafe-event-listeners */
|
|
14
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } /* eslint-disable @repo/internal/dom-events/no-unsafe-event-listeners */
|
|
15
15
|
var PeriodTracking = exports.PeriodTracking = /*#__PURE__*/function () {
|
|
16
16
|
function PeriodTracking(session) {
|
|
17
17
|
(0, _classCallCheck2.default)(this, PeriodTracking);
|
|
@@ -157,6 +157,24 @@ var PeriodTracking = exports.PeriodTracking = /*#__PURE__*/function () {
|
|
|
157
157
|
key: "endResults",
|
|
158
158
|
get: function get() {
|
|
159
159
|
this.changePeriodAndTrackLast(this.state);
|
|
160
|
+
if ((0, _platformFeatureFlags.fg)('cc_editor_insm_fix_attributes')) {
|
|
161
|
+
return {
|
|
162
|
+
active: {
|
|
163
|
+
features: Array.from(this.periodMeasurements.active.features),
|
|
164
|
+
heavyTasks: Array.from(this.periodMeasurements.active.heavyTasks),
|
|
165
|
+
measurements: this.periodMeasurements.active.measurements,
|
|
166
|
+
duration: this.periodMeasurements.active.duration,
|
|
167
|
+
count: this.periodMeasurements.active.count
|
|
168
|
+
},
|
|
169
|
+
inactive: {
|
|
170
|
+
features: Array.from(this.periodMeasurements.inactive.features),
|
|
171
|
+
heavyTasks: Array.from(this.periodMeasurements.inactive.heavyTasks),
|
|
172
|
+
measurements: this.periodMeasurements.inactive.measurements,
|
|
173
|
+
duration: this.periodMeasurements.inactive.duration,
|
|
174
|
+
count: this.periodMeasurements.inactive.count
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
160
178
|
return this.periodMeasurements;
|
|
161
179
|
}
|
|
162
180
|
}, {
|
package/dist/cjs/insm-session.js
CHANGED
|
@@ -21,11 +21,14 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
|
|
|
21
21
|
* Only intended for internal use.
|
|
22
22
|
*
|
|
23
23
|
* Exported for consumers who may require the type.
|
|
24
|
+
*
|
|
25
|
+
* Note: Events are not reliably fired from mobile browsers (ie. when a browser is closed when not in use)
|
|
24
26
|
*/
|
|
25
27
|
var INSMSession = exports.INSMSession = /*#__PURE__*/function () {
|
|
26
28
|
function INSMSession(experienceKey, experienceProperties, insm) {
|
|
27
29
|
(0, _classCallCheck2.default)(this, INSMSession);
|
|
28
30
|
(0, _defineProperty2.default)(this, "startedAt", performance.now());
|
|
31
|
+
(0, _defineProperty2.default)(this, "pageLoadTime", null);
|
|
29
32
|
(0, _defineProperty2.default)(this, "running", true);
|
|
30
33
|
(0, _defineProperty2.default)(this, "addedProperties", []);
|
|
31
34
|
(0, _defineProperty2.default)(this, "runningFeatures", new Set());
|
|
@@ -39,12 +42,18 @@ var INSMSession = exports.INSMSession = /*#__PURE__*/function () {
|
|
|
39
42
|
insmSession: this,
|
|
40
43
|
reportingThreshold: 500
|
|
41
44
|
});
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Note: Events are not reliably fired from mobile browsers (ie. when a browser is closed when not in use)
|
|
45
|
-
*/
|
|
46
45
|
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Completes the page load timing. This is called automatically when ending a heavy task
|
|
49
|
+
* with the key 'PageLoad'.
|
|
50
|
+
*/
|
|
47
51
|
return (0, _createClass2.default)(INSMSession, [{
|
|
52
|
+
key: "completePageLoad",
|
|
53
|
+
value: function completePageLoad() {
|
|
54
|
+
this.pageLoadTime = performance.now() - this.startedAt;
|
|
55
|
+
}
|
|
56
|
+
}, {
|
|
48
57
|
key: "updateExperienceKey",
|
|
49
58
|
value: function updateExperienceKey(experienceKey) {
|
|
50
59
|
this.experienceKey = experienceKey;
|
|
@@ -144,7 +153,7 @@ var INSMSession = exports.INSMSession = /*#__PURE__*/function () {
|
|
|
144
153
|
}, {
|
|
145
154
|
key: "end",
|
|
146
155
|
value: function end(endDetails) {
|
|
147
|
-
var _this$insm$analyticsW;
|
|
156
|
+
var _periodResults$active, _periodResults$active2, _periodResults$active3, _periodResults$active4, _this$insm$analyticsW;
|
|
148
157
|
if (this.running === false) {
|
|
149
158
|
// If an experience has already been ended -- don't repeat the ending
|
|
150
159
|
return;
|
|
@@ -177,19 +186,27 @@ var INSMSession = exports.INSMSession = /*#__PURE__*/function () {
|
|
|
177
186
|
var operationalEvent = {
|
|
178
187
|
actionSubject: 'insm',
|
|
179
188
|
action: 'measured',
|
|
180
|
-
attributes: _objectSpread(_objectSpread({}, evaluatedAddedProperties), {}, {
|
|
189
|
+
attributes: _objectSpread(_objectSpread(_objectSpread({}, evaluatedAddedProperties), {}, {
|
|
181
190
|
experienceKey: this.experienceKey,
|
|
182
191
|
initial: this.experienceProperties.initial,
|
|
183
192
|
contentId: this.experienceProperties.contentId,
|
|
184
193
|
timing: {
|
|
185
194
|
startedAt: this.startedAt,
|
|
195
|
+
// Note: this will not match up with the periods sum of durations, as it includes
|
|
196
|
+
// time paused when heavy tasks were running, and/or the page is in the background.
|
|
186
197
|
duration: duration
|
|
187
198
|
},
|
|
188
199
|
periods: periodResults,
|
|
189
|
-
endDetails: endDetails
|
|
190
|
-
|
|
200
|
+
endDetails: endDetails
|
|
201
|
+
}, (0, _expValEquals.expValEquals)('cc_editor_insm_outlier_events', 'cohort', 'test') ? {
|
|
202
|
+
longScripts: this.longAnimationFrameMeasurer.current,
|
|
203
|
+
pageLoadTime: this.pageLoadTime,
|
|
204
|
+
deviceDetails: getDeviceDetails()
|
|
205
|
+
} : {}), {}, {
|
|
206
|
+
// these health attributes drive our SLOs
|
|
207
|
+
healthAFPS: (_periodResults$active = periodResults.active.measurements.afps) !== null && _periodResults$active !== void 0 && _periodResults$active.average ? ((_periodResults$active2 = periodResults.active.measurements.afps) === null || _periodResults$active2 === void 0 ? void 0 : _periodResults$active2.average) >= 50 : undefined,
|
|
208
|
+
healthINP: (_periodResults$active3 = periodResults.active.measurements.inp) !== null && _periodResults$active3 !== void 0 && _periodResults$active3.average ? ((_periodResults$active4 = periodResults.active.measurements.inp) === null || _periodResults$active4 === void 0 ? void 0 : _periodResults$active4.average) >= 200 : undefined
|
|
191
209
|
}),
|
|
192
|
-
deviceDetails: (0, _expValEquals.expValEquals)('cc_editor_interactivity_monitoring', 'isEnabled', true) ? getDeviceDetails() : undefined,
|
|
193
210
|
highPriority: true,
|
|
194
211
|
tags: ['editor'],
|
|
195
212
|
source: 'unknown'
|
package/dist/cjs/insm.js
CHANGED
|
@@ -11,6 +11,7 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
|
|
|
11
11
|
var _insmSession = require("./insm-session");
|
|
12
12
|
var _afps = require("./period-measurers/afps");
|
|
13
13
|
var _inp = require("./inp-measurers/inp");
|
|
14
|
+
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
14
15
|
var INSM = exports.INSM = /*#__PURE__*/function () {
|
|
15
16
|
function INSM(options) {
|
|
16
17
|
var _this = this;
|
|
@@ -53,15 +54,18 @@ var INSM = exports.INSM = /*#__PURE__*/function () {
|
|
|
53
54
|
* Starts a heavy task in the currently running session.
|
|
54
55
|
*
|
|
55
56
|
* This also pauses measurement.
|
|
57
|
+
*
|
|
58
|
+
* For PageLoads using the key 'PageLoad' will mean the heavy task duration
|
|
59
|
+
* is added to the insm session event as pageLoadTime.
|
|
56
60
|
*/
|
|
57
61
|
return (0, _createClass2.default)(INSM, [{
|
|
58
62
|
key: "startHeavyTask",
|
|
59
63
|
value: function startHeavyTask(heavyTaskName) {
|
|
60
|
-
var _this$runningSession2, _this$runningSession3, _this$
|
|
64
|
+
var _this$runningSession2, _this$runningSession3, _this$runningSession4;
|
|
61
65
|
this.runningHeavyTasks.add(heavyTaskName);
|
|
62
66
|
(_this$runningSession2 = this.runningSession) === null || _this$runningSession2 === void 0 || (_this$runningSession2 = _this$runningSession2.periodTracking) === null || _this$runningSession2 === void 0 || _this$runningSession2.startHeavyTask(heavyTaskName);
|
|
63
67
|
(_this$runningSession3 = this.runningSession) === null || _this$runningSession3 === void 0 || _this$runningSession3.periodTracking.pause(heavyTaskName);
|
|
64
|
-
(_this$
|
|
68
|
+
(_this$runningSession4 = this.runningSession) === null || _this$runningSession4 === void 0 || _this$runningSession4.longAnimationFrameMeasurer.pause();
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
/**
|
|
@@ -70,12 +74,18 @@ var INSM = exports.INSM = /*#__PURE__*/function () {
|
|
|
70
74
|
}, {
|
|
71
75
|
key: "endHeavyTask",
|
|
72
76
|
value: function endHeavyTask(heavyTaskName) {
|
|
73
|
-
var _this$
|
|
77
|
+
var _this$runningSession5;
|
|
74
78
|
this.runningHeavyTasks.delete(heavyTaskName);
|
|
75
|
-
(_this$
|
|
79
|
+
(_this$runningSession5 = this.runningSession) === null || _this$runningSession5 === void 0 || _this$runningSession5.periodTracking.resume(heavyTaskName);
|
|
76
80
|
if (this.runningHeavyTasks.size === 0) {
|
|
77
|
-
var _this$
|
|
78
|
-
(_this$
|
|
81
|
+
var _this$runningSession6;
|
|
82
|
+
(_this$runningSession6 = this.runningSession) === null || _this$runningSession6 === void 0 || _this$runningSession6.longAnimationFrameMeasurer.resume();
|
|
83
|
+
}
|
|
84
|
+
if ((0, _expValEquals.expValEquals)('cc_editor_insm_outlier_events', 'cohort', 'test')) {
|
|
85
|
+
if (heavyTaskName === 'PageLoad') {
|
|
86
|
+
var _this$runningSession7;
|
|
87
|
+
(_this$runningSession7 = this.runningSession) === null || _this$runningSession7 === void 0 || _this$runningSession7.completePageLoad();
|
|
88
|
+
}
|
|
79
89
|
}
|
|
80
90
|
}
|
|
81
91
|
|
|
@@ -83,15 +93,19 @@ var INSM = exports.INSM = /*#__PURE__*/function () {
|
|
|
83
93
|
* Call this when starting a new experience. This is expected to be wired to the product
|
|
84
94
|
* routing solution.
|
|
85
95
|
*
|
|
86
|
-
* It's expected this call will be paired with a `insm.session.startHeavyTask('
|
|
87
|
-
* so that performance degradations linked
|
|
96
|
+
* It's expected this call will be paired with a `insm.session.startHeavyTask('PageLoad')` and
|
|
97
|
+
* subsequent `insm.session.endHeavyTask('PageLoad')` so that performance degradations linked
|
|
98
|
+
* to the page initialisation are excluded from the active interactivity monitoring.
|
|
99
|
+
*
|
|
100
|
+
* Using the key 'PageLoad' is special and will result in the heavy task duration being added to the
|
|
101
|
+
* insm session event as pageLoadTime.
|
|
88
102
|
*
|
|
89
103
|
*
|
|
90
104
|
* ```ts
|
|
91
105
|
* insm.start('edit-page', { initial: true, contentId: '9001' })
|
|
92
|
-
* insm.session.startHeavyTask(''
|
|
106
|
+
* insm.session.startHeavyTask('PageLoad')
|
|
93
107
|
* // ... heavy initialisation work
|
|
94
|
-
* insm.session.endHeavyTask(''
|
|
108
|
+
* insm.session.endHeavyTask('PageLoad')
|
|
95
109
|
* ```
|
|
96
110
|
*/
|
|
97
111
|
}, {
|
|
@@ -138,8 +152,8 @@ var INSM = exports.INSM = /*#__PURE__*/function () {
|
|
|
138
152
|
}, {
|
|
139
153
|
key: "stopEarly",
|
|
140
154
|
value: function stopEarly(reasonKey, description) {
|
|
141
|
-
var _this$
|
|
142
|
-
(_this$
|
|
155
|
+
var _this$runningSession8;
|
|
156
|
+
(_this$runningSession8 = this.runningSession) === null || _this$runningSession8 === void 0 || _this$runningSession8.earlyStop(reasonKey, description);
|
|
143
157
|
}
|
|
144
158
|
|
|
145
159
|
/**
|
|
@@ -8,11 +8,15 @@ exports.LongAnimationFrameMeasurer = void 0;
|
|
|
8
8
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
9
9
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
10
10
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
11
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
12
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
13
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
14
|
+
// Script timing data we want to track
|
|
11
15
|
var LongAnimationFrameMeasurer = exports.LongAnimationFrameMeasurer = /*#__PURE__*/function () {
|
|
12
16
|
function LongAnimationFrameMeasurer(options) {
|
|
13
17
|
var _this = this;
|
|
14
18
|
(0, _classCallCheck2.default)(this, LongAnimationFrameMeasurer);
|
|
15
|
-
(0, _defineProperty2.default)(this, "
|
|
19
|
+
(0, _defineProperty2.default)(this, "longestScriptTimings", []);
|
|
16
20
|
(0, _defineProperty2.default)(this, "minimumIndex", -1);
|
|
17
21
|
(0, _defineProperty2.default)(this, "minimumDuration", Infinity);
|
|
18
22
|
this.options = options;
|
|
@@ -33,48 +37,85 @@ var LongAnimationFrameMeasurer = exports.LongAnimationFrameMeasurer = /*#__PURE_
|
|
|
33
37
|
return (0, _createClass2.default)(LongAnimationFrameMeasurer, [{
|
|
34
38
|
key: "handleBatch",
|
|
35
39
|
value: function handleBatch(batch) {
|
|
36
|
-
var len = this.longestAnimationFrames.length;
|
|
37
40
|
for (var batchIndex = 0; batchIndex < batch.length; batchIndex++) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
var animationFrame = batch[batchIndex];
|
|
42
|
+
|
|
43
|
+
// Only process frames that exceed the reporting threshold
|
|
44
|
+
if (animationFrame.duration < this.options.reportingThreshold) {
|
|
41
45
|
continue;
|
|
42
46
|
}
|
|
43
|
-
var longAnimationFrameEntry = Object.assign(batch[batchIndex], {
|
|
44
|
-
runningFeatures: Array.from(this.options.insmSession.runningFeatures)
|
|
45
|
-
});
|
|
46
47
|
|
|
47
|
-
//
|
|
48
|
-
if (
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
// Process all scripts in this long animation frame
|
|
49
|
+
if (animationFrame.scripts && animationFrame.scripts.length > 0) {
|
|
50
|
+
var _iterator = _createForOfIteratorHelper(animationFrame.scripts),
|
|
51
|
+
_step;
|
|
52
|
+
try {
|
|
53
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
54
|
+
var script = _step.value;
|
|
55
|
+
this.processScript(script, animationFrame);
|
|
56
|
+
}
|
|
57
|
+
} catch (err) {
|
|
58
|
+
_iterator.e(err);
|
|
59
|
+
} finally {
|
|
60
|
+
_iterator.f();
|
|
53
61
|
}
|
|
54
|
-
len++;
|
|
55
|
-
continue;
|
|
56
62
|
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}, {
|
|
66
|
+
key: "createScriptTiming",
|
|
67
|
+
value: function createScriptTiming(script, animationFrame) {
|
|
68
|
+
return {
|
|
69
|
+
duration: script.duration,
|
|
70
|
+
forcedStyleAndLayoutDuration: script.forcedStyleAndLayoutDuration,
|
|
71
|
+
invoker: script.invoker,
|
|
72
|
+
invokerType: script.invokerType,
|
|
73
|
+
sourceCharPosition: script.sourceCharPosition,
|
|
74
|
+
sourceFunctionName: script.sourceFunctionName,
|
|
75
|
+
sourceURL: script.sourceURL,
|
|
76
|
+
features: Array.from(this.options.insmSession.runningFeatures),
|
|
77
|
+
afDuration: animationFrame.duration
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}, {
|
|
81
|
+
key: "processScript",
|
|
82
|
+
value: function processScript(script, animationFrame) {
|
|
83
|
+
var scriptDuration = script.duration;
|
|
84
|
+
var len = this.longestScriptTimings.length;
|
|
57
85
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
86
|
+
// Not yet at capacity: append and update min tracking incrementally
|
|
87
|
+
if (len < this.options.limit) {
|
|
88
|
+
var _scriptTiming = this.createScriptTiming(script, animationFrame);
|
|
89
|
+
this.longestScriptTimings[len] = _scriptTiming;
|
|
90
|
+
if (len === 0 || scriptDuration < this.minimumDuration) {
|
|
91
|
+
this.minimumDuration = scriptDuration;
|
|
92
|
+
this.minimumIndex = len;
|
|
61
93
|
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
62
96
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (this.longestAnimationFrames[i].duration < _possibleNewMinimumDuration) {
|
|
69
|
-
_possiblyNewMinimumIndex = i;
|
|
70
|
-
_possibleNewMinimumDuration = this.longestAnimationFrames[i].duration;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
97
|
+
// At capacity: only do work if we beat the current min
|
|
98
|
+
if (scriptDuration <= this.minimumDuration) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
var scriptTiming = this.createScriptTiming(script, animationFrame);
|
|
73
102
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
103
|
+
// Replace the current min
|
|
104
|
+
this.longestScriptTimings[this.minimumIndex] = scriptTiming;
|
|
105
|
+
|
|
106
|
+
// Find new minimum
|
|
107
|
+
var newMinimumIndex = 0;
|
|
108
|
+
var newMinimumDuration = this.longestScriptTimings[0].duration;
|
|
109
|
+
for (var i = 1; i < this.options.limit; i++) {
|
|
110
|
+
if (this.longestScriptTimings[i].duration < newMinimumDuration) {
|
|
111
|
+
newMinimumIndex = i;
|
|
112
|
+
newMinimumDuration = this.longestScriptTimings[i].duration;
|
|
113
|
+
}
|
|
77
114
|
}
|
|
115
|
+
|
|
116
|
+
// Update the min tracking
|
|
117
|
+
this.minimumIndex = newMinimumIndex;
|
|
118
|
+
this.minimumDuration = newMinimumDuration;
|
|
78
119
|
}
|
|
79
120
|
|
|
80
121
|
/**
|
|
@@ -96,12 +137,12 @@ var LongAnimationFrameMeasurer = exports.LongAnimationFrameMeasurer = /*#__PURE_
|
|
|
96
137
|
}
|
|
97
138
|
|
|
98
139
|
/**
|
|
99
|
-
* Returns the current tracked longest
|
|
140
|
+
* Returns the current tracked longest script timings sorted by duration
|
|
100
141
|
*/
|
|
101
142
|
}, {
|
|
102
143
|
key: "current",
|
|
103
144
|
get: function get() {
|
|
104
|
-
var copy = this.
|
|
145
|
+
var copy = this.longestScriptTimings.slice();
|
|
105
146
|
copy.sort(function (a, b) {
|
|
106
147
|
return b.duration - a.duration;
|
|
107
148
|
});
|
|
@@ -119,4 +160,5 @@ var LongAnimationFrameMeasurer = exports.LongAnimationFrameMeasurer = /*#__PURE_
|
|
|
119
160
|
}
|
|
120
161
|
}]);
|
|
121
162
|
}(); // Based on https://github.com/GoogleChrome/web-vitals/blob/1b872cf5f2159e8ace0e98d55d8eb54fb09adfbe/src/types.ts#L129
|
|
163
|
+
// exported for use in test file
|
|
122
164
|
// Based on https://github.com/GoogleChrome/web-vitals/blob/1b872cf5f2159e8ace0e98d55d8eb54fb09adfbe/src/types.ts#L129
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
/* eslint-disable @repo/internal/dom-events/no-unsafe-event-listeners */
|
|
3
|
-
|
|
3
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
4
4
|
export class PeriodTracking {
|
|
5
5
|
constructor(session) {
|
|
6
6
|
_defineProperty(this, "periodMeasurements", {
|
|
@@ -106,6 +106,24 @@ export class PeriodTracking {
|
|
|
106
106
|
}
|
|
107
107
|
get endResults() {
|
|
108
108
|
this.changePeriodAndTrackLast(this.state);
|
|
109
|
+
if (fg('cc_editor_insm_fix_attributes')) {
|
|
110
|
+
return {
|
|
111
|
+
active: {
|
|
112
|
+
features: Array.from(this.periodMeasurements.active.features),
|
|
113
|
+
heavyTasks: Array.from(this.periodMeasurements.active.heavyTasks),
|
|
114
|
+
measurements: this.periodMeasurements.active.measurements,
|
|
115
|
+
duration: this.periodMeasurements.active.duration,
|
|
116
|
+
count: this.periodMeasurements.active.count
|
|
117
|
+
},
|
|
118
|
+
inactive: {
|
|
119
|
+
features: Array.from(this.periodMeasurements.inactive.features),
|
|
120
|
+
heavyTasks: Array.from(this.periodMeasurements.inactive.heavyTasks),
|
|
121
|
+
measurements: this.periodMeasurements.inactive.measurements,
|
|
122
|
+
duration: this.periodMeasurements.inactive.duration,
|
|
123
|
+
count: this.periodMeasurements.inactive.count
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
109
127
|
return this.periodMeasurements;
|
|
110
128
|
}
|
|
111
129
|
setupActiveStartInteractionListeners() {
|
|
@@ -8,10 +8,13 @@ import { LongAnimationFrameMeasurer } from './session-measurers/LongAnimationFra
|
|
|
8
8
|
* Only intended for internal use.
|
|
9
9
|
*
|
|
10
10
|
* Exported for consumers who may require the type.
|
|
11
|
+
*
|
|
12
|
+
* Note: Events are not reliably fired from mobile browsers (ie. when a browser is closed when not in use)
|
|
11
13
|
*/
|
|
12
14
|
export class INSMSession {
|
|
13
15
|
constructor(experienceKey, experienceProperties, insm) {
|
|
14
16
|
_defineProperty(this, "startedAt", performance.now());
|
|
17
|
+
_defineProperty(this, "pageLoadTime", null);
|
|
15
18
|
_defineProperty(this, "running", true);
|
|
16
19
|
_defineProperty(this, "addedProperties", []);
|
|
17
20
|
_defineProperty(this, "runningFeatures", new Set());
|
|
@@ -25,10 +28,14 @@ export class INSMSession {
|
|
|
25
28
|
insmSession: this,
|
|
26
29
|
reportingThreshold: 500
|
|
27
30
|
});
|
|
31
|
+
}
|
|
28
32
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Completes the page load timing. This is called automatically when ending a heavy task
|
|
35
|
+
* with the key 'PageLoad'.
|
|
36
|
+
*/
|
|
37
|
+
completePageLoad() {
|
|
38
|
+
this.pageLoadTime = performance.now() - this.startedAt;
|
|
32
39
|
}
|
|
33
40
|
updateExperienceKey(experienceKey) {
|
|
34
41
|
this.experienceKey = experienceKey;
|
|
@@ -116,7 +123,7 @@ export class INSMSession {
|
|
|
116
123
|
});
|
|
117
124
|
}
|
|
118
125
|
end(endDetails) {
|
|
119
|
-
var _this$insm$analyticsW;
|
|
126
|
+
var _periodResults$active, _periodResults$active2, _periodResults$active3, _periodResults$active4, _this$insm$analyticsW;
|
|
120
127
|
if (this.running === false) {
|
|
121
128
|
// If an experience has already been ended -- don't repeat the ending
|
|
122
129
|
return;
|
|
@@ -148,13 +155,21 @@ export class INSMSession {
|
|
|
148
155
|
contentId: this.experienceProperties.contentId,
|
|
149
156
|
timing: {
|
|
150
157
|
startedAt: this.startedAt,
|
|
158
|
+
// Note: this will not match up with the periods sum of durations, as it includes
|
|
159
|
+
// time paused when heavy tasks were running, and/or the page is in the background.
|
|
151
160
|
duration
|
|
152
161
|
},
|
|
153
162
|
periods: periodResults,
|
|
154
163
|
endDetails: endDetails,
|
|
155
|
-
|
|
164
|
+
...(expValEquals('cc_editor_insm_outlier_events', 'cohort', 'test') ? {
|
|
165
|
+
longScripts: this.longAnimationFrameMeasurer.current,
|
|
166
|
+
pageLoadTime: this.pageLoadTime,
|
|
167
|
+
deviceDetails: getDeviceDetails()
|
|
168
|
+
} : {}),
|
|
169
|
+
// these health attributes drive our SLOs
|
|
170
|
+
healthAFPS: (_periodResults$active = periodResults.active.measurements.afps) !== null && _periodResults$active !== void 0 && _periodResults$active.average ? ((_periodResults$active2 = periodResults.active.measurements.afps) === null || _periodResults$active2 === void 0 ? void 0 : _periodResults$active2.average) >= 50 : undefined,
|
|
171
|
+
healthINP: (_periodResults$active3 = periodResults.active.measurements.inp) !== null && _periodResults$active3 !== void 0 && _periodResults$active3.average ? ((_periodResults$active4 = periodResults.active.measurements.inp) === null || _periodResults$active4 === void 0 ? void 0 : _periodResults$active4.average) >= 200 : undefined
|
|
156
172
|
},
|
|
157
|
-
deviceDetails: expValEquals('cc_editor_interactivity_monitoring', 'isEnabled', true) ? getDeviceDetails() : undefined,
|
|
158
173
|
highPriority: true,
|
|
159
174
|
tags: ['editor'],
|
|
160
175
|
source: 'unknown'
|
package/dist/es2019/insm.js
CHANGED
|
@@ -2,6 +2,7 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
|
2
2
|
import { INSMSession } from './insm-session';
|
|
3
3
|
import { AnimationFPSIM } from './period-measurers/afps';
|
|
4
4
|
import { INPTracker } from './inp-measurers/inp';
|
|
5
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
5
6
|
export class INSM {
|
|
6
7
|
constructor(options) {
|
|
7
8
|
/**
|
|
@@ -40,25 +41,34 @@ export class INSM {
|
|
|
40
41
|
* Starts a heavy task in the currently running session.
|
|
41
42
|
*
|
|
42
43
|
* This also pauses measurement.
|
|
44
|
+
*
|
|
45
|
+
* For PageLoads using the key 'PageLoad' will mean the heavy task duration
|
|
46
|
+
* is added to the insm session event as pageLoadTime.
|
|
43
47
|
*/
|
|
44
48
|
startHeavyTask(heavyTaskName) {
|
|
45
|
-
var _this$runningSession2, _this$runningSession3, _this$runningSession4, _this$
|
|
49
|
+
var _this$runningSession2, _this$runningSession3, _this$runningSession4, _this$runningSession5;
|
|
46
50
|
this.runningHeavyTasks.add(heavyTaskName);
|
|
47
51
|
(_this$runningSession2 = this.runningSession) === null || _this$runningSession2 === void 0 ? void 0 : (_this$runningSession3 = _this$runningSession2.periodTracking) === null || _this$runningSession3 === void 0 ? void 0 : _this$runningSession3.startHeavyTask(heavyTaskName);
|
|
48
52
|
(_this$runningSession4 = this.runningSession) === null || _this$runningSession4 === void 0 ? void 0 : _this$runningSession4.periodTracking.pause(heavyTaskName);
|
|
49
|
-
(_this$
|
|
53
|
+
(_this$runningSession5 = this.runningSession) === null || _this$runningSession5 === void 0 ? void 0 : _this$runningSession5.longAnimationFrameMeasurer.pause();
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
/**
|
|
53
57
|
* Ends a heavy task in the currently running session
|
|
54
58
|
*/
|
|
55
59
|
endHeavyTask(heavyTaskName) {
|
|
56
|
-
var _this$
|
|
60
|
+
var _this$runningSession6;
|
|
57
61
|
this.runningHeavyTasks.delete(heavyTaskName);
|
|
58
|
-
(_this$
|
|
62
|
+
(_this$runningSession6 = this.runningSession) === null || _this$runningSession6 === void 0 ? void 0 : _this$runningSession6.periodTracking.resume(heavyTaskName);
|
|
59
63
|
if (this.runningHeavyTasks.size === 0) {
|
|
60
|
-
var _this$
|
|
61
|
-
(_this$
|
|
64
|
+
var _this$runningSession7;
|
|
65
|
+
(_this$runningSession7 = this.runningSession) === null || _this$runningSession7 === void 0 ? void 0 : _this$runningSession7.longAnimationFrameMeasurer.resume();
|
|
66
|
+
}
|
|
67
|
+
if (expValEquals('cc_editor_insm_outlier_events', 'cohort', 'test')) {
|
|
68
|
+
if (heavyTaskName === 'PageLoad') {
|
|
69
|
+
var _this$runningSession8;
|
|
70
|
+
(_this$runningSession8 = this.runningSession) === null || _this$runningSession8 === void 0 ? void 0 : _this$runningSession8.completePageLoad();
|
|
71
|
+
}
|
|
62
72
|
}
|
|
63
73
|
}
|
|
64
74
|
|
|
@@ -66,15 +76,19 @@ export class INSM {
|
|
|
66
76
|
* Call this when starting a new experience. This is expected to be wired to the product
|
|
67
77
|
* routing solution.
|
|
68
78
|
*
|
|
69
|
-
* It's expected this call will be paired with a `insm.session.startHeavyTask('
|
|
70
|
-
* so that performance degradations linked
|
|
79
|
+
* It's expected this call will be paired with a `insm.session.startHeavyTask('PageLoad')` and
|
|
80
|
+
* subsequent `insm.session.endHeavyTask('PageLoad')` so that performance degradations linked
|
|
81
|
+
* to the page initialisation are excluded from the active interactivity monitoring.
|
|
82
|
+
*
|
|
83
|
+
* Using the key 'PageLoad' is special and will result in the heavy task duration being added to the
|
|
84
|
+
* insm session event as pageLoadTime.
|
|
71
85
|
*
|
|
72
86
|
*
|
|
73
87
|
* ```ts
|
|
74
88
|
* insm.start('edit-page', { initial: true, contentId: '9001' })
|
|
75
|
-
* insm.session.startHeavyTask(''
|
|
89
|
+
* insm.session.startHeavyTask('PageLoad')
|
|
76
90
|
* // ... heavy initialisation work
|
|
77
|
-
* insm.session.endHeavyTask(''
|
|
91
|
+
* insm.session.endHeavyTask('PageLoad')
|
|
78
92
|
* ```
|
|
79
93
|
*/
|
|
80
94
|
start(experienceKey, experienceProperties) {
|
|
@@ -114,8 +128,8 @@ export class INSM {
|
|
|
114
128
|
* scenarios such as when error boundaries are hit.
|
|
115
129
|
*/
|
|
116
130
|
stopEarly(reasonKey, description) {
|
|
117
|
-
var _this$
|
|
118
|
-
(_this$
|
|
131
|
+
var _this$runningSession9;
|
|
132
|
+
(_this$runningSession9 = this.runningSession) === null || _this$runningSession9 === void 0 ? void 0 : _this$runningSession9.earlyStop(reasonKey, description);
|
|
119
133
|
}
|
|
120
134
|
|
|
121
135
|
/**
|