@atlaskit/react-ufo 3.14.7 → 3.14.9

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/create-experimental-interaction-metrics-payload/index.js +14 -12
  3. package/dist/cjs/create-payload/utils/get-vc-metrics.js +17 -13
  4. package/dist/cjs/interaction-metrics/index.js +35 -15
  5. package/dist/cjs/interaction-metrics-init/index.js +5 -3
  6. package/dist/cjs/trace-interaction/index.js +10 -32
  7. package/dist/cjs/trace-interaction/internal/map-to-interaction-type.js +16 -0
  8. package/dist/cjs/trace-interaction/internal/trace-ufo-interaction.js +46 -0
  9. package/dist/cjs/trace-press/index.js +2 -25
  10. package/dist/cjs/vc/index.js +7 -0
  11. package/dist/es2019/create-experimental-interaction-metrics-payload/index.js +4 -2
  12. package/dist/es2019/create-payload/utils/get-vc-metrics.js +10 -4
  13. package/dist/es2019/interaction-metrics/index.js +36 -16
  14. package/dist/es2019/interaction-metrics-init/index.js +5 -3
  15. package/dist/es2019/trace-interaction/index.js +4 -31
  16. package/dist/es2019/trace-interaction/internal/map-to-interaction-type.js +10 -0
  17. package/dist/es2019/trace-interaction/internal/trace-ufo-interaction.js +39 -0
  18. package/dist/es2019/trace-press/index.js +2 -25
  19. package/dist/es2019/vc/index.js +5 -0
  20. package/dist/esm/create-experimental-interaction-metrics-payload/index.js +14 -12
  21. package/dist/esm/create-payload/utils/get-vc-metrics.js +17 -13
  22. package/dist/esm/interaction-metrics/index.js +36 -16
  23. package/dist/esm/interaction-metrics-init/index.js +5 -3
  24. package/dist/esm/trace-interaction/index.js +4 -31
  25. package/dist/esm/trace-interaction/internal/map-to-interaction-type.js +10 -0
  26. package/dist/esm/trace-interaction/internal/trace-ufo-interaction.js +39 -0
  27. package/dist/esm/trace-press/index.js +2 -25
  28. package/dist/esm/vc/index.js +6 -0
  29. package/dist/types/common/common/types.d.ts +4 -1
  30. package/dist/types/trace-interaction/index.d.ts +1 -0
  31. package/dist/types/trace-interaction/internal/map-to-interaction-type.d.ts +2 -0
  32. package/dist/types/trace-interaction/internal/trace-ufo-interaction.d.ts +3 -0
  33. package/dist/types/vc/index.d.ts +1 -0
  34. package/dist/types-ts4.5/common/common/types.d.ts +4 -1
  35. package/dist/types-ts4.5/trace-interaction/index.d.ts +1 -0
  36. package/dist/types-ts4.5/trace-interaction/internal/map-to-interaction-type.d.ts +2 -0
  37. package/dist/types-ts4.5/trace-interaction/internal/trace-ufo-interaction.d.ts +3 -0
  38. package/dist/types-ts4.5/vc/index.d.ts +1 -0
  39. package/package.json +10 -4
