@atlaskit/react-ufo 4.14.3 → 4.14.5

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 (40) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/config/index.js +4 -0
  3. package/dist/cjs/create-payload/index.js +22 -2
  4. package/dist/cjs/create-payload/utils/get-vc-metrics.js +10 -6
  5. package/dist/cjs/interaction-metrics/index.js +20 -1
  6. package/dist/cjs/segment/segment.js +5 -0
  7. package/dist/cjs/vc/index.js +4 -3
  8. package/dist/cjs/vc/vc-observer-new/index.js +31 -7
  9. package/dist/cjs/vc/vc-observer-new/raw-data-handler/index.js +237 -0
  10. package/dist/es2019/config/index.js +3 -0
  11. package/dist/es2019/create-payload/index.js +17 -1
  12. package/dist/es2019/create-payload/utils/get-vc-metrics.js +5 -2
  13. package/dist/es2019/interaction-metrics/index.js +16 -0
  14. package/dist/es2019/segment/segment.js +6 -1
  15. package/dist/es2019/vc/index.js +4 -2
  16. package/dist/es2019/vc/vc-observer-new/index.js +20 -1
  17. package/dist/es2019/vc/vc-observer-new/raw-data-handler/index.js +173 -0
  18. package/dist/esm/config/index.js +3 -0
  19. package/dist/esm/create-payload/index.js +22 -2
  20. package/dist/esm/create-payload/utils/get-vc-metrics.js +11 -7
  21. package/dist/esm/interaction-metrics/index.js +17 -0
  22. package/dist/esm/segment/segment.js +6 -1
  23. package/dist/esm/vc/index.js +4 -3
  24. package/dist/esm/vc/vc-observer-new/index.js +31 -7
  25. package/dist/esm/vc/vc-observer-new/raw-data-handler/index.js +231 -0
  26. package/dist/types/common/common/types.d.ts +1 -1
  27. package/dist/types/common/vc/types.d.ts +20 -1
  28. package/dist/types/config/index.d.ts +6 -0
  29. package/dist/types/interaction-metrics/index.d.ts +1 -0
  30. package/dist/types/vc/types.d.ts +1 -0
  31. package/dist/types/vc/vc-observer-new/raw-data-handler/index.d.ts +20 -0
  32. package/dist/types/vc/vc-observer-new/types.d.ts +2 -0
  33. package/dist/types-ts4.5/common/common/types.d.ts +1 -1
  34. package/dist/types-ts4.5/common/vc/types.d.ts +25 -1
  35. package/dist/types-ts4.5/config/index.d.ts +6 -0
  36. package/dist/types-ts4.5/interaction-metrics/index.d.ts +1 -0
  37. package/dist/types-ts4.5/vc/types.d.ts +1 -0
  38. package/dist/types-ts4.5/vc/vc-observer-new/raw-data-handler/index.d.ts +20 -0
  39. package/dist/types-ts4.5/vc/vc-observer-new/types.d.ts +2 -0
  40. package/package.json +7 -1
@@ -23,6 +23,7 @@ const interactionQueue = [];
23
23
  const segmentCache = new Map();
24
24
  export const segmentUnmountCache = new Map(); // Temporarily store segment unmount counts
25
25
 
26
+ let firstSegmentLoadMarked = false;
26
27
  const segmentObservers = [];
27
28
  export function getActiveInteraction() {
28
29
  const interactionId = getInteractionId();
@@ -194,6 +195,21 @@ export function addMark(interactionId, type, name, labelStack, time = performanc
194
195
  });
195
196
  }
196
197
  }
