@atlaskit/insm 0.1.2 → 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 +17 -0
- package/README.md +17 -0
- package/dist/cjs/index.js +5 -2
- package/dist/cjs/insm-period.js +20 -2
- package/dist/cjs/insm-session.js +82 -8
- package/dist/cjs/insm.js +49 -9
- package/dist/cjs/session-measurers/LongAnimationFrameMeasurer.js +164 -0
- package/dist/es2019/index.js +5 -2
- package/dist/es2019/insm-period.js +19 -1
- package/dist/es2019/insm-session.js +77 -5
- package/dist/es2019/insm.js +46 -9
- package/dist/es2019/session-measurers/LongAnimationFrameMeasurer.js +128 -0
- package/dist/esm/index.js +5 -2
- package/dist/esm/insm-period.js +19 -1
- package/dist/esm/insm-session.js +84 -8
- package/dist/esm/insm.js +49 -9
- package/dist/esm/session-measurers/LongAnimationFrameMeasurer.js +161 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/insm-period.d.ts +21 -2
- package/dist/types/insm-session.d.ts +13 -2
- package/dist/types/insm.d.ts +18 -4
- package/dist/types/session-measurers/LongAnimationFrameMeasurer.d.ts +63 -0
- package/dist/types/types.d.ts +25 -25
- package/dist/types-ts4.5/index.d.ts +1 -1
- package/dist/types-ts4.5/insm-period.d.ts +21 -2
- package/dist/types-ts4.5/insm-session.d.ts +13 -2
- package/dist/types-ts4.5/insm.d.ts +18 -4
- package/dist/types-ts4.5/session-measurers/LongAnimationFrameMeasurer.d.ts +63 -0
- package/dist/types-ts4.5/types.d.ts +25 -25
- package/package.json +11 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
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
|
+
|
|
14
|
+
## 0.1.3
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Updated dependencies
|
|
19
|
+
|
|
3
20
|
## 0.1.2
|
|
4
21
|
|
|
5
22
|
### 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.
|
|
@@ -169,6 +172,20 @@ insm.start(experienceKey, {
|
|
|
169
172
|
Note: calling this will end any existing experience (unless the experience key and properties
|
|
170
173
|
match - in which case no session change will occur).
|
|
171
174
|
|
|
175
|
+
#### Updating a page session experienceKey after it's started
|
|
176
|
+
|
|
177
|
+
In some scenarios you may need to update the running sessions experience key after it has started,
|
|
178
|
+
in these cases you can use `overrideExperienceKey`.
|
|
179
|
+
|
|
180
|
+
If there is a running experience, it will update the running experiences name.
|
|
181
|
+
|
|
182
|
+
If there is no running experience (ie. if the original experienceKey had not been whitelisted), it
|
|
183
|
+
will start a new experience using the last started experienceProperties.
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
insm.overrideExperienceKey('new-key');
|
|
187
|
+
```
|
|
188
|
+
|
|
172
189
|
#### Naming guidance
|
|
173
190
|
|
|
174
191
|
Choose an `experienceKey` that reflects the product and content type you want to analyze.
|
package/dist/cjs/index.js
CHANGED
|
@@ -16,8 +16,6 @@ function init(options) {
|
|
|
16
16
|
}
|
|
17
17
|
function insmInitialised() {
|
|
18
18
|
if (!initialisedInsm) {
|
|
19
|
-
// eslint-disable-next-line no-console
|
|
20
|
-
console.error('INSM used when not initialised');
|
|
21
19
|
return false;
|
|
22
20
|
}
|
|
23
21
|
return true;
|
|
@@ -42,6 +40,11 @@ var insm = exports.insm = {
|
|
|
42
40
|
initialisedInsm.start(experienceKey, experienceProperties);
|
|
43
41
|
}
|
|
44
42
|
},
|
|
43
|
+
overrideExperienceKey: function overrideExperienceKey(experienceKey) {
|
|
44
|
+
if (insmInitialised()) {
|
|
45
|
+
initialisedInsm.overrideExperienceKey(experienceKey);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
45
48
|
stopEarly: function stopEarly(reasonKey, description) {
|
|
46
49
|
if (insmInitialised()) {
|
|
47
50
|
initialisedInsm.stopEarly(reasonKey, description);
|
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
|
@@ -8,7 +8,10 @@ exports.INSMSession = 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 _bowserUltralight = _interopRequireDefault(require("bowser-ultralight"));
|
|
12
|
+
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
11
13
|
var _insmPeriod = require("./insm-period");
|
|
14
|
+
var _LongAnimationFrameMeasurer = require("./session-measurers/LongAnimationFrameMeasurer");
|
|
12
15
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
13
16
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
14
17
|
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; } } }; }
|
|
@@ -18,11 +21,14 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
|
|
|
18
21
|
* Only intended for internal use.
|
|
19
22
|
*
|
|
20
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)
|
|
21
26
|
*/
|
|
22
27
|
var INSMSession = exports.INSMSession = /*#__PURE__*/function () {
|
|
23
28
|
function INSMSession(experienceKey, experienceProperties, insm) {
|
|
24
29
|
(0, _classCallCheck2.default)(this, INSMSession);
|
|
25
30
|
(0, _defineProperty2.default)(this, "startedAt", performance.now());
|
|
31
|
+
(0, _defineProperty2.default)(this, "pageLoadTime", null);
|
|
26
32
|
(0, _defineProperty2.default)(this, "running", true);
|
|
27
33
|
(0, _defineProperty2.default)(this, "addedProperties", []);
|
|
28
34
|
(0, _defineProperty2.default)(this, "runningFeatures", new Set());
|
|
@@ -30,16 +36,33 @@ var INSMSession = exports.INSMSession = /*#__PURE__*/function () {
|
|
|
30
36
|
this.experienceProperties = experienceProperties;
|
|
31
37
|
this.insm = insm;
|
|
32
38
|
this.periodTracking = new _insmPeriod.PeriodTracking(this);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
this.longAnimationFrameMeasurer = new _LongAnimationFrameMeasurer.LongAnimationFrameMeasurer({
|
|
40
|
+
initial: this.experienceProperties.initial,
|
|
41
|
+
limit: 3,
|
|
42
|
+
insmSession: this,
|
|
43
|
+
reportingThreshold: 500
|
|
44
|
+
});
|
|
37
45
|
}
|
|
38
46
|
|
|
39
47
|
/**
|
|
40
|
-
*
|
|
48
|
+
* Completes the page load timing. This is called automatically when ending a heavy task
|
|
49
|
+
* with the key 'PageLoad'.
|
|
41
50
|
*/
|
|
42
51
|
return (0, _createClass2.default)(INSMSession, [{
|
|
52
|
+
key: "completePageLoad",
|
|
53
|
+
value: function completePageLoad() {
|
|
54
|
+
this.pageLoadTime = performance.now() - this.startedAt;
|
|
55
|
+
}
|
|
56
|
+
}, {
|
|
57
|
+
key: "updateExperienceKey",
|
|
58
|
+
value: function updateExperienceKey(experienceKey) {
|
|
59
|
+
this.experienceKey = experienceKey;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Adds a feature to the currently running session
|
|
64
|
+
*/
|
|
65
|
+
}, {
|
|
43
66
|
key: "startFeature",
|
|
44
67
|
value: function startFeature(featureName) {
|
|
45
68
|
var _this$periodTracking;
|
|
@@ -130,7 +153,7 @@ var INSMSession = exports.INSMSession = /*#__PURE__*/function () {
|
|
|
130
153
|
}, {
|
|
131
154
|
key: "end",
|
|
132
155
|
value: function end(endDetails) {
|
|
133
|
-
var _this$insm$analyticsW;
|
|
156
|
+
var _periodResults$active, _periodResults$active2, _periodResults$active3, _periodResults$active4, _this$insm$analyticsW;
|
|
134
157
|
if (this.running === false) {
|
|
135
158
|
// If an experience has already been ended -- don't repeat the ending
|
|
136
159
|
return;
|
|
@@ -163,22 +186,73 @@ var INSMSession = exports.INSMSession = /*#__PURE__*/function () {
|
|
|
163
186
|
var operationalEvent = {
|
|
164
187
|
actionSubject: 'insm',
|
|
165
188
|
action: 'measured',
|
|
166
|
-
attributes: _objectSpread(_objectSpread({}, evaluatedAddedProperties), {}, {
|
|
189
|
+
attributes: _objectSpread(_objectSpread(_objectSpread({}, evaluatedAddedProperties), {}, {
|
|
167
190
|
experienceKey: this.experienceKey,
|
|
168
191
|
initial: this.experienceProperties.initial,
|
|
169
192
|
contentId: this.experienceProperties.contentId,
|
|
170
193
|
timing: {
|
|
171
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.
|
|
172
197
|
duration: duration
|
|
173
198
|
},
|
|
174
199
|
periods: periodResults,
|
|
175
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
|
|
176
209
|
}),
|
|
177
210
|
highPriority: true,
|
|
178
211
|
tags: ['editor'],
|
|
179
212
|
source: 'unknown'
|
|
180
213
|
};
|
|
181
214
|
(_this$insm$analyticsW = this.insm.analyticsWebClient) === null || _this$insm$analyticsW === void 0 || _this$insm$analyticsW.sendOperationalEvent(operationalEvent);
|
|
215
|
+
this.longAnimationFrameMeasurer.cleanup();
|
|
182
216
|
}
|
|
183
217
|
}]);
|
|
184
|
-
}();
|
|
218
|
+
}(); // Functionality vendored from UFO
|
|
219
|
+
function getDeviceDetails() {
|
|
220
|
+
var _navigator$connection, _navigator$connection2, _navigator$connection3;
|
|
221
|
+
var telemetry = {};
|
|
222
|
+
|
|
223
|
+
// /platform/packages/data/ufo-internal/src/core/publisher/plugins/browser.ts
|
|
224
|
+
if (_bowserUltralight.default.getParser) {
|
|
225
|
+
var _ref;
|
|
226
|
+
var browser = _bowserUltralight.default.getParser(((_ref = typeof window !== 'undefined' && !!window ? window : undefined) === null || _ref === void 0 || (_ref = _ref.navigator) === null || _ref === void 0 ? void 0 : _ref.userAgent) || '');
|
|
227
|
+
Object.assign(telemetry, {
|
|
228
|
+
'event:browser:name': browser.getBrowserName(),
|
|
229
|
+
'event:browser:version': browser.getBrowserVersion()
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// /platform/packages/data/ufo-internal/src/core/publisher/plugins/cpus.ts
|
|
234
|
+
Object.assign(telemetry, {
|
|
235
|
+
'event:cpus': navigator.hardwareConcurrency
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// /platform/packages/data/ufo-internal/src/core/publisher/plugins/memory.ts
|
|
239
|
+
// @ts-ignore: deviceMemory is exposed in some browsers
|
|
240
|
+
Object.assign(telemetry, {
|
|
241
|
+
'event:memory': navigator.deviceMemory
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// /platform/packages/data/ufo-internal/src/core/publisher/plugins/network.ts
|
|
245
|
+
Object.assign(telemetry, {
|
|
246
|
+
// Network
|
|
247
|
+
// @ts-ignore: connection is available in some browsers
|
|
248
|
+
// eslint-disable-next-line compat/compat
|
|
249
|
+
'event:network:effectiveType': (_navigator$connection = navigator.connection) === null || _navigator$connection === void 0 ? void 0 : _navigator$connection.effectiveType,
|
|
250
|
+
// @ts-ignore: connection is available in some browsers
|
|
251
|
+
// eslint-disable-next-line compat/compat
|
|
252
|
+
'event:network:rtt': (_navigator$connection2 = navigator.connection) === null || _navigator$connection2 === void 0 ? void 0 : _navigator$connection2.rtt,
|
|
253
|
+
// @ts-ignore: connection is available in some browsers
|
|
254
|
+
// eslint-disable-next-line compat/compat
|
|
255
|
+
'event:network:downlink': (_navigator$connection3 = navigator.connection) === null || _navigator$connection3 === void 0 ? void 0 : _navigator$connection3.downlink
|
|
256
|
+
});
|
|
257
|
+
return telemetry;
|
|
258
|
+
}
|
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,14 +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;
|
|
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);
|
|
68
|
+
(_this$runningSession4 = this.runningSession) === null || _this$runningSession4 === void 0 || _this$runningSession4.longAnimationFrameMeasurer.pause();
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
/**
|
|
@@ -69,24 +74,38 @@ var INSM = exports.INSM = /*#__PURE__*/function () {
|
|
|
69
74
|
}, {
|
|
70
75
|
key: "endHeavyTask",
|
|
71
76
|
value: function endHeavyTask(heavyTaskName) {
|
|
72
|
-
var _this$
|
|
77
|
+
var _this$runningSession5;
|
|
73
78
|
this.runningHeavyTasks.delete(heavyTaskName);
|
|
74
|
-
(_this$
|
|
79
|
+
(_this$runningSession5 = this.runningSession) === null || _this$runningSession5 === void 0 || _this$runningSession5.periodTracking.resume(heavyTaskName);
|
|
80
|
+
if (this.runningHeavyTasks.size === 0) {
|
|
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
|
+
}
|
|
89
|
+
}
|
|
75
90
|
}
|
|
76
91
|
|
|
77
92
|
/**
|
|
78
93
|
* Call this when starting a new experience. This is expected to be wired to the product
|
|
79
94
|
* routing solution.
|
|
80
95
|
*
|
|
81
|
-
* It's expected this call will be paired with a `insm.session.startHeavyTask('
|
|
82
|
-
* 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.
|
|
83
102
|
*
|
|
84
103
|
*
|
|
85
104
|
* ```ts
|
|
86
105
|
* insm.start('edit-page', { initial: true, contentId: '9001' })
|
|
87
|
-
* insm.session.startHeavyTask(''
|
|
106
|
+
* insm.session.startHeavyTask('PageLoad')
|
|
88
107
|
* // ... heavy initialisation work
|
|
89
|
-
* insm.session.endHeavyTask(''
|
|
108
|
+
* insm.session.endHeavyTask('PageLoad')
|
|
90
109
|
* ```
|
|
91
110
|
*/
|
|
92
111
|
}, {
|
|
@@ -100,10 +119,31 @@ var INSM = exports.INSM = /*#__PURE__*/function () {
|
|
|
100
119
|
contentId: experienceProperties.contentId
|
|
101
120
|
});
|
|
102
121
|
}
|
|
122
|
+
this.lastStartedExperienceProperties = experienceProperties;
|
|
103
123
|
if ((_this$options$experie = this.options.experiences[experienceKey]) !== null && _this$options$experie !== void 0 && _this$options$experie.enabled) {
|
|
104
124
|
this.runningSession = new _insmSession.INSMSession(experienceKey, experienceProperties, this);
|
|
105
125
|
}
|
|
106
126
|
}
|
|
127
|
+
}, {
|
|
128
|
+
key: "overrideExperienceKey",
|
|
129
|
+
value:
|
|
130
|
+
/**
|
|
131
|
+
* Call this to update the name of the running session after it's started
|
|
132
|
+
* In the case it's been started with an unregistered name, and there is not running
|
|
133
|
+
* session. This will also trigger the session being started.
|
|
134
|
+
*/
|
|
135
|
+
function overrideExperienceKey(experienceKey) {
|
|
136
|
+
if (this.runningSession !== undefined) {
|
|
137
|
+
// If there is a running session - we update its name
|
|
138
|
+
this.runningSession.updateExperienceKey(experienceKey);
|
|
139
|
+
} else {
|
|
140
|
+
var _this$options$experie2;
|
|
141
|
+
// otherwise - we assume the last session was not registered, and start it with the new name
|
|
142
|
+
if ((_this$options$experie2 = this.options.experiences[experienceKey]) !== null && _this$options$experie2 !== void 0 && _this$options$experie2.enabled && this.lastStartedExperienceProperties) {
|
|
143
|
+
this.runningSession = new _insmSession.INSMSession(experienceKey, this.lastStartedExperienceProperties, this);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
107
147
|
|
|
108
148
|
/**
|
|
109
149
|
* This prematurely halts any running experience measurement. It's expected to be used in
|
|
@@ -112,8 +152,8 @@ var INSM = exports.INSM = /*#__PURE__*/function () {
|
|
|
112
152
|
}, {
|
|
113
153
|
key: "stopEarly",
|
|
114
154
|
value: function stopEarly(reasonKey, description) {
|
|
115
|
-
var _this$
|
|
116
|
-
(_this$
|
|
155
|
+
var _this$runningSession8;
|
|
156
|
+
(_this$runningSession8 = this.runningSession) === null || _this$runningSession8 === void 0 || _this$runningSession8.earlyStop(reasonKey, description);
|
|
117
157
|
}
|
|
118
158
|
|
|
119
159
|
/**
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.LongAnimationFrameMeasurer = void 0;
|
|
8
|
+
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
9
|
+
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
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
|
|
15
|
+
var LongAnimationFrameMeasurer = exports.LongAnimationFrameMeasurer = /*#__PURE__*/function () {
|
|
16
|
+
function LongAnimationFrameMeasurer(options) {
|
|
17
|
+
var _this = this;
|
|
18
|
+
(0, _classCallCheck2.default)(this, LongAnimationFrameMeasurer);
|
|
19
|
+
(0, _defineProperty2.default)(this, "longestScriptTimings", []);
|
|
20
|
+
(0, _defineProperty2.default)(this, "minimumIndex", -1);
|
|
21
|
+
(0, _defineProperty2.default)(this, "minimumDuration", Infinity);
|
|
22
|
+
this.options = options;
|
|
23
|
+
this.paused = options.insmSession.insm.runningHeavyTasks.size !== 0;
|
|
24
|
+
if (PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')) {
|
|
25
|
+
this.observer = new PerformanceObserver(function (list) {
|
|
26
|
+
if (!_this.paused) {
|
|
27
|
+
// only handle batches when tracking is not paused
|
|
28
|
+
_this.handleBatch(list.getEntries());
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
this.observer.observe({
|
|
32
|
+
type: 'long-animation-frame',
|
|
33
|
+
buffered: options.initial
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return (0, _createClass2.default)(LongAnimationFrameMeasurer, [{
|
|
38
|
+
key: "handleBatch",
|
|
39
|
+
value: function handleBatch(batch) {
|
|
40
|
+
for (var batchIndex = 0; batchIndex < batch.length; batchIndex++) {
|
|
41
|
+
var animationFrame = batch[batchIndex];
|
|
42
|
+
|
|
43
|
+
// Only process frames that exceed the reporting threshold
|
|
44
|
+
if (animationFrame.duration < this.options.reportingThreshold) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
|
|
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();
|
|
61
|
+
}
|
|
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;
|
|
85
|
+
|
|
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;
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
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);
|
|
102
|
+
|
|
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
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Update the min tracking
|
|
117
|
+
this.minimumIndex = newMinimumIndex;
|
|
118
|
+
this.minimumDuration = newMinimumDuration;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Pauses tracking
|
|
123
|
+
*/
|
|
124
|
+
}, {
|
|
125
|
+
key: "pause",
|
|
126
|
+
value: function pause() {
|
|
127
|
+
this.paused = true;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Resumes tracking
|
|
132
|
+
*/
|
|
133
|
+
}, {
|
|
134
|
+
key: "resume",
|
|
135
|
+
value: function resume() {
|
|
136
|
+
this.paused = false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Returns the current tracked longest script timings sorted by duration
|
|
141
|
+
*/
|
|
142
|
+
}, {
|
|
143
|
+
key: "current",
|
|
144
|
+
get: function get() {
|
|
145
|
+
var copy = this.longestScriptTimings.slice();
|
|
146
|
+
copy.sort(function (a, b) {
|
|
147
|
+
return b.duration - a.duration;
|
|
148
|
+
});
|
|
149
|
+
return copy;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Cleans up the performance tracking (tracking cannot be resumed following this).
|
|
154
|
+
*/
|
|
155
|
+
}, {
|
|
156
|
+
key: "cleanup",
|
|
157
|
+
value: function cleanup() {
|
|
158
|
+
var _this$observer;
|
|
159
|
+
(_this$observer = this.observer) === null || _this$observer === void 0 || _this$observer.disconnect();
|
|
160
|
+
}
|
|
161
|
+
}]);
|
|
162
|
+
}(); // Based on https://github.com/GoogleChrome/web-vitals/blob/1b872cf5f2159e8ace0e98d55d8eb54fb09adfbe/src/types.ts#L129
|
|
163
|
+
// exported for use in test file
|
|
164
|
+
// Based on https://github.com/GoogleChrome/web-vitals/blob/1b872cf5f2159e8ace0e98d55d8eb54fb09adfbe/src/types.ts#L129
|
package/dist/es2019/index.js
CHANGED
|
@@ -9,8 +9,6 @@ export function init(options) {
|
|
|
9
9
|
}
|
|
10
10
|
function insmInitialised() {
|
|
11
11
|
if (!initialisedInsm) {
|
|
12
|
-
// eslint-disable-next-line no-console
|
|
13
|
-
console.error('INSM used when not initialised');
|
|
14
12
|
return false;
|
|
15
13
|
}
|
|
16
14
|
return true;
|
|
@@ -35,6 +33,11 @@ export const insm = {
|
|
|
35
33
|
initialisedInsm.start(experienceKey, experienceProperties);
|
|
36
34
|
}
|
|
37
35
|
},
|
|
36
|
+
overrideExperienceKey(experienceKey) {
|
|
37
|
+
if (insmInitialised()) {
|
|
38
|
+
initialisedInsm.overrideExperienceKey(experienceKey);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
38
41
|
stopEarly(reasonKey, description) {
|
|
39
42
|
if (insmInitialised()) {
|
|
40
43
|
initialisedInsm.stopEarly(reasonKey, description);
|
|
@@ -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() {
|