@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 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);
@@ -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
  }, {
@@ -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
- * Note: Events are not reliably fired from mobile browsers (ie. when a browser is closed when not in use)
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
- * Adds a feature to the currently running session
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$runningSession4;
77
+ var _this$runningSession5;
73
78
  this.runningHeavyTasks.delete(heavyTaskName);
74
- (_this$runningSession4 = this.runningSession) === null || _this$runningSession4 === void 0 || _this$runningSession4.periodTracking.resume(heavyTaskName);
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('page-load')` and subsequent `insm.session.endHeavyTask('page-load')`
82
- * so that performance degradations linked to the page initialisation are excluded from the active interactivity monitoring.
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(''page-load')
106
+ * insm.session.startHeavyTask('PageLoad')
88
107
  * // ... heavy initialisation work
89
- * insm.session.endHeavyTask(''page-load')
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$runningSession5;
116
- (_this$runningSession5 = this.runningSession) === null || _this$runningSession5 === void 0 || _this$runningSession5.earlyStop(reasonKey, description);
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
@@ -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() {