198
+ export function markFirstSegmentLoad(interactionId, labelStack, time = performance.now()) {
199
+ if (!fg('platform_mark_ufo_segment_first_load')) {
200
+ return;
201
+ }
202
+ const interaction = interactions.get(interactionId);
203
+ if (interaction != null && !firstSegmentLoadMarked) {
204
+ firstSegmentLoadMarked = true;
205
+ interaction.marks.push({
206
+ type: 'first_segment_load',
207
+ name: 'first_segment_load',
208
+ labelStack,
209
+ time
210
+ });
211
+ }
212
+ }
197
213
  export function addMarkToAll(type, name, labelStack, time = performance.now()) {
198
214
  interactions.forEach(interaction => {
199
215
  interaction.marks.push({
@@ -7,11 +7,12 @@ import { getConfig, getDoNotAbortActivePressInteraction, getInteractionRate, get
7
7
  import { getActiveTrace, setInteractionActiveTrace } from '../experience-trace-id-context';
8
8
  import UFOInteractionContext from '../interaction-context';
9
9
  import UFOInteractionIDContext from '../interaction-id-context';
10
- import { abortByNewInteraction, addApdex, addCustomData, addCustomTiming, addHold, addHoldByID, addMark, addNewInteraction, addProfilerTimings, addRequestInfo, addSegment, addSpan, getActiveInteraction, removeHoldByID, removeSegment, tryComplete } from '../interaction-metrics';
10
+ import { abortByNewInteraction, addApdex, addCustomData, addCustomTiming, addHold, addHoldByID, addMark, addNewInteraction, addProfilerTimings, addRequestInfo, addSegment, addSpan, getActiveInteraction, markFirstSegmentLoad, removeHoldByID, removeSegment, tryComplete } from '../interaction-metrics';
11
11
  import UFORouteName from '../route-name-context';
12
12
  import generateId from '../short-id';
13
13
  import scheduleOnPaint from './schedule-on-paint';
14
14
  let tryCompleteHandle;
15
+ let hasMarkedFirstSegmentLoad = false;
15
16
 
16
17
  /** A portion of the page we apply measurement to */
17
18
  export default function UFOSegment({
@@ -53,6 +54,10 @@ export default function UFOSegment({
53
54
  } : {})
54
55
  }], [parentContext, segmentName, segmentId, type]);
55
56
  const interactionId = useContext(UFOInteractionIDContext);
57
+ if (interactionId.current != null && !hasMarkedFirstSegmentLoad) {
58
+ markFirstSegmentLoad(interactionId.current, labelStack, performance.now());
59
+ hasMarkedFirstSegmentLoad = true;
60
+ }
56
61
  const interactionContext = useMemo(() => {
57
62
  let lastCompleteEndTime = 0;
58
63
  function complete(endTime = performance.now()) {
@@ -97,7 +97,8 @@ export class VCObserverWrapper {
97
97
  experienceKey,
98
98
  include3p,
99
99
  excludeSmartAnswersInSearch,
100
- includeSSRRatio
100
+ includeSSRRatio,
101
+ includeRawData
101
102
  } = param;
102
103
  const v1v2Result = isVCRevisionEnabled('fy25.01', experienceKey) || isVCRevisionEnabled('fy25.02', experienceKey) ? await ((_this$oldVCObserver4 = this.oldVCObserver) === null || _this$oldVCObserver4 === void 0 ? void 0 : _this$oldVCObserver4.getVCResult(param)) : {};
103
104
  const v3Result = isVCRevisionEnabled('fy25.03', experienceKey) ? await ((_this$newVCObserver3 = this.newVCObserver) === null || _this$newVCObserver3 === void 0 ? void 0 : _this$newVCObserver3.getVCResult({
@@ -110,7 +111,8 @@ export class VCObserverWrapper {
110
111
  includeSSRRatio,
111
112
  interactionType: param.interactionType,
112
113
  isPageVisible: param.isPageVisible,
113
- interactionAbortReason: param.interactionAbortReason
114
+ interactionAbortReason: param.interactionAbortReason,
115
+ includeRawData
114
116
  })) : [];
115
117
  if (!v3Result) {
116
118
  return v1v2Result !== null && v1v2Result !== void 0 ? v1v2Result : {};
@@ -7,6 +7,7 @@ import VCCalculator_FY25_03 from './metric-calculator/fy25_03';
7
7
  import getViewportHeight from './metric-calculator/utils/get-viewport-height';
8
8
  import getViewportWidth from './metric-calculator/utils/get-viewport-width';
9
9
  import VCNextCalculator from './metric-calculator/vcnext';
10
+ import RawDataHandler from './raw-data-handler';
10
11
  import ViewportObserver from './viewport-observer';
11
12
  import WindowEventObserver from './window-event-observer';
12
13
  const SSRState = {
@@ -201,10 +202,12 @@ export default class VCObserverNew {
201
202
  isPageVisible,
202
203
  include3p,
203
204
  includeSSRRatio,
204
- excludeSmartAnswersInSearch
205
+ excludeSmartAnswersInSearch,
206
+ includeRawData
205
207
  } = param;
206
208
  const results = [];
207
209
  this.addStartEntry(start);
210
+ const feVCCalculationStartTime = performance.now();
208
211
  const calculator_fy25_03 = new VCCalculator_FY25_03();
209
212
  if (param.ssr) {
210
213
  this.addSSR(param.ssr);
@@ -247,6 +250,22 @@ export default class VCObserverNew {
247
250
  if (vcNext) {
248
251
  results.push(vcNext);
249
252
  }
253
+ const feVCCalculationEndTime = performance.now();
254
+ if (includeRawData && fg('platform_ufo_enable_vc_raw_data')) {
255
+ const rawVCCalculationStartTime = performance.now();
256
+ const rawHandler = new RawDataHandler();
257
+ const raw = await rawHandler.getRawData({
258
+ entries: orderedEntries,
259
+ startTime: start,
260
+ stopTime: stop,
261
+ isPageVisible
262
+ });
263
+ if (raw) {
264
+ raw.rawVCTime = Number((performance.now() - rawVCCalculationStartTime).toFixed(2));
265
+ raw.feVCTime = Number((feVCCalculationEndTime - feVCCalculationStartTime).toFixed(2));
266
+ results.push(raw);
267
+ }
268
+ }
250
269
  return results;
251
270
  }
252
271
  addStartEntry(startTime) {
@@ -0,0 +1,173 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import getViewportHeight from '../metric-calculator/utils/get-viewport-height';
3
+ import getViewportWidth from '../metric-calculator/utils/get-viewport-width';
4
+ const ABORTING_WINDOW_EVENT = ['wheel', 'scroll', 'keydown', 'resize'];
5
+ const MAX_OBSERVATIONS = 100;
6
+ export default class RawDataHandler {
7
+ constructor() {
8
+ _defineProperty(this, "revisionNo", 'raw-handler');
9
+ }
10
+ getVCCleanStatus(filteredEntries) {
11
+ let dirtyReason = '';
12
+ let abortTimestamp = -1;
13
+ const hasAbortEvent = filteredEntries.some(entry => {
14
+ if (entry.data.type === 'window:event') {
15
+ const data = entry.data;
16
+ if (ABORTING_WINDOW_EVENT.includes(data.eventType)) {
17
+ dirtyReason = data.eventType === 'keydown' ? 'keypress' : data.eventType;
18
+ abortTimestamp = Math.round(entry.time);
19
+ return true;
20
+ }
21
+ }
22
+ return false;
23
+ });
24
+ if (hasAbortEvent && dirtyReason) {
25
+ return {
26
+ isVCClean: false,
27
+ dirtyReason,
28
+ abortTimestamp
29
+ };
30
+ }
31
+ return {
32
+ isVCClean: true
33
+ };
34
+ }
35
+ async getRawData({
36
+ entries,
37
+ startTime,
38
+ stopTime,
39
+ isPageVisible
40
+ }) {
41
+ var _rawObservations;
42
+ let isVCClean;
43
+ let dirtyReason;
44
+ const getVCCleanStatusResult = this.getVCCleanStatus(entries);
45
+ isVCClean = getVCCleanStatusResult.isVCClean;
46
+ dirtyReason = getVCCleanStatusResult.dirtyReason;
47
+ if (!isPageVisible) {
48
+ return {
49
+ revision: this.revisionNo,
50
+ clean: false,
51
+ 'metric:vc90': null,
52
+ abortReason: 'browser_backgrounded',
53
+ abortTimestamp: -1,
54
+ viewport: {
55
+ w: getViewportWidth(),
56
+ h: getViewportHeight()
57
+ }
58
+ };
59
+ }
60
+ const viewportEntries = entries.filter(entry => {
61
+ return entry.time >= startTime && entry.time <= stopTime && entry.data && entry.data.visible;
62
+ });
63
+ const targetNameToIdMap = new Map();
64
+ const elementMapEntriesMap = {};
65
+ let nextElementId = 1;
66
+ const typeMap = new Map();
67
+ const typeMapEntriesMap = {};
68
+ let nextTypeId = 1;
69
+ const attributeMap = new Map();
70
+ const attributeEntriesMap = {};
71
+ let nextAttributeId = 1;
72
+ let rawObservations = viewportEntries.map(entry => {
73
+ const viewportEntry = entry.data;
74
+ const targetName = viewportEntry.elementName || '';
75
+ const type = viewportEntry.type || '';
76
+ const rect = viewportEntry.rect;
77
+ const attributeName = viewportEntry.attributeName || '';
78
+ let eid = targetNameToIdMap.get(viewportEntry.elementName || '') || 0;
79
+ if (eid === 0) {
80
+ eid = nextElementId;
81
+ nextElementId += 1;
82
+ targetNameToIdMap.set(targetName, eid);
83
+ elementMapEntriesMap[eid] = targetName;
84
+ }
85
+ let chg = typeMap.get(type || '') || 0;
86
+ if (chg === 0) {
87
+ chg = nextTypeId;
88
+ nextTypeId += 1;
89
+ typeMap.set(type, chg);
90
+ typeMapEntriesMap[chg] = type;
91
+ }
92
+ let att = 0;
93
+ if (attributeName) {
94
+ att = attributeMap.get(attributeName) || 0;
95
+ if (att === 0) {
96
+ att = nextAttributeId;
97
+ nextAttributeId += 1;
98
+ attributeMap.set(attributeName, att);
99
+ attributeEntriesMap[att] = attributeName;
100
+ }
101
+ }
102
+ const observation = {
103
+ t: Math.round(entry.time),
104
+ r: [Math.round(rect.left * 10) / 10, Math.round(rect.top * 10) / 10, Math.round(rect.right * 10) / 10, Math.round(rect.bottom * 10) / 10],
105
+ chg,
106
+ eid: eid || 0,
107
+ ...(att > 0 ? {
108
+ att
109
+ } : {})
110
+ };
111
+ return observation;
112
+ });
113
+ // If the number of observations is greater than the maximum allowed, we need to trim the observations to the maximum allowed.
114
+ // We do this by keeping the first observation and the last MAX_OBSERVATIONS observations.
115
+ // We then collect the referenced IDs from the remaining observations and remove the unreferenced entries from the maps
116
+ if (rawObservations.length > MAX_OBSERVATIONS) {
117
+ const firstObservation = rawObservations[0];
118
+ const lastObservations = rawObservations.slice(-MAX_OBSERVATIONS);
119
+ rawObservations = [firstObservation, ...lastObservations];
120
+
121
+ // Collect referenced IDs from remaining observations
122
+ const referencedEids = new Set();
123
+ const referencedChgs = new Set();
124
+ const referencedAtts = new Set();
125
+ for (const observation of rawObservations) {
126
+ if (observation.eid > 0) {
127
+ referencedEids.add(observation.eid);
128
+ }
129
+ if (typeof observation.chg === 'number' && observation.chg > 0) {
130
+ referencedChgs.add(observation.chg);
131
+ }
132
+ if (observation.att !== undefined && observation.att > 0) {
133
+ referencedAtts.add(observation.att);
134
+ }
135
+ }
136
+
137
+ // Remove unreferenced entries from maps
138
+ for (const eid of Object.keys(elementMapEntriesMap).map(Number)) {
139
+ if (!referencedEids.has(eid)) {
140
+ delete elementMapEntriesMap[eid];
141
+ }
142
+ }
143
+ for (const chg of Object.keys(typeMapEntriesMap).map(Number)) {
144
+ if (!referencedChgs.has(chg)) {
145
+ delete typeMapEntriesMap[chg];
146
+ }
147
+ }
148
+ for (const att of Object.keys(attributeEntriesMap).map(Number)) {
149
+ if (!referencedAtts.has(att)) {
150
+ delete attributeEntriesMap[att];
151
+ }
152
+ }
153
+ }
154
+ const result = {
155
+ revision: this.revisionNo,
156
+ clean: isVCClean,
157
+ 'metric:vc90': null,
158
+ rawData: {
159
+ obs: (_rawObservations = rawObservations) !== null && _rawObservations !== void 0 ? _rawObservations : undefined,
160
+ eid: elementMapEntriesMap !== null && elementMapEntriesMap !== void 0 ? elementMapEntriesMap : undefined,
161
+ chg: typeMapEntriesMap !== null && typeMapEntriesMap !== void 0 ? typeMapEntriesMap : undefined,
162
+ att: attributeEntriesMap !== null && attributeEntriesMap !== void 0 ? attributeEntriesMap : undefined
163
+ },
164
+ abortReason: dirtyReason,
165
+ abortTimestamp: getVCCleanStatusResult.abortTimestamp,
166
+ viewport: {
167
+ w: getViewportWidth(),
168
+ h: getViewportHeight()
169
+ }
170
+ };
171
+ return result;
172
+ }
173
+ }
@@ -167,6 +167,9 @@ export function getExperimentalInteractionRate(name, interactionType) {
167
167
  return 0;
168
168
  }
169
169
  }
170
+ export function getVCRawDataInteractionRate(name, interactionType) {
171
+ return getConfigRate(name, interactionType, 'enableVCRawDataRates');
172
+ }
170
173
  export function getPostInteractionRate(name, interactionType) {
171
174
  return getConfigRate(name, interactionType, 'postInteractionLog');
172
175
  }
@@ -52,6 +52,7 @@ import { optimizeMarks } from './utils/optimize-marks';
52
52
  import { optimizeReactProfilerTimings } from './utils/optimize-react-profiler-timings';
53
53
  import { optimizeRequestInfo } from './utils/optimize-request-info';
54
54
  import { optimizeSpans } from './utils/optimize-spans';
55
+ var MAX_PAYLOAD_SIZE = 250;
55
56
  function getUfoNameOverride(interaction) {
56
57
  var ufoName = interaction.ufoName,
57
58
  apdex = interaction.apdex;
@@ -390,7 +391,7 @@ function createInteractionMetricsPayload(_x, _x2, _x3, _x4, _x5) {
390
391
  function _createInteractionMetricsPayload() {
391
392
  _createInteractionMetricsPayload = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(interaction, interactionId, experimental, criticalPayloadCount, vcMetrics) {
392
393
  var _window$location, _config$additionalPay;
393
- var interactionPayloadStart, config, end, start, ufoName, knownSegments, rate, type, abortReason, routeName, featureFlags, previousInteractionName, isPreviousInteractionAborted, abortedByInteractionName, responsiveness, unknownElementName, unknownElementHierarchy, hydration, pageVisibilityAtTTI, pageVisibilityAtTTAI, segments, segmentTree, isDetailedPayload, isPageLoad, calculatePageVisibilityFromTheStartOfPageLoad, moreAccuratePageVisibilityAtTTI, moreAccuratePageVisibilityAtTTAI, labelStack, getInitialPageLoadSSRMetrics, pageLoadInteractionMetrics, getDetailedInteractionMetrics, getPageLoadDetailedInteractionMetrics, newUFOName, resourceTimings, _yield$Promise$all, _yield$Promise$all2, finalVCMetrics, experimentalMetrics, paintMetrics, batteryInfo, getReactHydrationStats, payload;
394
+ var interactionPayloadStart, config, end, start, ufoName, knownSegments, rate, type, abortReason, routeName, featureFlags, previousInteractionName, isPreviousInteractionAborted, abortedByInteractionName, responsiveness, unknownElementName, unknownElementHierarchy, hydration, pageVisibilityAtTTI, pageVisibilityAtTTAI, segments, segmentTree, isDetailedPayload, isPageLoad, calculatePageVisibilityFromTheStartOfPageLoad, moreAccuratePageVisibilityAtTTI, moreAccuratePageVisibilityAtTTAI, labelStack, getInitialPageLoadSSRMetrics, pageLoadInteractionMetrics, getDetailedInteractionMetrics, getPageLoadDetailedInteractionMetrics, newUFOName, resourceTimings, _yield$Promise$all, _yield$Promise$all2, finalVCMetrics, experimentalMetrics, paintMetrics, batteryInfo, getReactHydrationStats, payload, size, vcRev, rawData, rawDataSize;
394
395
  return _regeneratorRuntime.wrap(function _callee$(_context) {
395
396
  while (1) switch (_context.prev = _context.next) {
396
397
  case 0:
@@ -596,7 +597,26 @@ function _createInteractionMetricsPayload() {
596
597
  regularTTAI = undefined;
597
598
  expTTAI = undefined;
598
599
  }
599
- payload.attributes.properties['event:sizeInKb'] = getPayloadSize(payload.attributes.properties);
600
+ if (fg('platform_ufo_enable_vc_raw_data')) {
601
+ size = getPayloadSize(payload.attributes.properties);
602
+ vcRev = payload.attributes.properties['ufo:vc:rev'];
603
+ rawData = vcRev.find(function (item) {
604
+ return item.revision === 'raw-handler';
605
+ });
606
+ if (rawData) {
607
+ rawDataSize = getPayloadSize(rawData);
608
+ payload.attributes.properties['ufo:vc:raw:size'] = rawDataSize;
609
+ if (size > MAX_PAYLOAD_SIZE && Array.isArray(vcRev) && vcRev.length > 0) {
610
+ payload.attributes.properties['ufo:vc:rev'] = vcRev.filter(function (item) {
611
+ return item.revision !== 'raw-handler';
612
+ });
613
+ payload.attributes.properties['ufo:vc:raw:removed'] = true;
614
+ }
615
+ }
616
+ payload.attributes.properties['event:sizeInKb'] = getPayloadSize(payload.attributes.properties);
617
+ } else {
618
+ payload.attributes.properties['event:sizeInKb'] = getPayloadSize(payload.attributes.properties);
619
+ }
600
620
  return _context.abrupt("return", payload);
601
621
  case 47:
602
622
  case "end":
@@ -3,7 +3,8 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
3
3
  import _regeneratorRuntime from "@babel/runtime/regenerator";
4
4
  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; }
5
5
  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) { _defineProperty(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; }
6
- import { getConfig, getMostRecentVCRevision } from '../../config';
6
+ import coinflip from '../../coinflip';
7
+ import { getConfig, getMostRecentVCRevision, getVCRawDataInteractionRate } from '../../config';
7
8
  import { interactionExtraMetrics, postInteractionLog } from '../../interaction-metrics';
8
9
  import getInteractionStatus from './get-interaction-status';
9
10
  import getPageVisibilityUpToTTAI from './get-page-visibility-up-to-ttai';
@@ -22,6 +23,7 @@ function _getVCMetrics() {
22
23
  isPageVisible,
23
24
  shouldReportVCMetrics,
24
25
  observer,
26
+ includeRawData,
25
27
  isSSREnabled,
26
28
  ssr,
27
29
  tti,
@@ -59,6 +61,7 @@ function _getVCMetrics() {
59
61
  }
60
62
  return _context.abrupt("return", {});
61
63
  case 14:
64
+ includeRawData = coinflip(getVCRawDataInteractionRate(interaction.ufoName, interaction.type));
62
65
  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)));
63
66
  ssr = interaction.type === 'page_load' && isSSREnabled ? {
64
67
  ssr: getSSRDoneTimeValue(config)
@@ -66,7 +69,7 @@ function _getVCMetrics() {
66
69
  postInteractionLog.setVCObserverSSRConfig(ssr);
67
70
  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;
68
71
  prefix = 'ufo';
69
- _context.next = 21;
72
+ _context.next = 22;
70
73
  return observer.getVCResult(_objectSpread(_objectSpread({
71
74
  start: interaction.start,
72
75
  stop: interaction.end,
@@ -82,9 +85,10 @@ function _getVCMetrics() {
82
85
  include3p: include3p,
83
86
  excludeSmartAnswersInSearch: excludeSmartAnswersInSearch,
84
87
  interactionType: interaction.type,
85
- isPageVisible: isPageVisible
88
+ isPageVisible: isPageVisible,
89
+ includeRawData: includeRawData
86
90
  }));
87
- case 21:
91
+ case 22:
88
92
  result = _context.sent;
89
93
  observer.stop(interaction.ufoName);
90
94
  if (!include3p) {
@@ -98,15 +102,15 @@ function _getVCMetrics() {
98
102
  return revision === mostRecentVCRevision;
99
103
  });
100
104
  if (!(!shouldReportVCMetrics || !(mostRecentVCRevisionPayload !== null && mostRecentVCRevisionPayload !== void 0 && mostRecentVCRevisionPayload.clean))) {
101
- _context.next = 28;
105
+ _context.next = 29;
102
106
  break;
103
107
  }
104
108
  return _context.abrupt("return", result);
105
- case 28:
109
+ case 29:
106
110
  return _context.abrupt("return", _objectSpread(_objectSpread({}, result), {}, {
107
111
  'metric:vc90': mostRecentVCRevisionPayload['metric:vc90']
108
112
  }));
109
- case 29:
113
+ case 30:
110
114
  case "end":
111
115
  return _context.stop();
112
116
  }
@@ -33,6 +33,7 @@ var interactionQueue = [];
33
33
  var segmentCache = new Map();
34
34
  export var segmentUnmountCache = new Map(); // Temporarily store segment unmount counts
35
35
 
36
+ var firstSegmentLoadMarked = false;
36
37
  var segmentObservers = [];
37
38
  export function getActiveInteraction() {
38
39
  var interactionId = getInteractionId();
@@ -229,6 +230,22 @@ export function addMark(interactionId, type, name, labelStack) {
229
230
  });
230
231
  }
231
232
  }
233
+ export function markFirstSegmentLoad(interactionId, labelStack) {
234
+ var time = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : performance.now();
235
+ if (!fg('platform_mark_ufo_segment_first_load')) {
236
+ return;
237
+ }
238
+ var interaction = interactions.get(interactionId);
239
+ if (interaction != null && !firstSegmentLoadMarked) {
240
+ firstSegmentLoadMarked = true;
241
+ interaction.marks.push({
242
+ type: 'first_segment_load',
243
+ name: 'first_segment_load',
244
+ labelStack: labelStack,
245
+ time: time
246
+ });
247
+ }
248
+ }
232
249
  export function addMarkToAll(type, name, labelStack) {
233
250
  var time = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : performance.now();
234
251
  interactions.forEach(function (interaction) {
@@ -11,11 +11,12 @@ import { getConfig, getDoNotAbortActivePressInteraction, getInteractionRate, get
11
11
  import { getActiveTrace, setInteractionActiveTrace } from '../experience-trace-id-context';
12
12
  import UFOInteractionContext from '../interaction-context';
13
13
  import UFOInteractionIDContext from '../interaction-id-context';
14
- import { abortByNewInteraction, addApdex as _addApdex, addCustomData as _addCustomData, addCustomTiming, addHold, addHoldByID, addMark as _addMark, addNewInteraction, addProfilerTimings, addRequestInfo, addSegment, addSpan, getActiveInteraction, removeHoldByID, removeSegment, tryComplete } from '../interaction-metrics';
14
+ import { abortByNewInteraction, addApdex as _addApdex, addCustomData as _addCustomData, addCustomTiming, addHold, addHoldByID, addMark as _addMark, addNewInteraction, addProfilerTimings, addRequestInfo, addSegment, addSpan, getActiveInteraction, markFirstSegmentLoad, removeHoldByID, removeSegment, tryComplete } from '../interaction-metrics';
15
15
  import UFORouteName from '../route-name-context';
16
16
  import generateId from '../short-id';
17
17
  import scheduleOnPaint from './schedule-on-paint';
18
18
  var tryCompleteHandle;
19
+ var hasMarkedFirstSegmentLoad = false;
19
20
 
20
21
  /** A portion of the page we apply measurement to */
21
22
  export default function UFOSegment(_ref) {
@@ -58,6 +59,10 @@ export default function UFOSegment(_ref) {
58
59
  } : {})];
59
60
  }, [parentContext, segmentName, segmentId, type]);
60
61
  var interactionId = useContext(UFOInteractionIDContext);
62
+ if (interactionId.current != null && !hasMarkedFirstSegmentLoad) {
63
+ markFirstSegmentLoad(interactionId.current, labelStack, performance.now());
64
+ hasMarkedFirstSegmentLoad = true;
65
+ }
61
66
  var interactionContext = useMemo(function () {
62
67
  var lastCompleteEndTime = 0;
63
68
  function complete() {
@@ -112,11 +112,11 @@ export var VCObserverWrapper = /*#__PURE__*/function () {
112
112
  value: function () {
113
113
  var _getVCResult = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(param) {
114
114
  var _this$oldVCObserver4, _this$newVCObserver3, _ref2;
115
- var experienceKey, include3p, excludeSmartAnswersInSearch, includeSSRRatio, v1v2Result, v3Result, ssrRatio;
115
+ var experienceKey, include3p, excludeSmartAnswersInSearch, includeSSRRatio, includeRawData, v1v2Result, v3Result, ssrRatio;
116
116
  return _regeneratorRuntime.wrap(function _callee$(_context) {
117
117
  while (1) switch (_context.prev = _context.next) {
118
118
  case 0:
119
- experienceKey = param.experienceKey, include3p = param.include3p, excludeSmartAnswersInSearch = param.excludeSmartAnswersInSearch, includeSSRRatio = param.includeSSRRatio;
119
+ experienceKey = param.experienceKey, include3p = param.include3p, excludeSmartAnswersInSearch = param.excludeSmartAnswersInSearch, includeSSRRatio = param.includeSSRRatio, includeRawData = param.includeRawData;
120
120
  if (!(isVCRevisionEnabled('fy25.01', experienceKey) || isVCRevisionEnabled('fy25.02', experienceKey))) {
121
121
  _context.next = 7;
122
122
  break;
@@ -146,7 +146,8 @@ export var VCObserverWrapper = /*#__PURE__*/function () {
146
146
  includeSSRRatio: includeSSRRatio,
147
147
  interactionType: param.interactionType,
148
148
  isPageVisible: param.isPageVisible,
149
- interactionAbortReason: param.interactionAbortReason
149
+ interactionAbortReason: param.interactionAbortReason,
150
+ includeRawData: includeRawData
150
151
  });
151
152
  case 12:
152
153
  _context.t1 = _context.sent;
@@ -13,6 +13,7 @@ import VCCalculator_FY25_03 from './metric-calculator/fy25_03';
13
13
  import getViewportHeight from './metric-calculator/utils/get-viewport-height';
14
14
  import getViewportWidth from './metric-calculator/utils/get-viewport-width';
15
15
  import VCNextCalculator from './metric-calculator/vcnext';
16
+ import RawDataHandler from './raw-data-handler';
16
17
  import ViewportObserver from './viewport-observer';
17
18
  import WindowEventObserver from './window-event-observer';
18
19
  var SSRState = {
@@ -231,13 +232,14 @@ var VCObserverNew = /*#__PURE__*/function () {
231
232
  key: "getVCResult",
232
233
  value: function () {
233
234
  var _getVCResult = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(param) {
234
- var start, stop, interactionId, interactionType, interactionAbortReason, isPageVisible, include3p, includeSSRRatio, excludeSmartAnswersInSearch, results, calculator_fy25_03, orderedEntries, fy25_03, calculator_next, vcNext;
235
+ var start, stop, interactionId, interactionType, interactionAbortReason, isPageVisible, include3p, includeSSRRatio, excludeSmartAnswersInSearch, includeRawData, results, feVCCalculationStartTime, calculator_fy25_03, orderedEntries, fy25_03, calculator_next, vcNext, feVCCalculationEndTime, rawVCCalculationStartTime, rawHandler, raw;
235
236
  return _regeneratorRuntime.wrap(function _callee$(_context) {
236
237
  while (1) switch (_context.prev = _context.next) {
237
238
  case 0:
238
- start = param.start, stop = param.stop, interactionId = param.interactionId, interactionType = param.interactionType, interactionAbortReason = param.interactionAbortReason, isPageVisible = param.isPageVisible, include3p = param.include3p, includeSSRRatio = param.includeSSRRatio, excludeSmartAnswersInSearch = param.excludeSmartAnswersInSearch;
239
+ start = param.start, stop = param.stop, interactionId = param.interactionId, interactionType = param.interactionType, interactionAbortReason = param.interactionAbortReason, isPageVisible = param.isPageVisible, include3p = param.include3p, includeSSRRatio = param.includeSSRRatio, excludeSmartAnswersInSearch = param.excludeSmartAnswersInSearch, includeRawData = param.includeRawData;
239
240
  results = [];
240
241
  this.addStartEntry(start);
242
+ feVCCalculationStartTime = performance.now();
241
243
  calculator_fy25_03 = new VCCalculator_FY25_03();
242
244
  if (param.ssr) {
243
245
  this.addSSR(param.ssr);
@@ -246,7 +248,7 @@ var VCObserverNew = /*#__PURE__*/function () {
246
248
  start: start,
247
249
  stop: stop
248
250
  });
249
- _context.next = 8;
251
+ _context.next = 9;
250
252
  return calculator_fy25_03.calculate({
251
253
  orderedEntries: orderedEntries,
252
254
  startTime: start,
@@ -260,7 +262,7 @@ var VCObserverNew = /*#__PURE__*/function () {
260
262
  isPageVisible: isPageVisible,
261
263
  interactionAbortReason: interactionAbortReason
262
264
  });
263
- case 8:
265
+ case 9:
264
266
  fy25_03 = _context.sent;
265
267
  if (fy25_03) {
266
268
  results.push(fy25_03);
@@ -268,7 +270,7 @@ var VCObserverNew = /*#__PURE__*/function () {
268
270
 
269
271
  // TODO on cleanup: put behind `enabledVCRevisions` config
270
272
  calculator_next = new VCNextCalculator();
271
- _context.next = 13;
273
+ _context.next = 14;
272
274
  return calculator_next.calculate({
273
275
  orderedEntries: orderedEntries,
274
276
  startTime: start,
@@ -281,13 +283,35 @@ var VCObserverNew = /*#__PURE__*/function () {
281
283
  isPageVisible: isPageVisible,
282
284
  interactionAbortReason: interactionAbortReason
283
285
  });
284
- case 13:
286
+ case 14:
285
287
  vcNext = _context.sent;
286
288
  if (vcNext) {
287
289
  results.push(vcNext);
288
290
  }
291
+ feVCCalculationEndTime = performance.now();
292
+ if (!(includeRawData && fg('platform_ufo_enable_vc_raw_data'))) {
293
+ _context.next = 24;
294
+ break;
295
+ }
296
+ rawVCCalculationStartTime = performance.now();
297
+ rawHandler = new RawDataHandler();
298
+ _context.next = 22;
299
+ return rawHandler.getRawData({
300
+ entries: orderedEntries,
301
+ startTime: start,
302
+ stopTime: stop,
303
+ isPageVisible: isPageVisible
304
+ });
305
+ case 22:
306
+ raw = _context.sent;
307
+ if (raw) {
308
+ raw.rawVCTime = Number((performance.now() - rawVCCalculationStartTime).toFixed(2));
309
+ raw.feVCTime = Number((feVCCalculationEndTime - feVCCalculationStartTime).toFixed(2));
310
+ results.push(raw);
311
+ }
312
+ case 24:
289
313
  return _context.abrupt("return", results);
290
- case 16:
314
+ case 25:
291
315
  case "end":
292
316
  return _context.stop();
293
317
  }