@@ -1,18 +1,6 @@
1
- import { v4 as createUUID } from 'uuid';
2
- import coinflip from '../coinflip';
3
- import { getDoNotAbortActivePressInteraction, getInteractionRate } from '../config';
4
- import { DefaultInteractionID } from '../interaction-id-context';
5
- import { abortAll, addNewInteraction, getActiveInteraction } from '../interaction-metrics';
6
- import UFORouteName from '../route-name-context';
7
- function mapToInteractionType(eventType) {
8
- if (eventType === 'click' || eventType === 'dblclick' || eventType === 'mousedown') {
9
- return 'press';
10
- }
11
- if (eventType === 'mouseenter' || eventType === 'mouseover') {
12
- return 'hover';
13
- }
14
- return undefined;
15
- }
1
+ import mapToInteractionType from './internal/map-to-interaction-type';
2
+ import internal_traceUFOInteraction from './internal/trace-ufo-interaction';
3
+ export { default as UNSAFE__DO_NOT_USE_traceUFOInteraction } from './internal/trace-ufo-interaction';
16
4
  function traceUFOInteraction(name, event) {
17
5
  if (!event || !event.isTrusted) {
18
6
  return;
@@ -22,21 +10,6 @@ function traceUFOInteraction(name, event) {
22
10
  // when interactionType is falsy we do not yet support this type of event. should we blow up with throwing error instead?
23
11
  return;
24
12
  }
25
- const rate = getInteractionRate(name, interactionType);
26
- const pressInteractionsList = getDoNotAbortActivePressInteraction();
27
- if (pressInteractionsList !== null && pressInteractionsList !== void 0 && pressInteractionsList.includes(name)) {
28
- const interaction = getActiveInteraction();
29
- if ((interaction === null || interaction === void 0 ? void 0 : interaction.ufoName) !== 'unknown' && (interaction === null || interaction === void 0 ? void 0 : interaction.type) === 'press') {
30
- return;
31
- }
32
- }
33
- if (coinflip(rate)) {
34
- var _event$timeStamp;
35
- abortAll('new_interaction', name);
36
- const startTimestamp = (_event$timeStamp = event.timeStamp) !== null && _event$timeStamp !== void 0 ? _event$timeStamp : performance.now();
37
- const newId = createUUID();
38
- DefaultInteractionID.current = newId;
39
- addNewInteraction(newId, name, 'press', startTimestamp, rate, [], UFORouteName.current);
40
- }
13
+ return internal_traceUFOInteraction(name, interactionType, event.timeStamp);
41
14
  }
42
15
  export default traceUFOInteraction;
@@ -0,0 +1,10 @@
1
+ function mapToInteractionType(eventType) {
2
+ if (eventType === 'click' || eventType === 'dblclick' || eventType === 'mousedown') {
3
+ return 'press';
4
+ }
5
+ if (eventType === 'mouseenter' || eventType === 'mouseover') {
6
+ return 'hover';
7
+ }
8
+ return undefined;
9
+ }
10
+ export default mapToInteractionType;
@@ -0,0 +1,39 @@
1
+ import { v4 as createUUID } from 'uuid';
2
+ import { fg } from '@atlaskit/platform-feature-flags';
3
+ import coinflip from '../../coinflip';
4
+ import { getDoNotAbortActivePressInteraction, getInteractionRate } from '../../config';
5
+ import { getActiveTrace, setInteractionActiveTrace } from '../../experience-trace-id-context';
6
+ import { DefaultInteractionID } from '../../interaction-id-context';
7
+ import { abortAll, addNewInteraction, getActiveInteraction } from '../../interaction-metrics';
8
+ import UFORouteName from '../../route-name-context';
9
+ function traceUFOInteraction(name, interactionType, startTime) {
10
+ const rate = getInteractionRate(name, interactionType);
11
+ const pressInteractionsList = getDoNotAbortActivePressInteraction();
12
+ if (pressInteractionsList !== null && pressInteractionsList !== void 0 && pressInteractionsList.includes(name)) {
13
+ const interaction = getActiveInteraction();
14
+ if ((interaction === null || interaction === void 0 ? void 0 : interaction.ufoName) !== 'unknown' && (interaction === null || interaction === void 0 ? void 0 : interaction.type) === 'press') {
15
+ return;
16
+ }
17
+ } else {
18
+ if (fg('platform_ufo_abort_measurement_fix')) {
19
+ // abort any existing interaction regardless if the next interaction's coinflip returns true or false
20
+ abortAll('new_interaction', name);
21
+ }
22
+ }
23
+ if (coinflip(rate)) {
24
+ if (!fg('platform_ufo_abort_measurement_fix')) {
25
+ abortAll('new_interaction', name);
26
+ }
27
+ const startTimestamp = startTime !== null && startTime !== void 0 ? startTime : performance.now();
28
+ const newId = createUUID();
29
+ DefaultInteractionID.current = newId;
30
+
31
+ // covered experiences with tracing instrumentation:
32
+ // inline-result.inline-card-create-submit
33
+ setInteractionActiveTrace(newId, interactionType);
34
+ addNewInteraction(newId, name, interactionType === 'hover' ? 'press' : interactionType,
35
+ // TODO add dedicated type for hover, might change backend though
36
+ startTimestamp, rate, [], UFORouteName.current, getActiveTrace());
37
+ }
38
+ }
39
+ export default traceUFOInteraction;
@@ -1,28 +1,5 @@
1
- import { v4 as createUUID } from 'uuid';
2
- import coinflip from '../coinflip';
3
- import { getDoNotAbortActivePressInteraction, getInteractionRate } from '../config';
4
- import { getActiveTrace, setInteractionActiveTrace } from '../experience-trace-id-context';
5
- import { DefaultInteractionID } from '../interaction-id-context';
6
- import { abortAll, addNewInteraction, getActiveInteraction } from '../interaction-metrics';
7
- import UFORouteName from '../route-name-context';
1
+ import { default as internal_traceUFOInteraction } from '../trace-interaction/internal/trace-ufo-interaction';
8
2
  function traceUFOPress(name, timestamp) {
9
- const rate = getInteractionRate(name, 'press');
10
- const pressInteractionsList = getDoNotAbortActivePressInteraction();
11
- if (pressInteractionsList !== null && pressInteractionsList !== void 0 && pressInteractionsList.includes(name)) {
12
- const interaction = getActiveInteraction();
13
- if ((interaction === null || interaction === void 0 ? void 0 : interaction.ufoName) !== 'unknown' && (interaction === null || interaction === void 0 ? void 0 : interaction.type) === 'press') {
14
- return;
15
- }
16
- }
17
- if (coinflip(rate)) {
18
- abortAll('new_interaction', name);
19
- const startTimestamp = timestamp !== null && timestamp !== void 0 ? timestamp : performance.now();
20
- const newId = createUUID();
21
- // covered experiences with tracing instrumentation:
22
- // inline-result.inline-card-create-submit
23
- setInteractionActiveTrace(newId, 'press');
24
- DefaultInteractionID.current = newId;
25
- addNewInteraction(newId, name, 'press', startTimestamp, rate, [], UFORouteName.current, getActiveTrace());
26
- }
3
+ return internal_traceUFOInteraction(name, 'press', timestamp);
27
4
  }
28
5
  export default traceUFOPress;
@@ -165,4 +165,9 @@ export function getVCObserver(opts = {}) {
165
165
  globalThis.__vcObserver = shouldMockVCObserver ? new VCObserverNOOP() : new VCObserverWrapper(opts);
166
166
  }
167
167
  return globalThis.__vcObserver;
168
+ }
169
+ export function newVCObserver(opts = {}) {
170
+ const shouldMockVCObserver = !isEnvironmentSupported();
171
+ const observer = shouldMockVCObserver ? new VCObserverNOOP() : new VCObserverWrapper(opts);
172
+ return observer;
168
173
  }
@@ -84,17 +84,19 @@ export function getExperimentalVCMetrics(_x) {
84
84
  }
85
85
  function _getExperimentalVCMetrics() {
86
86
  _getExperimentalVCMetrics = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(interaction) {
87
- var _interaction$apdex, prefix, result, VC, pageVisibilityUpToTTAI;
87
+ var vcObserver, _interaction$apdex, prefix, result, VC, pageVisibilityUpToTTAI;
88
88
  return _regeneratorRuntime.wrap(function _callee$(_context) {
89
89
  while (1) switch (_context.prev = _context.next) {
90
90
  case 0:
91
- if (!experimentalVC.vcObserver) {
92
- _context.next = 12;
91
+ // Use per-interaction VC observer if available, otherwise fall back to global experimentalVC
92
+ vcObserver = interaction.experimentalVCObserver || experimentalVC.vcObserver;
93
+ if (!vcObserver) {
94
+ _context.next = 13;
93
95
  break;
94
96
  }
95
97
  prefix = 'ufo-experimental';
96
- _context.next = 4;
97
- return experimentalVC.vcObserver.getVCResult({
98
+ _context.next = 5;
99
+ return vcObserver.getVCResult({
98
100
  start: interaction.start,
99
101
  stop: interaction.end,
100
102
  tti: (_interaction$apdex = interaction.apdex) === null || _interaction$apdex === void 0 || (_interaction$apdex = _interaction$apdex[0]) === null || _interaction$apdex === void 0 ? void 0 : _interaction$apdex.stopTime,
@@ -104,28 +106,28 @@ function _getExperimentalVCMetrics() {
104
106
  experienceKey: interaction.ufoName,
105
107
  interactionId: interaction.id
106
108
  });
107
- case 4:
109
+ case 5:
108
110
  result = _context.sent;
109
111
  VC = result === null || result === void 0 ? void 0 : result['metrics:vc'];
110
112
  if (!(!VC || !(result !== null && result !== void 0 && result["".concat(prefix, ":vc:clean")]))) {
111
- _context.next = 8;
113
+ _context.next = 9;
112
114
  break;
113
115
  }
114
116
  return _context.abrupt("return", result);
115
- case 8:
117
+ case 9:
116
118
  pageVisibilityUpToTTAI = getPageVisibilityState(interaction.start, interaction.end);
117
119
  if (!(interaction.abortReason || pageVisibilityUpToTTAI !== 'visible')) {
118
- _context.next = 11;
120
+ _context.next = 12;
119
121
  break;
120
122
  }
121
123
  return _context.abrupt("return", result);
122
- case 11:
124
+ case 12:
123
125
  return _context.abrupt("return", _objectSpread(_objectSpread({}, result), {}, {
124
126
  'metric:experimental:vc90': VC['90']
125
127
  }));
126
- case 12:
127
- return _context.abrupt("return", null);
128
128
  case 13:
129
+ return _context.abrupt("return", null);
130
+ case 14:
129
131
  case "end":
130
132
  return _context.stop();
131
133
  }
@@ -16,7 +16,7 @@ function getVCMetrics(_x) {
16
16
  function _getVCMetrics() {
17
17
  _getVCMetrics = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(interaction) {
18
18
  var _config$vc, _config$vc$ssrWhiteli, _interaction$apdex, _config$vc2, _config$vc3, _config$experimentalI, _result$ufoVcRev;
19
- var config, interactionStatus, pageVisibilityUpToTTAI, shouldReportVCMetrics, isSSREnabled, ssr, tti, prefix, result, mostRecentVCRevision, mostRecentVCRevisionPayload;
19
+ var config, interactionStatus, pageVisibilityUpToTTAI, shouldReportVCMetrics, observer, isSSREnabled, ssr, tti, prefix, result, mostRecentVCRevision, mostRecentVCRevisionPayload;
20
20
  return _regeneratorRuntime.wrap(function _callee$(_context) {
21
21
  while (1) switch (_context.prev = _context.next) {
22
22
  case 0:
@@ -27,7 +27,7 @@ function _getVCMetrics() {
27
27
  }
28
28
  return _context.abrupt("return", {});
29
29
  case 3:
30
- if (!(fg('platform_ufo_enable_interactions_vc') || fg('platform_ufo_enable_interactivity_jsm'))) {
30
+ if (!fg('platform_ufo_enable_vc_press_interactions')) {
31
31
  _context.next = 8;
32
32
  break;
33
33
  }
@@ -48,14 +48,15 @@ function _getVCMetrics() {
48
48
  case 10:
49
49
  interactionStatus = getInteractionStatus(interaction);
50
50
  pageVisibilityUpToTTAI = getPageVisibilityUpToTTAI(interaction);
51
- shouldReportVCMetrics = interactionStatus.originalInteractionStatus === 'SUCCEEDED' && pageVisibilityUpToTTAI === 'visible';
51
+ shouldReportVCMetrics = interactionStatus.originalInteractionStatus === 'SUCCEEDED' && pageVisibilityUpToTTAI === 'visible'; // Use per-interaction VC observer if available, otherwise fall back to global
52
+ observer = interaction.vcObserver || getVCObserver();
52
53
  if (!(!shouldReportVCMetrics && fg('platform_ufo_no_vc_on_aborted'))) {
53
- _context.next = 16;
54
+ _context.next = 17;
54
55
  break;
55
56
  }
56
- getVCObserver().stop(interaction.ufoName);
57
+ observer.stop(interaction.ufoName);
57
58
  return _context.abrupt("return", {});
58
- case 16:
59
+ case 17:
59
60
  isSSREnabled = interaction.type === 'page_load' && ((config === null || config === void 0 ? void 0 : config.ssr) || (config === null || config === void 0 || (_config$vc$ssrWhiteli = config.vc.ssrWhitelist) === null || _config$vc$ssrWhiteli === void 0 ? void 0 : _config$vc$ssrWhiteli.includes(interaction.ufoName)));
60
61
  ssr = interaction.type === 'page_load' && isSSREnabled ? {
61
62
  ssr: getSSRDoneTimeValue(config)
@@ -63,8 +64,8 @@ function _getVCMetrics() {
63
64
  postInteractionLog.setVCObserverSSRConfig(ssr);
64
65
  tti = (_interaction$apdex = interaction.apdex) === null || _interaction$apdex === void 0 || (_interaction$apdex = _interaction$apdex[0]) === null || _interaction$apdex === void 0 ? void 0 : _interaction$apdex.stopTime;
65
66
  prefix = 'ufo';
66
- _context.next = 23;
67
- return getVCObserver().getVCResult(_objectSpread({
67
+ _context.next = 24;
68
+ return observer.getVCResult(_objectSpread({
68
69
  start: interaction.start,
69
70
  stop: interaction.end,
70
71
  tti: tti,
@@ -76,10 +77,13 @@ function _getVCMetrics() {
76
77
  interactionId: interaction.id,
77
78
  includeSSRRatio: (_config$vc3 = config.vc) === null || _config$vc3 === void 0 ? void 0 : _config$vc3.includeSSRRatio
78
79
  }, ssr));
79
- case 23:
80
+ case 24:
80
81
  result = _context.sent;
82
+ if (fg('platform_ufo_enable_vc_observer_per_interaction')) {
83
+ observer.stop(interaction.ufoName);
84
+ }
81
85
  if ((_config$experimentalI = config.experimentalInteractionMetrics) !== null && _config$experimentalI !== void 0 && _config$experimentalI.enabled) {
82
- getVCObserver().stop(interaction.ufoName);
86
+ observer.stop(interaction.ufoName);
83
87
  }
84
88
  postInteractionLog.setLastInteractionFinishVCResult(result);
85
89
  mostRecentVCRevision = getMostRecentVCRevision(interaction.ufoName);
@@ -88,15 +92,15 @@ function _getVCMetrics() {
88
92
  return revision === mostRecentVCRevision;
89
93
  });
90
94
  if (!(!shouldReportVCMetrics || !(mostRecentVCRevisionPayload !== null && mostRecentVCRevisionPayload !== void 0 && mostRecentVCRevisionPayload.clean))) {
91
- _context.next = 30;
95
+ _context.next = 32;
92
96
  break;
93
97
  }
94
98
  return _context.abrupt("return", result);
95
- case 30:
99
+ case 32:
96
100
  return _context.abrupt("return", _objectSpread(_objectSpread({}, result), {}, {
97
101
  'metric:vc90': mostRecentVCRevisionPayload['metric:vc90']
98
102
  }));
99
- case 31:
103
+ case 33:
100
104
  case "end":
101
105
  return _context.stop();
102
106
  }
@@ -16,7 +16,7 @@ import { experimentalVC, getExperimentalVCMetrics, onExperimentalInteractionComp
16
16
  import { clearActiveTrace } from '../experience-trace-id-context';
17
17
  import { allFeatureFlagsAccessed, currentFeatureFlagsAccessed } from '../feature-flags-accessed';
18
18
  import { getInteractionId } from '../interaction-id-context';
19
- import { getVCObserver } from '../vc';
19
+ import { getVCObserver, newVCObserver } from '../vc';
20
20
  import { interactions } from './common/constants';
21
21
  import PostInteractionLog from './post-interaction-log';
22
22
  var PreviousInteractionLog = {
@@ -523,7 +523,9 @@ function finishInteraction(id, data) {
523
523
  clearActiveTrace();
524
524
  callCleanUpCallbacks(data);
525
525
  if ((_getConfig4 = getConfig()) !== null && _getConfig4 !== void 0 && (_getConfig4 = _getConfig4.vc) !== null && _getConfig4 !== void 0 && _getConfig4.stopVCAtInteractionFinish) {
526
- data.vc = getVCObserver().getVCRawData();
526
+ // Use per-interaction VC observer if available, otherwise fall back to global
527
+ var observer = data.vcObserver || getVCObserver();
528
+ data.vc = observer.getVCRawData();
527
529
  }
528
530
  if (!((_getConfig5 = getConfig()) !== null && _getConfig5 !== void 0 && (_getConfig5 = _getConfig5.experimentalInteractionMetrics) !== null && _getConfig5 !== void 0 && _getConfig5.enabled)) {
529
531
  remove(id);
@@ -735,6 +737,7 @@ export function addNewInteraction(interactionId, ufoName, type, startTime, rate,
735
737
  if ((_getConfig11 = getConfig()) !== null && _getConfig11 !== void 0 && (_getConfig11 = _getConfig11.postInteractionLog) !== null && _getConfig11 !== void 0 && _getConfig11.enabled) {
736
738
  postInteractionLog.reset();
737
739
  }
740
+ var vcObserver;
738
741
  var previousTime = startTime;
739
742
  var timeoutTime = fg('platform_ufo_enable_timeout_config') ? getInteractionTimeout(ufoName) : CLEANUP_TIMEOUT;
740
743
  var timerID = setTimeout(function () {
@@ -757,6 +760,21 @@ export function addNewInteraction(interactionId, ufoName, type, startTime, rate,
757
760
  this.timerID = newTimerID;
758
761
  }
759
762
  var addFeatureFlagsToInteraction = coinflip(getCapabilityRate('feature_flag_access'));
763
+ var config = getConfig();
764
+ if (config && config.vc) {
765
+ var vcOptions = {
766
+ heatmapSize: config.vc.heatmapSize,
767
+ oldDomUpdates: config.vc.oldDomUpdates,
768
+ devToolsEnabled: config.vc.devToolsEnabled,
769
+ selectorConfig: config.vc.selectorConfig,
770
+ ssrEnablePageLayoutPlaceholder: config.vc.ssrEnablePageLayoutPlaceholder,
771
+ disableSizeAndPositionCheck: config.vc.disableSizeAndPositionCheck
772
+ };
773
+ vcObserver = fg('platform_ufo_enable_vc_observer_per_interaction') ? newVCObserver(vcOptions) : undefined;
774
+ }
775
+
776
+ // Create per-interaction VC observer when feature flag is enabled
777
+
760
778
  var metrics = {
761
779
  id: interactionId,
762
780
  start: startTime,
@@ -797,7 +815,8 @@ export function addNewInteraction(interactionId, ufoName, type, startTime, rate,
797
815
  redirects: [],
798
816
  timerID: timerID,
799
817
  changeTimeout: changeTimeout,
800
- trace: trace
818
+ trace: trace,
819
+ vcObserver: vcObserver
801
820
  };
802
821
  if (addFeatureFlagsToInteraction) {
803
822
  currentFeatureFlagsAccessed.clear();
@@ -816,13 +835,21 @@ export function addNewInteraction(interactionId, ufoName, type, startTime, rate,
816
835
  metrics.cleanupCallbacks.push(function () {
817
836
  clearTimeout(metrics.timerID);
818
837
  });
838
+ // Add cleanup for per-interaction VC observer
839
+ if (vcObserver) {
840
+ metrics.cleanupCallbacks.push(function () {
841
+ vcObserver.stop(ufoName);
842
+ });
843
+ }
819
844
  var awaitBM3TTIList = getAwaitBM3TTIList();
820
845
  if (awaitBM3TTIList.includes(ufoName)) {
821
846
  addHoldByID(interactionId, [], ufoName, ufoName, true);
822
847
  }
823
- if (type === 'transition') {
848
+ if (type === 'transition' || type === 'page_load') {
824
849
  var _getConfig12;
825
- getVCObserver().start({
850
+ // Use per-interaction VC observer if available, otherwise fall back to global
851
+ var observer = vcObserver || getVCObserver();
852
+ observer.start({
826
853
  startTime: startTime,
827
854
  experienceKey: ufoName
828
855
  });
@@ -835,20 +862,13 @@ export function addNewInteraction(interactionId, ufoName, type, startTime, rate,
835
862
  });
836
863
  }
837
864
  }
838
- if (type === 'press' && (fg('platform_ufo_enable_interactions_vc') || fg('platform_ufo_enable_interactivity_jsm'))) {
839
- var _getConfig13;
840
- getVCObserver().start({
865
+ if (type === 'press' && fg('platform_ufo_enable_vc_press_interactions')) {
866
+ // Use per-interaction VC observer if available, otherwise fall back to global
867
+ var _observer = vcObserver || getVCObserver();
868
+ _observer.start({
841
869
  startTime: startTime,
842
870
  experienceKey: ufoName
843
871
  });
844
- postInteractionLog.startVCObserver({
845
- startTime: startTime
846
- });
847
- if ((_getConfig13 = getConfig()) !== null && _getConfig13 !== void 0 && (_getConfig13 = _getConfig13.experimentalInteractionMetrics) !== null && _getConfig13 !== void 0 && _getConfig13.enabled) {
848
- experimentalVC.start({
849
- startTime: startTime
850
- });
851
- }
852
872
  }
853
873
  }
854
874
  export function addBrowserMetricEvent(event) {
@@ -92,9 +92,11 @@ export function init(analyticsWebClientAsync, config) {
92
92
  ssrEnablePageLayoutPlaceholder: config.vc.ssrEnablePageLayoutPlaceholder,
93
93
  disableSizeAndPositionCheck: config.vc.disableSizeAndPositionCheck
94
94
  };
95
- getVCObserver(vcOptions).start({
96
- startTime: 0
97
- });
95
+ if (!fg('platform_ufo_enable_vc_observer_per_interaction')) {
96
+ getVCObserver(vcOptions).start({
97
+ startTime: 0
98
+ });
99
+ }
98
100
  postInteractionLog.initializeVCObserver(vcOptions);
99
101
  postInteractionLog.startVCObserver({
100
102
  startTime: 0
@@ -1,18 +1,6 @@
1
- import { v4 as createUUID } from 'uuid';
2
- import coinflip from '../coinflip';
3
- import { getDoNotAbortActivePressInteraction, getInteractionRate } from '../config';
4
- import { DefaultInteractionID } from '../interaction-id-context';
5
- import { abortAll, addNewInteraction, getActiveInteraction } from '../interaction-metrics';
6
- import UFORouteName from '../route-name-context';
7
- function mapToInteractionType(eventType) {
8
- if (eventType === 'click' || eventType === 'dblclick' || eventType === 'mousedown') {
9
- return 'press';
10
- }
11
- if (eventType === 'mouseenter' || eventType === 'mouseover') {
12
- return 'hover';
13
- }
14
- return undefined;
15
- }
1
+ import mapToInteractionType from './internal/map-to-interaction-type';
2
+ import internal_traceUFOInteraction from './internal/trace-ufo-interaction';
3
+ export { default as UNSAFE__DO_NOT_USE_traceUFOInteraction } from './internal/trace-ufo-interaction';
16
4
  function traceUFOInteraction(name, event) {
17
5
  if (!event || !event.isTrusted) {
18
6
  return;
@@ -22,21 +10,6 @@ function traceUFOInteraction(name, event) {
22
10
  // when interactionType is falsy we do not yet support this type of event. should we blow up with throwing error instead?
23
11
  return;
24
12
  }
25
- var rate = getInteractionRate(name, interactionType);
26
- var pressInteractionsList = getDoNotAbortActivePressInteraction();
27
- if (pressInteractionsList !== null && pressInteractionsList !== void 0 && pressInteractionsList.includes(name)) {
28
- var interaction = getActiveInteraction();
29
- if ((interaction === null || interaction === void 0 ? void 0 : interaction.ufoName) !== 'unknown' && (interaction === null || interaction === void 0 ? void 0 : interaction.type) === 'press') {
30
- return;
31
- }
32
- }
33
- if (coinflip(rate)) {
34
- var _event$timeStamp;
35
- abortAll('new_interaction', name);
36
- var startTimestamp = (_event$timeStamp = event.timeStamp) !== null && _event$timeStamp !== void 0 ? _event$timeStamp : performance.now();
37
- var newId = createUUID();
38
- DefaultInteractionID.current = newId;
39
- addNewInteraction(newId, name, 'press', startTimestamp, rate, [], UFORouteName.current);
40
- }
13
+ return internal_traceUFOInteraction(name, interactionType, event.timeStamp);
41
14
  }
42
15
  export default traceUFOInteraction;
@@ -0,0 +1,10 @@
1
+ function mapToInteractionType(eventType) {
2
+ if (eventType === 'click' || eventType === 'dblclick' || eventType === 'mousedown') {
3
+ return 'press';
4
+ }
5
+ if (eventType === 'mouseenter' || eventType === 'mouseover') {
6
+ return 'hover';
7
+ }
8
+ return undefined;
9
+ }
10
+ export default mapToInteractionType;
@@ -0,0 +1,39 @@
1
+ import { v4 as createUUID } from 'uuid';
2
+ import { fg } from '@atlaskit/platform-feature-flags';
3
+ import coinflip from '../../coinflip';
4
+ import { getDoNotAbortActivePressInteraction, getInteractionRate } from '../../config';
5
+ import { getActiveTrace, setInteractionActiveTrace } from '../../experience-trace-id-context';
6
+ import { DefaultInteractionID } from '../../interaction-id-context';
7
+ import { abortAll, addNewInteraction, getActiveInteraction } from '../../interaction-metrics';
8
+ import UFORouteName from '../../route-name-context';
9
+ function traceUFOInteraction(name, interactionType, startTime) {
10
+ var rate = getInteractionRate(name, interactionType);
11
+ var pressInteractionsList = getDoNotAbortActivePressInteraction();
12
+ if (pressInteractionsList !== null && pressInteractionsList !== void 0 && pressInteractionsList.includes(name)) {
13
+ var interaction = getActiveInteraction();
14
+ if ((interaction === null || interaction === void 0 ? void 0 : interaction.ufoName) !== 'unknown' && (interaction === null || interaction === void 0 ? void 0 : interaction.type) === 'press') {
15
+ return;
16
+ }
17
+ } else {
18
+ if (fg('platform_ufo_abort_measurement_fix')) {
19
+ // abort any existing interaction regardless if the next interaction's coinflip returns true or false
20
+ abortAll('new_interaction', name);
21
+ }
22
+ }
23
+ if (coinflip(rate)) {
24
+ if (!fg('platform_ufo_abort_measurement_fix')) {
25
+ abortAll('new_interaction', name);
26
+ }
27
+ var startTimestamp = startTime !== null && startTime !== void 0 ? startTime : performance.now();
28
+ var newId = createUUID();
29
+ DefaultInteractionID.current = newId;
30
+
31
+ // covered experiences with tracing instrumentation:
32
+ // inline-result.inline-card-create-submit
33
+ setInteractionActiveTrace(newId, interactionType);
34
+ addNewInteraction(newId, name, interactionType === 'hover' ? 'press' : interactionType,
35
+ // TODO add dedicated type for hover, might change backend though
36
+ startTimestamp, rate, [], UFORouteName.current, getActiveTrace());
37
+ }
38
+ }
39
+ export default traceUFOInteraction;
@@ -1,28 +1,5 @@
1
- import { v4 as createUUID } from 'uuid';
2
- import coinflip from '../coinflip';
3
- import { getDoNotAbortActivePressInteraction, getInteractionRate } from '../config';
4
- import { getActiveTrace, setInteractionActiveTrace } from '../experience-trace-id-context';
5
- import { DefaultInteractionID } from '../interaction-id-context';
6
- import { abortAll, addNewInteraction, getActiveInteraction } from '../interaction-metrics';
7
- import UFORouteName from '../route-name-context';
1
+ import { default as internal_traceUFOInteraction } from '../trace-interaction/internal/trace-ufo-interaction';
8
2
  function traceUFOPress(name, timestamp) {
9
- var rate = getInteractionRate(name, 'press');
10
- var pressInteractionsList = getDoNotAbortActivePressInteraction();
11
- if (pressInteractionsList !== null && pressInteractionsList !== void 0 && pressInteractionsList.includes(name)) {
12
- var interaction = getActiveInteraction();
13
- if ((interaction === null || interaction === void 0 ? void 0 : interaction.ufoName) !== 'unknown' && (interaction === null || interaction === void 0 ? void 0 : interaction.type) === 'press') {
14
- return;
15
- }
16
- }
17
- if (coinflip(rate)) {
18
- abortAll('new_interaction', name);
19
- var startTimestamp = timestamp !== null && timestamp !== void 0 ? timestamp : performance.now();
20
- var newId = createUUID();
21
- // covered experiences with tracing instrumentation:
22
- // inline-result.inline-card-create-submit
23
- setInteractionActiveTrace(newId, 'press');
24
- DefaultInteractionID.current = newId;
25
- addNewInteraction(newId, name, 'press', startTimestamp, rate, [], UFORouteName.current, getActiveTrace());
26
- }
3
+ return internal_traceUFOInteraction(name, 'press', timestamp);
27
4
  }
28
5
  export default traceUFOPress;
@@ -234,4 +234,10 @@ export function getVCObserver() {
234
234
  globalThis.__vcObserver = shouldMockVCObserver ? new VCObserverNOOP() : new VCObserverWrapper(opts);
235
235
  }
236
236
  return globalThis.__vcObserver;
237
+ }
238
+ export function newVCObserver() {
239
+ var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
240
+ var shouldMockVCObserver = !isEnvironmentSupported();
241
+ var observer = shouldMockVCObserver ? new VCObserverNOOP() : new VCObserverWrapper(opts);
242
+ return observer;
237
243
  }
@@ -1,5 +1,6 @@
1
1
  import type { TraceIdContext } from '../../experience-trace-id-context';
2
2
  import type { LabelStack, UFOInteractionContextType } from '../../interaction-context';
3
+ import type { VCObserverInterface } from '../../vc/types';
3
4
  import { type VCRawDataType, type VCResult } from '../vc/types';
4
5
  export type LifecycleMarkType = 'render' | 'beforePaint' | 'afterPaint' | 'nextTick' | 'mount' | 'commit';
5
6
  export type MarkType = ('placeholder' | 'bm3_stop' | 'bundle_preload' | 'custom') | LifecycleMarkType;
@@ -113,8 +114,8 @@ export interface InteractionMetrics {
113
114
  holdInfo: HoldInfo[];
114
115
  holdExpInfo: HoldInfo[];
115
116
  holdActive: Map<string, HoldActive>;
116
- holdExpActive: Map<string, HoldActive>;
117
117
  reactProfilerTimings: ReactProfilerTiming[];
118
+ holdExpActive: Map<string, HoldActive>;
118
119
  measureStart: number;
119
120
  rate: number;
120
121
  cancelCallbacks: (() => void)[];
@@ -158,6 +159,8 @@ export interface InteractionMetrics {
158
159
  changeTimeout: (newTime: number) => void;
159
160
  trace: TraceIdContext | null;
160
161
  legacyMetrics?: BM3Event[];
162
+ vcObserver?: VCObserverInterface;
163
+ experimentalVCObserver?: VCObserverInterface;
161
164
  vc?: VCRawDataType | null;
162
165
  experimentalTTAI?: number;
163
166
  experimentalVC90?: number;
@@ -1,3 +1,4 @@
1
1
  import type { UIEvent } from 'react';
2
+ export { default as UNSAFE__DO_NOT_USE_traceUFOInteraction } from './internal/trace-ufo-interaction';
2
3
  declare function traceUFOInteraction(name: string, event: UIEvent): void;
3
4
  export default traceUFOInteraction;
@@ -0,0 +1,2 @@
1
+ declare function mapToInteractionType(eventType: string): "press" | "hover" | undefined;
2
+ export default mapToInteractionType;
@@ -0,0 +1,3 @@
1
+ type InteractionType = 'press' | 'typing' | 'hover';
2
+ declare function traceUFOInteraction(name: string, interactionType: InteractionType, startTime?: DOMHighResTimeStamp): void;
3
+ export default traceUFOInteraction;
@@ -24,3 +24,4 @@ export declare class VCObserverWrapper implements VCObserverInterface {
24
24
  }
25
25
  export declare function isEnvironmentSupported(): boolean;
26
26
  export declare function getVCObserver(opts?: VCObserverOptions): VCObserverInterface;
27
+ export declare function newVCObserver(opts?: VCObserverOptions): VCObserverInterface;
@@ -1,5 +1,6 @@
1
1
  import type { TraceIdContext } from '../../experience-trace-id-context';
2
2
  import type { LabelStack, UFOInteractionContextType } from '../../interaction-context';
3
+ import type { VCObserverInterface } from '../../vc/types';
3
4
  import { type VCRawDataType, type VCResult } from '../vc/types';
4
5
  export type LifecycleMarkType = 'render' | 'beforePaint' | 'afterPaint' | 'nextTick' | 'mount' | 'commit';
5
6
  export type MarkType = ('placeholder' | 'bm3_stop' | 'bundle_preload' | 'custom') | LifecycleMarkType;
@@ -113,8 +114,8 @@ export interface InteractionMetrics {
113
114
  holdInfo: HoldInfo[];
114
115
  holdExpInfo: HoldInfo[];
115
116
  holdActive: Map<string, HoldActive>;
116
- holdExpActive: Map<string, HoldActive>;
117
117
  reactProfilerTimings: ReactProfilerTiming[];
118
+ holdExpActive: Map<string, HoldActive>;
118
119
  measureStart: number;
119
120
  rate: number;
120
121
  cancelCallbacks: (() => void)[];
@@ -158,6 +159,8 @@ export interface InteractionMetrics {
158
159
  changeTimeout: (newTime: number) => void;
159
160
  trace: TraceIdContext | null;
160
161
  legacyMetrics?: BM3Event[];
162
+ vcObserver?: VCObserverInterface;
163
+ experimentalVCObserver?: VCObserverInterface;
161
164
  vc?: VCRawDataType | null;
162
165
  experimentalTTAI?: number;
163
166
  experimentalVC90?: number;
@@ -1,3 +1,4 @@
1
1
  import type { UIEvent } from 'react';
2
+ export { default as UNSAFE__DO_NOT_USE_traceUFOInteraction } from './internal/trace-ufo-interaction';
2
3
  declare function traceUFOInteraction(name: string, event: UIEvent): void;
3
4
  export default traceUFOInteraction;
@@ -0,0 +1,2 @@
1
+ declare function mapToInteractionType(eventType: string): "press" | "hover" | undefined;
2
+ export default mapToInteractionType;
@@ -0,0 +1,3 @@
1
+ type InteractionType = 'press' | 'typing' | 'hover';
2
+ declare function traceUFOInteraction(name: string, interactionType: InteractionType, startTime?: DOMHighResTimeStamp): void;
3
+ export default traceUFOInteraction;
@@ -24,3 +24,4 @@ export declare class VCObserverWrapper implements VCObserverInterface {
24
24
  }
25
25
  export declare function isEnvironmentSupported(): boolean;
26
26
  export declare function getVCObserver(opts?: VCObserverOptions): VCObserverInterface;
27
+ export declare function newVCObserver(opts?: VCObserverOptions): VCObserverInterface;