@atlaskit/react-ufo 5.2.5 → 5.2.7

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 (43) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/config/index.js +48 -28
  3. package/dist/cjs/create-payload/index.js +2 -2
  4. package/dist/cjs/experience-trace-id-context/context-manager.js +4 -4
  5. package/dist/cjs/ignore-holds/index.js +1 -2
  6. package/dist/cjs/interaction-metrics-init/index.js +10 -1
  7. package/dist/cjs/load-hold/UFOLoadHold.js +9 -1
  8. package/dist/cjs/segment/segment.js +10 -2
  9. package/dist/cjs/segment/third-party-segment.js +1 -2
  10. package/dist/cjs/trace-interaction/internal/trace-ufo-interaction.js +4 -0
  11. package/dist/cjs/trace-pageload/index.js +8 -0
  12. package/dist/cjs/trace-transition/index.js +4 -0
  13. package/dist/es2019/config/index.js +21 -2
  14. package/dist/es2019/create-payload/index.js +1 -1
  15. package/dist/es2019/experience-trace-id-context/context-manager.js +4 -4
  16. package/dist/es2019/ignore-holds/index.js +1 -2
  17. package/dist/es2019/interaction-metrics-init/index.js +11 -2
  18. package/dist/es2019/load-hold/UFOLoadHold.js +9 -1
  19. package/dist/es2019/segment/segment.js +11 -3
  20. package/dist/es2019/segment/third-party-segment.js +1 -2
  21. package/dist/es2019/trace-interaction/internal/trace-ufo-interaction.js +5 -1
  22. package/dist/es2019/trace-pageload/index.js +9 -1
  23. package/dist/es2019/trace-transition/index.js +5 -1
  24. package/dist/esm/config/index.js +47 -28
  25. package/dist/esm/create-payload/index.js +2 -2
  26. package/dist/esm/experience-trace-id-context/context-manager.js +4 -4
  27. package/dist/esm/ignore-holds/index.js +1 -2
  28. package/dist/esm/interaction-metrics-init/index.js +11 -2
  29. package/dist/esm/load-hold/UFOLoadHold.js +9 -1
  30. package/dist/esm/segment/segment.js +11 -3
  31. package/dist/esm/segment/third-party-segment.js +1 -2
  32. package/dist/esm/trace-interaction/internal/trace-ufo-interaction.js +5 -1
  33. package/dist/esm/trace-pageload/index.js +9 -1
  34. package/dist/esm/trace-transition/index.js +5 -1
  35. package/dist/types/config/index.d.ts +10 -0
  36. package/dist/types/ignore-holds/index.d.ts +1 -5
  37. package/dist/types/segment/segment.d.ts +1 -5
  38. package/dist/types/segment/third-party-segment.d.ts +0 -3
  39. package/dist/types-ts4.5/config/index.d.ts +10 -0
  40. package/dist/types-ts4.5/ignore-holds/index.d.ts +1 -5
  41. package/dist/types-ts4.5/segment/segment.d.ts +1 -5
  42. package/dist/types-ts4.5/segment/third-party-segment.d.ts +0 -3
  43. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @atlaskit/ufo-interaction-ignore
2
2
 
3
+ ## 5.2.7
4
+
5
+ ### Patch Changes
6
+
7
+ - [`a059dfab456d9`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/a059dfab456d9) -
8
+ Add back UFO killswitch config
9
+
10
+ ## 5.2.6
11
+
12
+ ### Patch Changes
13
+
14
+ - [`33f328a1704e1`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/33f328a1704e1) -
15
+ FG cleanup - platform_ufo_browser_backgrounded_abort_timestamp
16
+
3
17
  ## 5.2.5
4
18
 
5
19
  ### Patch Changes
@@ -23,6 +23,7 @@ exports.getReactHydrationStats = getReactHydrationStats;
23
23
  exports.getTypingPerformanceTracingMethod = getTypingPerformanceTracingMethod;
24
24
  exports.getUfoNameOverrides = getUfoNameOverrides;
25
25
  exports.getVCRawDataInteractionRate = getVCRawDataInteractionRate;
26
+ exports.isUFOEnabled = isUFOEnabled;
26
27
  exports.isVCRevisionEnabled = isVCRevisionEnabled;
27
28
  exports.setUFOConfig = setUFOConfig;
28
29
  exports.shouldUseRawDataThirdPartyBehavior = shouldUseRawDataThirdPartyBehavior;
@@ -61,6 +62,25 @@ function setUFOConfig(newConfig) {
61
62
  function getConfig() {
62
63
  return config;
63
64
  }
65
+
66
+ /**
67
+ * Check if UFO is enabled based on the config.enabled field.
68
+ *
69
+ * This function is gated behind the platform_ufo_enable_killswitch_config feature flag.
70
+ * When the feature flag is disabled, UFO is always considered enabled (default behavior).
71
+ * When the feature flag is enabled, the config.enabled field is respected.
72
+ *
73
+ * @returns true if UFO is enabled, false if disabled
74
+ */
75
+ function isUFOEnabled() {
76
+ var _config;
77
+ // Only respect the config.enabled field when the killswitch feature flag is enabled
78
+ if (!(0, _platformFeatureFlags.fg)('platform_ufo_enable_killswitch_config')) {
79
+ return true;
80
+ }
81
+ // Default to enabled if config is not set or enabled is not explicitly false
82
+ return ((_config = config) === null || _config === void 0 ? void 0 : _config.enabled) !== false;
83
+ }
64
84
  var isValidConfigArray = function isValidConfigArray(array) {
65
85
  return Array.isArray(array) && array.length > 0;
66
86
  };
@@ -102,8 +122,8 @@ function getReactHydrationStats() {
102
122
  return undefined;
103
123
  }
104
124
  try {
105
- var _config, _config$getReactHydra;
106
- var stats = (_config = config) === null || _config === void 0 || (_config$getReactHydra = _config.getReactHydrationStats) === null || _config$getReactHydra === void 0 ? void 0 : _config$getReactHydra.call(_config);
125
+ var _config2, _config2$getReactHydr;
126
+ var stats = (_config2 = config) === null || _config2 === void 0 || (_config2$getReactHydr = _config2.getReactHydrationStats) === null || _config2$getReactHydr === void 0 ? void 0 : _config2$getReactHydr.call(_config2);
107
127
  return stats !== null && stats !== void 0 ? stats : undefined;
108
128
  } catch (e) {
109
129
  // eslint-disable-next-line no-console
@@ -116,12 +136,12 @@ function getInteractionRate(name, interactionKind) {
116
136
  if (!config) {
117
137
  return 0;
118
138
  }
119
- var _config2 = config,
120
- killswitch = _config2.killswitch,
121
- rates = _config2.rates,
122
- rules = _config2.rules,
123
- kind = _config2.kind,
124
- autoGeneratedRate = _config2.autoGeneratedRate;
139
+ var _config3 = config,
140
+ killswitch = _config3.killswitch,
141
+ rates = _config3.rates,
142
+ rules = _config3.rules,
143
+ kind = _config3.kind,
144
+ autoGeneratedRate = _config3.autoGeneratedRate;
125
145
  if (killswitch != null) {
126
146
  // Specifically kill certain events
127
147
  if (killswitch.includes(name)) {
@@ -179,8 +199,8 @@ function getExperimentalInteractionRate(name, interactionType) {
179
199
  if (!config) {
180
200
  return 0;
181
201
  }
182
- var _config3 = config,
183
- experimentalInteractionMetrics = _config3.experimentalInteractionMetrics;
202
+ var _config4 = config,
203
+ experimentalInteractionMetrics = _config4.experimentalInteractionMetrics;
184
204
  if (!(experimentalInteractionMetrics !== null && experimentalInteractionMetrics !== void 0 && experimentalInteractionMetrics.enabled)) {
185
205
  return 0;
186
206
  }
@@ -215,8 +235,8 @@ function getCapabilityRate(capability) {
215
235
  if (!config) {
216
236
  return 0;
217
237
  }
218
- var _config4 = config,
219
- capabilityRate = _config4.capability;
238
+ var _config5 = config,
239
+ capabilityRate = _config5.capability;
220
240
  if (capabilityRate != null) {
221
241
  var rate = capabilityRate[capability];
222
242
  if (rate != null) {
@@ -261,8 +281,8 @@ function getTypingPerformanceTracingMethod() {
261
281
  if (!config) {
262
282
  return defaultMethod;
263
283
  }
264
- var _config5 = config,
265
- typingMethod = _config5.typingMethod;
284
+ var _config6 = config,
285
+ typingMethod = _config6.typingMethod;
266
286
  if (typingMethod != null && validTypingMethods.find(function (m) {
267
287
  return m === typingMethod;
268
288
  })) {
@@ -281,8 +301,8 @@ function getAwaitBM3TTIList() {
281
301
  if (!config) {
282
302
  return [];
283
303
  }
284
- var _config6 = config,
285
- awaitBM3TTI = _config6.awaitBM3TTI;
304
+ var _config7 = config,
305
+ awaitBM3TTI = _config7.awaitBM3TTI;
286
306
  if (awaitBM3TTI != null) {
287
307
  return awaitBM3TTI;
288
308
  } else {
@@ -302,8 +322,8 @@ function getUfoNameOverrides() {
302
322
  if (!config) {
303
323
  return undefined;
304
324
  }
305
- var _config7 = config,
306
- ufoNameOverrides = _config7.ufoNameOverrides;
325
+ var _config8 = config,
326
+ ufoNameOverrides = _config8.ufoNameOverrides;
307
327
  if (ufoNameOverrides != null) {
308
328
  return ufoNameOverrides;
309
329
  }
@@ -317,8 +337,8 @@ function getMinorInteractions() {
317
337
  if (!config) {
318
338
  return undefined;
319
339
  }
320
- var _config8 = config,
321
- minorInteractions = _config8.minorInteractions;
340
+ var _config9 = config,
341
+ minorInteractions = _config9.minorInteractions;
322
342
  return minorInteractions;
323
343
  } catch (_unused9) {
324
344
  return undefined;
@@ -331,8 +351,8 @@ function getDoNotAbortActivePressInteraction() {
331
351
  if (!config) {
332
352
  return undefined;
333
353
  }
334
- var _config9 = config,
335
- doNotAbortActivePressInteraction = _config9.doNotAbortActivePressInteraction;
354
+ var _config0 = config,
355
+ doNotAbortActivePressInteraction = _config0.doNotAbortActivePressInteraction;
336
356
  return doNotAbortActivePressInteraction;
337
357
  } catch (_unused0) {
338
358
  return undefined;
@@ -345,8 +365,8 @@ function getDoNotAbortActivePressInteractionOnTransition() {
345
365
  if (!config) {
346
366
  return undefined;
347
367
  }
348
- var _config0 = config,
349
- doNotAbortActivePressInteractionOnTransition = _config0.doNotAbortActivePressInteractionOnTransition;
368
+ var _config1 = config,
369
+ doNotAbortActivePressInteractionOnTransition = _config1.doNotAbortActivePressInteractionOnTransition;
350
370
  return doNotAbortActivePressInteractionOnTransition;
351
371
  } catch (_unused1) {
352
372
  return undefined;
@@ -359,8 +379,8 @@ function getFinishInteractionOnTransition() {
359
379
  if (!config) {
360
380
  return undefined;
361
381
  }
362
- var _config1 = config,
363
- finishInteractionOnTransition = _config1.finishInteractionOnTransition;
382
+ var _config10 = config,
383
+ finishInteractionOnTransition = _config10.finishInteractionOnTransition;
364
384
  return finishInteractionOnTransition;
365
385
  } catch (_unused10) {
366
386
  return undefined;
@@ -372,8 +392,8 @@ function getInteractionTimeout(ufoName) {
372
392
  if (!config) {
373
393
  return CLEANUP_TIMEOUT;
374
394
  }
375
- var _config10 = config,
376
- interactionTimeout = _config10.interactionTimeout;
395
+ var _config11 = config,
396
+ interactionTimeout = _config11.interactionTimeout;
377
397
  if (interactionTimeout != null && interactionTimeout[ufoName] != null) {
378
398
  return interactionTimeout[ufoName];
379
399
  }
@@ -9,9 +9,9 @@ try{return acc+item.cssRules.length;}catch(_unused3){return acc;}},0);var styleE
9
9
  getInitialPageLoadSSRMetrics=function getInitialPageLoadSSRMetrics(){var _config$ssr;if(!isPageLoad){return{};}var config=(0,_config.getConfig)();var SSRDoneTimeValue=(0,_getSsrDoneTimeValue.default)(config);var SSRDoneTime=SSRDoneTimeValue!==undefined?{SSRDoneTime:Math.round(SSRDoneTimeValue)}:{};var isBM3ConfigSSRDoneAsFmp=interaction.metaData.__legacy__bm3ConfigSSRDoneAsFmp;var isUFOConfigSSRDoneAsFmp=interaction.metaData.__legacy__bm3ConfigSSRDoneAsFmp||!!(config!==null&&config!==void 0&&(_config$ssr=config.ssr)!==null&&_config$ssr!==void 0&&_config$ssr.getSSRDoneTime);if(!experimental&&(isBM3ConfigSSRDoneAsFmp||isUFOConfigSSRDoneAsFmp)&&SSRDoneTimeValue!==undefined){try{performance.mark("FMP",{startTime:SSRDoneTimeValue,detail:{devtools:{dataType:'marker'}}});}catch(_unused6){}}return _objectSpread(_objectSpread({},SSRDoneTime),{},{isBM3ConfigSSRDoneAsFmp:isBM3ConfigSSRDoneAsFmp,isUFOConfigSSRDoneAsFmp:isUFOConfigSSRDoneAsFmp});};pageLoadInteractionMetrics=getInitialPageLoadSSRMetrics();// Detailed payload. Page visibility = visible
10
10
  getDetailedInteractionMetrics=function getDetailedInteractionMetrics(resourceTimings){if(experimental||window.__UFO_COMPACT_PAYLOAD__||!isDetailedPayload){return{};}var spans=[].concat((0,_toConsumableArray2.default)(interaction.spans),(0,_toConsumableArray2.default)(_interactionMetrics.interactionSpans));_interactionMetrics.interactionSpans.length=0;var shouldInclude3pHolds=(0,_config.shouldUseRawDataThirdPartyBehavior)(ufoName,type);var basePayload={errors:interaction.errors.map(function(_ref2){var labelStack=_ref2.labelStack,others=(0,_objectWithoutProperties2.default)(_ref2,_excluded);return _objectSpread(_objectSpread({},others),{},{labelStack:labelStack&&(0,_utils.optimizeLabelStack)(labelStack,(0,_getReactUfoPayloadVersion.getReactUFOPayloadVersion)(interaction.type))});}),holdActive:(0,_toConsumableArray2.default)(interaction.holdActive.values()),redirects:optimizeRedirects(interaction.redirects,start),holdInfo:(0,_optimizeHoldInfo.optimizeHoldInfo)(experimental?interaction.holdExpInfo:interaction.holdInfo,start,(0,_getReactUfoPayloadVersion.getReactUFOPayloadVersion)(interaction.type)),spans:(0,_optimizeSpans.optimizeSpans)(spans,start,(0,_getReactUfoPayloadVersion.getReactUFOPayloadVersion)(interaction.type)),requestInfo:(0,_optimizeRequestInfo.optimizeRequestInfo)(interaction.requestInfo,start,(0,_getReactUfoPayloadVersion.getReactUFOPayloadVersion)(interaction.type)),customTimings:(0,_optimizeCustomTimings.optimizeCustomTimings)(interaction.customTimings,start),bundleEvalTimings:objectToArray(getBundleEvalTimings(start)),resourceTimings:objectToArray(resourceTimings)};// Include third-party holds when feature flag is active
11
11
  if(shouldInclude3pHolds){var _interaction$hold3pIn;return _objectSpread(_objectSpread({},basePayload),{},{hold3pActive:interaction.hold3pActive?(0,_toConsumableArray2.default)(interaction.hold3pActive.values()):[],hold3pInfo:(0,_optimizeHoldInfo.optimizeHoldInfo)((_interaction$hold3pIn=interaction.hold3pInfo)!==null&&_interaction$hold3pIn!==void 0?_interaction$hold3pIn:[],start,(0,_getReactUfoPayloadVersion.getReactUFOPayloadVersion)(interaction.type))});}return basePayload;};// Page load & detailed payload
12
- getPageLoadDetailedInteractionMetrics=function getPageLoadDetailedInteractionMetrics(){var _config$ssr2,_config$ssr2$getSSRTi;if(!isPageLoad||!isDetailedPayload){return{};}var initialPageLoadExtraTimings=objectToArray(initialPageLoadExtraTiming.getTimings());var config=(0,_config.getConfig)();var defaultSSRTimings=objectToArray(ssr.getSSRTimings());var ssrTimingsFromConfig=config===null||config===void 0||(_config$ssr2=config.ssr)===null||_config$ssr2===void 0||(_config$ssr2$getSSRTi=_config$ssr2.getSSRTimings)===null||_config$ssr2$getSSRTi===void 0?void 0:_config$ssr2$getSSRTi.call(_config$ssr2);return{initialPageLoadExtraTimings:initialPageLoadExtraTimings,SSRTimings:ssrTimingsFromConfig?[].concat((0,_toConsumableArray2.default)(ssrTimingsFromConfig),(0,_toConsumableArray2.default)(defaultSSRTimings)):defaultSSRTimings};};if(experimental){expTTAI=(0,_getTtai.default)(interaction);}else{regularTTAI=(0,_getTtai.default)(interaction);}newUFOName=(0,_utils.sanitizeUfoName)(ufoName);resourceTimings=getResourceTimings(start,end);_context.t0=Promise;_context.t1=vcMetrics;if(_context.t1){_context.next=29;break;}_context.next=28;return(0,_getVcMetrics.default)(interaction);case 28:_context.t1=_context.sent;case 29:_context.t2=_context.t1;_context.t3=experimental?(0,_createExperimentalInteractionMetricsPayload.getExperimentalVCMetrics)(interaction):Promise.resolve(undefined);_context.t4=(0,_getPaintMetrics.getPaintMetricsToLegacyFormat)(type,end);_context.t5=(0,_getBatteryInfo.getBatteryInfoToLegacyFormat)();_context.t6=[_context.t2,_context.t3,_context.t4,_context.t5];_context.next=36;return _context.t0.all.call(_context.t0,_context.t6);case 36:_yield$Promise$all=_context.sent;_yield$Promise$all2=(0,_slicedToArray2.default)(_yield$Promise$all,4);finalVCMetrics=_yield$Promise$all2[0];experimentalMetrics=_yield$Promise$all2[1];paintMetrics=_yield$Promise$all2[2];batteryInfo=_yield$Promise$all2[3];if(!experimental){(0,_addPerformanceMeasures.addPerformanceMeasures)(interaction.start,(0,_toConsumableArray2.default)((finalVCMetrics===null||finalVCMetrics===void 0?void 0:finalVCMetrics['ufo:vc:rev'])||[]));}getReactHydrationStats=function getReactHydrationStats(){if(!hydration){return{};}return{hydration:hydration};};payload={actionSubject:'experience',action:'measured',eventType:'operational',source:'measured',tags:['observability'],attributes:{properties:_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({// basic
12
+ getPageLoadDetailedInteractionMetrics=function getPageLoadDetailedInteractionMetrics(){var _config$ssr2,_config$ssr2$getSSRTi;if(!isPageLoad||!isDetailedPayload){return{};}var initialPageLoadExtraTimings=objectToArray(initialPageLoadExtraTiming.getTimings());var config=(0,_config.getConfig)();var defaultSSRTimings=objectToArray(ssr.getSSRTimings());var ssrTimingsFromConfig=config===null||config===void 0||(_config$ssr2=config.ssr)===null||_config$ssr2===void 0||(_config$ssr2$getSSRTi=_config$ssr2.getSSRTimings)===null||_config$ssr2$getSSRTi===void 0?void 0:_config$ssr2$getSSRTi.call(_config$ssr2);return{initialPageLoadExtraTimings:initialPageLoadExtraTimings,SSRTimings:ssrTimingsFromConfig?[].concat((0,_toConsumableArray2.default)(ssrTimingsFromConfig),(0,_toConsumableArray2.default)(defaultSSRTimings)):defaultSSRTimings};};if(experimental){expTTAI=(0,_getTtai.default)(interaction);}else{regularTTAI=(0,_getTtai.default)(interaction);}newUFOName=(0,_utils.sanitizeUfoName)(ufoName);resourceTimings=getResourceTimings(start,end);_context.t0=Promise;_context.t1=vcMetrics;if(_context.t1){_context.next=29;break;}_context.next=28;return(0,_getVcMetrics.default)(interaction);case 28:_context.t1=_context.sent;case 29:_context.t2=_context.t1;_context.t3=experimental?(0,_createExperimentalInteractionMetricsPayload.getExperimentalVCMetrics)(interaction):Promise.resolve(undefined);_context.t4=(0,_getPaintMetrics.getPaintMetricsToLegacyFormat)(type,end);_context.t5=(0,_getBatteryInfo.getBatteryInfoToLegacyFormat)();_context.t6=[_context.t2,_context.t3,_context.t4,_context.t5];_context.next=36;return _context.t0.all.call(_context.t0,_context.t6);case 36:_yield$Promise$all=_context.sent;_yield$Promise$all2=(0,_slicedToArray2.default)(_yield$Promise$all,4);finalVCMetrics=_yield$Promise$all2[0];experimentalMetrics=_yield$Promise$all2[1];paintMetrics=_yield$Promise$all2[2];batteryInfo=_yield$Promise$all2[3];if(!experimental){(0,_addPerformanceMeasures.addPerformanceMeasures)(interaction.start,(0,_toConsumableArray2.default)((finalVCMetrics===null||finalVCMetrics===void 0?void 0:finalVCMetrics['ufo:vc:rev'])||[]));}getReactHydrationStats=function getReactHydrationStats(){if(!hydration){return{};}return{hydration:hydration};};payload={actionSubject:'experience',action:'measured',eventType:'operational',source:'measured',tags:['observability'],attributes:{properties:_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({// basic
13
13
  'event:hostname':((_window$location=window.location)===null||_window$location===void 0?void 0:_window$location.hostname)||'unknown','event:product':config.product,'event:population':config.population,'event:schema':'1.0.0','event:sizeInKb':0,'event:source':{name:'react-ufo/web',version:(0,_getReactUfoPayloadVersion.getReactUFOPayloadVersion)(interaction.type)},'event:region':config.region||'unknown','experience:key':experimental?'custom.experimental-interaction-metrics':'custom.interaction-metrics','experience:name':newUFOName,// Include CPU usage monitoring data
14
- 'event:cpu:usage':(0,_machineUtilisation.createPressureStateReport)(interaction.start,interaction.end),'event:memory:usage':(0,_machineUtilisation.createMemoryStateReport)(interaction.start,interaction.end)},criticalPayloadCount!==undefined?{'ufo:multipayload':true,'ufo:criticalPayloadCount':criticalPayloadCount}:{}),(0,_platformFeatureFlags.fg)('platform_ufo_browser_backgrounded_abort_timestamp')?{'ufo:pageVisibilityHiddenTimestamp':(0,_hiddenTiming.getEarliestHiddenTiming)(interaction.start,interaction.end)}:{}),{},{'ufo:wasPageHiddenBeforeInit':(0,_hiddenTiming.getHasHiddenTimingBeforeSetup)(),'ufo:isOpenedInBackground':(0,_hiddenTiming.isOpenedInBackground)(interaction.type)},(0,_platformFeatureFlags.fg)('platform_ufo_is_tab_throttled')?{'ufo:isTabThrottled':(0,_hiddenTiming.isTabThrottled)(start,end)}:{}),(0,_platformFeatureFlags.fg)('ufo_detect_aborting_interaction_during_ssr')?{'ufo:hasAbortingInteractionDuringSSR':(0,_vcObserverNew.getHasAbortingEventDuringSSR)()}:{}),(0,_getBrowserMetadata.getBrowserMetadataToLegacyFormat)()),batteryInfo),getSSRProperties(type)),getAssetsMetrics(interaction,pageLoadInteractionMetrics===null||pageLoadInteractionMetrics===void 0?void 0:pageLoadInteractionMetrics.SSRDoneTime)),getPPSMetrics(interaction)),paintMetrics),(0,_getNavigationMetrics.getNavigationMetricsToLegacyFormat)(type)),finalVCMetrics),experimentalMetrics),(_config$additionalPay=config.additionalPayloadData)===null||_config$additionalPay===void 0?void 0:_config$additionalPay.call(config,interaction)),getTracingContextData(interaction)),getStylesheetMetrics()),getErrorCounts(interaction)),getReactHydrationStats()),{},{interactionMetrics:_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({namePrefix:config.namePrefix||'',segmentPrefix:config.segmentPrefix||'',interactionId:interactionId,pageVisibilityAtTTI:pageVisibilityAtTTI,pageVisibilityAtTTAI:pageVisibilityAtTTAI,experimental__pageVisibilityAtTTI:moreAccuratePageVisibilityAtTTI,experimental__pageVisibilityAtTTAI:moreAccuratePageVisibilityAtTTAI,// raw interaction metrics
14
+ 'event:cpu:usage':(0,_machineUtilisation.createPressureStateReport)(interaction.start,interaction.end),'event:memory:usage':(0,_machineUtilisation.createMemoryStateReport)(interaction.start,interaction.end)},criticalPayloadCount!==undefined?{'ufo:multipayload':true,'ufo:criticalPayloadCount':criticalPayloadCount}:{}),{},{'ufo:pageVisibilityHiddenTimestamp':(0,_hiddenTiming.getEarliestHiddenTiming)(interaction.start,interaction.end),'ufo:wasPageHiddenBeforeInit':(0,_hiddenTiming.getHasHiddenTimingBeforeSetup)(),'ufo:isOpenedInBackground':(0,_hiddenTiming.isOpenedInBackground)(interaction.type)},(0,_platformFeatureFlags.fg)('platform_ufo_is_tab_throttled')?{'ufo:isTabThrottled':(0,_hiddenTiming.isTabThrottled)(start,end)}:{}),(0,_platformFeatureFlags.fg)('ufo_detect_aborting_interaction_during_ssr')?{'ufo:hasAbortingInteractionDuringSSR':(0,_vcObserverNew.getHasAbortingEventDuringSSR)()}:{}),(0,_getBrowserMetadata.getBrowserMetadataToLegacyFormat)()),batteryInfo),getSSRProperties(type)),getAssetsMetrics(interaction,pageLoadInteractionMetrics===null||pageLoadInteractionMetrics===void 0?void 0:pageLoadInteractionMetrics.SSRDoneTime)),getPPSMetrics(interaction)),paintMetrics),(0,_getNavigationMetrics.getNavigationMetricsToLegacyFormat)(type)),finalVCMetrics),experimentalMetrics),(_config$additionalPay=config.additionalPayloadData)===null||_config$additionalPay===void 0?void 0:_config$additionalPay.call(config,interaction)),getTracingContextData(interaction)),getStylesheetMetrics()),getErrorCounts(interaction)),getReactHydrationStats()),{},{interactionMetrics:_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({namePrefix:config.namePrefix||'',segmentPrefix:config.segmentPrefix||'',interactionId:interactionId,pageVisibilityAtTTI:pageVisibilityAtTTI,pageVisibilityAtTTAI:pageVisibilityAtTTAI,experimental__pageVisibilityAtTTI:moreAccuratePageVisibilityAtTTI,experimental__pageVisibilityAtTTAI:moreAccuratePageVisibilityAtTTAI,// raw interaction metrics
15
15
  rate:rate,routeName:routeName,type:type,abortReason:abortReason,featureFlags:featureFlags,previousInteractionName:previousInteractionName,isPreviousInteractionAborted:isPreviousInteractionAborted,abortedByInteractionName:abortedByInteractionName,// performance
16
16
  apdex:(0,_optimizeApdex.optimizeApdex)(interaction.apdex,(0,_getReactUfoPayloadVersion.getReactUFOPayloadVersion)(interaction.type)),end:Math.round(end)},interaction.end3p?{end3p:Math.round(interaction.end3p)}:{}),{},{start:Math.round(start),segments:(0,_getReactUfoPayloadVersion.getReactUFOPayloadVersion)(interaction.type)==='2.0.0'?segmentTree:(0,_utils.getOldSegmentsLabelStack)(segments,interaction.type),marks:(0,_optimizeMarks.optimizeMarks)(interaction.marks,(0,_getReactUfoPayloadVersion.getReactUFOPayloadVersion)(interaction.type)),customData:optimizeCustomData(interaction),reactProfilerTimings:(0,_optimizeReactProfilerTimings.optimizeReactProfilerTimings)(interaction.reactProfilerTimings,start,(0,_getReactUfoPayloadVersion.getReactUFOPayloadVersion)(interaction.type)),minorInteractions:interaction.minorInteractions},responsiveness?{responsiveness:responsiveness}:{}),labelStack),pageLoadInteractionMetrics),getDetailedInteractionMetrics(resourceTimings)),getPageLoadDetailedInteractionMetrics()),getBm3TrackerTimings(interaction)),{},{'metric:ttai':experimental?regularTTAI||expTTAI:undefined,'metric:experimental:ttai':expTTAI},unknownElementName?{unknownElementName:unknownElementName}:{}),unknownElementHierarchy?{unknownElementHierarchy:unknownElementHierarchy}:{}),'ufo:payloadTime':(0,_roundNumber.roundEpsilon)(performance.now()-interactionPayloadStart)})}};if(experimental){regularTTAI=undefined;expTTAI=undefined;}if((0,_platformFeatureFlags.fg)('platform_ufo_enable_vc_raw_data')){size=(0,_getPayloadSize.default)(payload.attributes.properties);vcRev=payload.attributes.properties['ufo:vc:rev'];rawData=vcRev.find(function(item){return item.revision==='raw-handler';});if(rawData){rawDataSize=(0,_getPayloadSize.default)(rawData);payload.attributes.properties['ufo:vc:raw:size']=rawDataSize;if(size>MAX_PAYLOAD_SIZE&&Array.isArray(vcRev)&&vcRev.length>0){payload.attributes.properties['ufo:vc:rev']=vcRev.filter(function(item){return item.revision!=='raw-handler';});payload.attributes.properties['ufo:vc:raw:removed']=true;}}payload.attributes.properties['event:sizeInKb']=(0,_getPayloadSize.default)(payload.attributes.properties);}else{payload.attributes.properties['event:sizeInKb']=(0,_getPayloadSize.default)(payload.attributes.properties);}// in order of importance, first one being least important
17
17
  // we can add more fields as necessary
@@ -17,7 +17,7 @@ var _api = require("@opentelemetry/api");
17
17
  * and we need to get it because we need to call a function that's not available in the OTel API:
18
18
  * `setActive`. The OTel JS API design doesn't allow us to manually set the active context
19
19
  * despite the spec allowing for the capability. Sigh.
20
- *
20
+ *
21
21
  * I imagine this situation might not be permanent if we can move to a system were we can rely
22
22
  * solely on the API, but for the purposes of the first change being React UFO API compatible,
23
23
  * we'll need to do this.
@@ -31,7 +31,7 @@ function getContextManager() {
31
31
  return contextManager;
32
32
  }
33
33
 
34
- /**
34
+ /**
35
35
  * The below is shamelessly borrowed from StackContextManager from @opentelemetry/sdk-trace-web
36
36
  * Using this rather than importing the entire package because this is all we need for now
37
37
  */
@@ -165,9 +165,9 @@ var UFOContextManager = exports.UFOContextManager = /*#__PURE__*/function () {
165
165
  * This function is an extension of the OTel spec, in order to facilitate the current API of React UFO trace context handling.
166
166
  * It doesn't keep track of any previously set active contexts, because it's assumed (for now) that only one trace context
167
167
  * will ever exist at a time.
168
- * The next step in the work to improve tracing in the FE will likely remove this function as we need to track the
168
+ * The next step in the work to improve tracing in the FE will likely remove this function as we need to track the
169
169
  * hierarchy of contexts (likely using the `with()` function above).
170
- * @param context The context to be made the globally active one
170
+ * @param context The context to be made the globally active one
171
171
  */
172
172
  }, {
173
173
  key: "setActive",
@@ -57,5 +57,4 @@ function UFOIgnoreHolds(_ref) {
57
57
  return /*#__PURE__*/_react.default.createElement(_interactionContext.default.Provider, {
58
58
  value: ignoredInteractionContext
59
59
  }, kids);
60
- }
61
- UFOIgnoreHolds.displayName = 'UFOIgnoreHolds';
60
+ }
@@ -153,10 +153,19 @@ function init(analyticsWebClientAsync, config) {
153
153
  return;
154
154
  }
155
155
 
156
+ // Always set config first so isUFOEnabled() can check config.enabled
157
+ (0, _config.setUFOConfig)(config);
158
+
159
+ // If UFO is disabled via config, skip all initialization
160
+ // This is gated behind platform_ufo_enable_killswitch_config feature flag
161
+ if (!(0, _config.isUFOEnabled)()) {
162
+ initialized = true;
163
+ return;
164
+ }
165
+
156
166
  // Initialize pressure observer for CPU usage monitoring
157
167
  (0, _machineUtilisation.initialisePressureObserver)();
158
168
  (0, _machineUtilisation.initialiseMemoryObserver)();
159
- (0, _config.setUFOConfig)(config);
160
169
  if ((0, _platformFeatureFlags.fg)('platform_ufo_enable_otel_context_manager')) {
161
170
  // Configure global OTel context manager
162
171
  var contextManager = new _contextManager.UFOContextManager();
@@ -8,6 +8,7 @@ Object.defineProperty(exports, "__esModule", {
8
8
  exports.default = UFOLoadHold;
9
9
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
10
  var _react = _interopRequireWildcard(require("react"));
11
+ var _config = require("../config");
11
12
  var _interactionContext = _interopRequireDefault(require("../interaction-context"));
12
13
  var _interactionIdContext = _interopRequireWildcard(require("../interaction-id-context"));
13
14
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
@@ -85,18 +86,25 @@ function UFOLoadHold(_ref) {
85
86
  hold = _ref$hold === void 0 ? true : _ref$hold,
86
87
  _ref$experimental = _ref.experimental,
87
88
  experimental = _ref$experimental === void 0 ? false : _ref$experimental;
89
+ // Check if UFO is enabled (gated behind platform_ufo_enable_killswitch_config feature flag)
90
+ // Note: isUFOEnabled() returns a stable value based on config, so it's safe to call before hooks
91
+ var ufoEnabled = (0, _config.isUFOEnabled)();
88
92
  var currentInteractionId = useInteractionIdValue();
89
93
 
90
94
  // react-18: useId instead
91
95
  var context = (0, _react.useContext)(_interactionContext.default);
92
96
  useLayoutEffectSAFE(function () {
97
+ // Skip hold registration if UFO is disabled
98
+ if (!ufoEnabled) {
99
+ return;
100
+ }
93
101
  if (hold && context != null) {
94
102
  if (experimental && context.holdExperimental) {
95
103
  return context.holdExperimental(name);
96
104
  }
97
105
  return context.hold(name);
98
106
  }
99
- }, [hold, context, name, currentInteractionId]);
107
+ }, [hold, context, name, currentInteractionId, ufoEnabled]);
100
108
 
101
109
  // react-18: can return children directly
102
110
  return children != null ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, children) : null;
@@ -36,6 +36,10 @@ function UFOSegment(_ref) {
36
36
  mode = _ref$mode === void 0 ? 'single' : _ref$mode,
37
37
  _ref$type = _ref.type,
38
38
  type = _ref$type === void 0 ? 'first-party' : _ref$type;
39
+ // If UFO is disabled, render children without any tracking overhead
40
+ // This is gated behind platform_ufo_enable_killswitch_config feature flag
41
+ // Note: isUFOEnabled() returns a stable value based on config, so it's safe to call before hooks
42
+ var ufoEnabled = (0, _config.isUFOEnabled)();
39
43
  var parentContext = (0, _react.useContext)(_interactionContext.default);
40
44
  var segmentIdMap = (0, _react.useMemo)(function () {
41
45
  if (!(parentContext !== null && parentContext !== void 0 && parentContext.segmentIdMap)) {
@@ -279,6 +283,11 @@ function UFOSegment(_ref) {
279
283
  return l.name;
280
284
  }).join('/');
281
285
  }, [labelStack]);
286
+
287
+ // If UFO is disabled, just render children without tracking overhead
288
+ if (!ufoEnabled) {
289
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, children);
290
+ }
282
291
  var ufoSegment = /*#__PURE__*/_react.default.createElement(_interactionContext.default.Provider, {
283
292
  value: interactionContext
284
293
  }, /*#__PURE__*/_react.default.createElement(_react.Profiler, {
@@ -292,5 +301,4 @@ function UFOSegment(_ref) {
292
301
  }, ufoSegment);
293
302
  }
294
303
  return ufoSegment;
295
- }
296
- UFOSegment.displayName = 'UFOSegment';
304
+ }
@@ -23,5 +23,4 @@ function UFOThirdPartySegment(props) {
23
23
  ignore: (0, _platformFeatureFlags.fg)('platform_ufo_exclude_3p_elements_from_ttai'),
24
24
  reason: "third-party-element"
25
25
  }, children));
26
- }
27
- UFOThirdPartySegment.displayName = 'UFOThirdPartySegment';
26
+ }
@@ -16,6 +16,10 @@ var _routeNameContext = _interopRequireDefault(require("../../route-name-context
16
16
 
17
17
  function traceUFOInteraction(name, interactionType, startTime) {
18
18
  var _getMinorInteractions;
19
+ // Skip if UFO is disabled (gated behind platform_ufo_enable_killswitch_config)
20
+ if (!(0, _config.isUFOEnabled)()) {
21
+ return;
22
+ }
19
23
  var rate = (0, _config.getInteractionRate)(name, interactionType);
20
24
  var pressInteractionsList = (0, _config.getDoNotAbortActivePressInteraction)();
21
25
  var minorInteractions = (pressInteractionsList !== null && pressInteractionsList !== void 0 ? pressInteractionsList : []).concat((_getMinorInteractions = (0, _config.getMinorInteractions)()) !== null && _getMinorInteractions !== void 0 ? _getMinorInteractions : []);
@@ -18,6 +18,10 @@ var _routeNameContext = _interopRequireDefault(require("../route-name-context"))
18
18
  var AWAITING_PAGELOAD_NAME = 'awaiting_pageload_name';
19
19
  function traceUFOPageLoad(ufoName) {
20
20
  var routeName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ufoName;
21
+ // Skip if UFO is disabled (gated behind platform_ufo_enable_killswitch_config)
22
+ if (!(0, _config.isUFOEnabled)()) {
23
+ return;
24
+ }
21
25
  var activeInteraction = (0, _interactionMetrics.getActiveInteraction)();
22
26
  if (activeInteraction && !ufoName) {
23
27
  return;
@@ -45,6 +49,10 @@ function traceUFOPageLoad(ufoName) {
45
49
  var _default = exports.default = traceUFOPageLoad;
46
50
  function updatePageloadName(ufoName) {
47
51
  var routeName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ufoName;
52
+ // Skip if UFO is disabled (gated behind platform_ufo_enable_killswitch_config)
53
+ if (!(0, _config.isUFOEnabled)()) {
54
+ return;
55
+ }
48
56
  var interaction = (0, _interactionMetrics.getActiveInteraction)();
49
57
  if (!interaction || interaction.type !== 'page_load' && interaction.type !== 'transition') {
50
58
  return;
@@ -21,6 +21,10 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
21
21
 
22
22
  function traceUFOTransition(ufoName) {
23
23
  var routeName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ufoName;
24
+ // Skip if UFO is disabled (gated behind platform_ufo_enable_killswitch_config)
25
+ if (!(0, _config.isUFOEnabled)()) {
26
+ return;
27
+ }
24
28
  var pressInteractionsList = (0, _config.getDoNotAbortActivePressInteractionOnTransition)();
25
29
  var interaction = (0, _interactionMetrics.getActiveInteraction)();
26
30
  if (pressInteractionsList && interaction) {
@@ -33,6 +33,25 @@ export function setUFOConfig(newConfig) {
33
33
  export function getConfig() {
34
34
  return config;
35
35
  }
36
+
37
+ /**
38
+ * Check if UFO is enabled based on the config.enabled field.
39
+ *
40
+ * This function is gated behind the platform_ufo_enable_killswitch_config feature flag.
41
+ * When the feature flag is disabled, UFO is always considered enabled (default behavior).
42
+ * When the feature flag is enabled, the config.enabled field is respected.
43
+ *
44
+ * @returns true if UFO is enabled, false if disabled
45
+ */
46
+ export function isUFOEnabled() {
47
+ var _config;
48
+ // Only respect the config.enabled field when the killswitch feature flag is enabled
49
+ if (!fg('platform_ufo_enable_killswitch_config')) {
50
+ return true;
51
+ }
52
+ // Default to enabled if config is not set or enabled is not explicitly false
53
+ return ((_config = config) === null || _config === void 0 ? void 0 : _config.enabled) !== false;
54
+ }
36
55
  const isValidConfigArray = array => {
37
56
  return Array.isArray(array) && array.length > 0;
38
57
  };
@@ -73,8 +92,8 @@ export function getReactHydrationStats() {
73
92
  return undefined;
74
93
  }
75
94
  try {
76
- var _config, _config$getReactHydra;
77
- const stats = (_config = config) === null || _config === void 0 ? void 0 : (_config$getReactHydra = _config.getReactHydrationStats) === null || _config$getReactHydra === void 0 ? void 0 : _config$getReactHydra.call(_config);
95
+ var _config2, _config2$getReactHydr;
96
+ const stats = (_config2 = config) === null || _config2 === void 0 ? void 0 : (_config2$getReactHydr = _config2.getReactHydrationStats) === null || _config2$getReactHydr === void 0 ? void 0 : _config2$getReactHydr.call(_config2);
78
97
  return stats !== null && stats !== void 0 ? stats : undefined;
79
98
  } catch (e) {
80
99
  // eslint-disable-next-line no-console
@@ -11,7 +11,7 @@ const getDetailedInteractionMetrics=resourceTimings=>{if(experimental||window.__
11
11
  if(shouldInclude3pHolds){var _interaction$hold3pIn;return{...basePayload,hold3pActive:interaction.hold3pActive?[...interaction.hold3pActive.values()]:[],hold3pInfo:optimizeHoldInfo((_interaction$hold3pIn=interaction.hold3pInfo)!==null&&_interaction$hold3pIn!==void 0?_interaction$hold3pIn:[],start,getReactUFOPayloadVersion(interaction.type))};}return basePayload;};// Page load & detailed payload
12
12
  const getPageLoadDetailedInteractionMetrics=()=>{var _config$ssr2,_config$ssr2$getSSRTi;if(!isPageLoad||!isDetailedPayload){return{};}const initialPageLoadExtraTimings=objectToArray(initialPageLoadExtraTiming.getTimings());const config=getConfig();const defaultSSRTimings=objectToArray(ssr.getSSRTimings());const ssrTimingsFromConfig=config===null||config===void 0?void 0:(_config$ssr2=config.ssr)===null||_config$ssr2===void 0?void 0:(_config$ssr2$getSSRTi=_config$ssr2.getSSRTimings)===null||_config$ssr2$getSSRTi===void 0?void 0:_config$ssr2$getSSRTi.call(_config$ssr2);return{initialPageLoadExtraTimings,SSRTimings:ssrTimingsFromConfig?[...ssrTimingsFromConfig,...defaultSSRTimings]:defaultSSRTimings};};if(experimental){expTTAI=getTTAI(interaction);}else{regularTTAI=getTTAI(interaction);}const newUFOName=sanitizeUfoName(ufoName);const resourceTimings=getResourceTimings(start,end);const[finalVCMetrics,experimentalMetrics,paintMetrics,batteryInfo]=await Promise.all([vcMetrics||(await getVCMetrics(interaction)),experimental?getExperimentalVCMetrics(interaction):Promise.resolve(undefined),getPaintMetricsToLegacyFormat(type,end),getBatteryInfoToLegacyFormat()]);if(!experimental){addPerformanceMeasures(interaction.start,[...((finalVCMetrics===null||finalVCMetrics===void 0?void 0:finalVCMetrics['ufo:vc:rev'])||[])]);}const getReactHydrationStats=()=>{if(!hydration){return{};}return{hydration};};const payload={actionSubject:'experience',action:'measured',eventType:'operational',source:'measured',tags:['observability'],attributes:{properties:{// basic
13
13
  'event:hostname':((_window$location=window.location)===null||_window$location===void 0?void 0:_window$location.hostname)||'unknown','event:product':config.product,'event:population':config.population,'event:schema':'1.0.0','event:sizeInKb':0,'event:source':{name:'react-ufo/web',version:getReactUFOPayloadVersion(interaction.type)},'event:region':config.region||'unknown','experience:key':experimental?'custom.experimental-interaction-metrics':'custom.interaction-metrics','experience:name':newUFOName,// Include CPU usage monitoring data
14
- 'event:cpu:usage':createPressureStateReport(interaction.start,interaction.end),'event:memory:usage':createMemoryStateReport(interaction.start,interaction.end),...(criticalPayloadCount!==undefined?{'ufo:multipayload':true,'ufo:criticalPayloadCount':criticalPayloadCount}:{}),...(fg('platform_ufo_browser_backgrounded_abort_timestamp')?{'ufo:pageVisibilityHiddenTimestamp':getEarliestHiddenTiming(interaction.start,interaction.end)}:{}),'ufo:wasPageHiddenBeforeInit':getHasHiddenTimingBeforeSetup(),'ufo:isOpenedInBackground':isOpenedInBackground(interaction.type),...(fg('platform_ufo_is_tab_throttled')?{'ufo:isTabThrottled':isTabThrottled(start,end)}:{}),...(fg('ufo_detect_aborting_interaction_during_ssr')?{'ufo:hasAbortingInteractionDuringSSR':getHasAbortingEventDuringSSR()}:{}),// root
14
+ 'event:cpu:usage':createPressureStateReport(interaction.start,interaction.end),'event:memory:usage':createMemoryStateReport(interaction.start,interaction.end),...(criticalPayloadCount!==undefined?{'ufo:multipayload':true,'ufo:criticalPayloadCount':criticalPayloadCount}:{}),'ufo:pageVisibilityHiddenTimestamp':getEarliestHiddenTiming(interaction.start,interaction.end),'ufo:wasPageHiddenBeforeInit':getHasHiddenTimingBeforeSetup(),'ufo:isOpenedInBackground':isOpenedInBackground(interaction.type),...(fg('platform_ufo_is_tab_throttled')?{'ufo:isTabThrottled':isTabThrottled(start,end)}:{}),...(fg('ufo_detect_aborting_interaction_during_ssr')?{'ufo:hasAbortingInteractionDuringSSR':getHasAbortingEventDuringSSR()}:{}),// root
15
15
  ...getBrowserMetadataToLegacyFormat(),...batteryInfo,...getSSRProperties(type),...getAssetsMetrics(interaction,pageLoadInteractionMetrics===null||pageLoadInteractionMetrics===void 0?void 0:pageLoadInteractionMetrics.SSRDoneTime),...getPPSMetrics(interaction),...paintMetrics,...getNavigationMetricsToLegacyFormat(type),...finalVCMetrics,...experimentalMetrics,...((_config$additionalPay=config.additionalPayloadData)===null||_config$additionalPay===void 0?void 0:_config$additionalPay.call(config,interaction)),...getTracingContextData(interaction),...getStylesheetMetrics(),...getErrorCounts(interaction),...getReactHydrationStats(),interactionMetrics:{namePrefix:config.namePrefix||'',segmentPrefix:config.segmentPrefix||'',interactionId,pageVisibilityAtTTI,pageVisibilityAtTTAI,experimental__pageVisibilityAtTTI:moreAccuratePageVisibilityAtTTI,experimental__pageVisibilityAtTTAI:moreAccuratePageVisibilityAtTTAI,// raw interaction metrics
16
16
  rate,routeName,type,abortReason,featureFlags,previousInteractionName,isPreviousInteractionAborted,abortedByInteractionName,// performance
17
17
  apdex:optimizeApdex(interaction.apdex,getReactUFOPayloadVersion(interaction.type)),end:Math.round(end),...(interaction.end3p?{end3p:Math.round(interaction.end3p)}:{}),start:Math.round(start),segments:getReactUFOPayloadVersion(interaction.type)==='2.0.0'?segmentTree:getOldSegmentsLabelStack(segments,interaction.type),marks:optimizeMarks(interaction.marks,getReactUFOPayloadVersion(interaction.type)),customData:optimizeCustomData(interaction),reactProfilerTimings:optimizeReactProfilerTimings(interaction.reactProfilerTimings,start,getReactUFOPayloadVersion(interaction.type)),minorInteractions:interaction.minorInteractions,...(responsiveness?{responsiveness}:{}),...labelStack,...pageLoadInteractionMetrics,...getDetailedInteractionMetrics(resourceTimings),...getPageLoadDetailedInteractionMetrics(),...getBm3TrackerTimings(interaction),'metric:ttai':experimental?regularTTAI||expTTAI:undefined,'metric:experimental:ttai':expTTAI,...(unknownElementName?{unknownElementName}:{}),...(unknownElementHierarchy?{unknownElementHierarchy}:{})},'ufo:payloadTime':roundEpsilon(performance.now()-interactionPayloadStart)}}};if(experimental){regularTTAI=undefined;expTTAI=undefined;}if(fg('platform_ufo_enable_vc_raw_data')){const size=getPayloadSize(payload.attributes.properties);const vcRev=payload.attributes.properties['ufo:vc:rev'];const rawData=vcRev.find(item=>item.revision==='raw-handler');if(rawData){const rawDataSize=getPayloadSize(rawData);payload.attributes.properties['ufo:vc:raw:size']=rawDataSize;if(size>MAX_PAYLOAD_SIZE&&Array.isArray(vcRev)&&vcRev.length>0){payload.attributes.properties['ufo:vc:rev']=vcRev.filter(item=>item.revision!=='raw-handler');payload.attributes.properties['ufo:vc:raw:removed']=true;}}payload.attributes.properties['event:sizeInKb']=getPayloadSize(payload.attributes.properties);}else{payload.attributes.properties['event:sizeInKb']=getPayloadSize(payload.attributes.properties);}// in order of importance, first one being least important
@@ -7,7 +7,7 @@ import { ROOT_CONTEXT } from '@opentelemetry/api';
7
7
  * and we need to get it because we need to call a function that's not available in the OTel API:
8
8
  * `setActive`. The OTel JS API design doesn't allow us to manually set the active context
9
9
  * despite the spec allowing for the capability. Sigh.
10
- *
10
+ *
11
11
  * I imagine this situation might not be permanent if we can move to a system were we can rely
12
12
  * solely on the API, but for the purposes of the first change being React UFO API compatible,
13
13
  * we'll need to do this.
@@ -21,7 +21,7 @@ export function getContextManager() {
21
21
  return contextManager;
22
22
  }
23
23
 
24
- /**
24
+ /**
25
25
  * The below is shamelessly borrowed from StackContextManager from @opentelemetry/sdk-trace-web
26
26
  * Using this rather than importing the entire package because this is all we need for now
27
27
  */
@@ -130,9 +130,9 @@ export class UFOContextManager {
130
130
  * This function is an extension of the OTel spec, in order to facilitate the current API of React UFO trace context handling.
131
131
  * It doesn't keep track of any previously set active contexts, because it's assumed (for now) that only one trace context
132
132
  * will ever exist at a time.
133
- * The next step in the work to improve tracing in the FE will likely remove this function as we need to track the
133
+ * The next step in the work to improve tracing in the FE will likely remove this function as we need to track the
134
134
  * hierarchy of contexts (likely using the `with()` function above).
135
- * @param context The context to be made the globally active one
135
+ * @param context The context to be made the globally active one
136
136
  */
137
137
  setActive(context) {
138
138
  if (this._enabled) {
@@ -46,5 +46,4 @@ export default function UFOIgnoreHolds({
46
46
  return /*#__PURE__*/React.createElement(InteractionContext.Provider, {
47
47
  value: ignoredInteractionContext
48
48
  }, kids);
49
- }
50
- UFOIgnoreHolds.displayName = 'UFOIgnoreHolds';
49
+ }
@@ -1,7 +1,7 @@
1
1
  import { context } from '@opentelemetry/api';
2
2
  import { fg } from '@atlaskit/platform-feature-flags';
3
3
  import { startLighthouseObserver } from '../additional-payload';
4
- import { setUFOConfig } from '../config';
4
+ import { isUFOEnabled, setUFOConfig } from '../config';
5
5
  import { experimentalVC, sinkExperimentalHandler } from '../create-experimental-interaction-metrics-payload';
6
6
  import { sinkExtraSearchPageInteractionHandler } from '../create-extra-search-page-interaction-payload';
7
7
  import { setContextManager, UFOContextManager } from '../experience-trace-id-context/context-manager';
@@ -129,10 +129,19 @@ export function init(analyticsWebClientAsync, config) {
129
129
  return;
130
130
  }
131
131
 
132
+ // Always set config first so isUFOEnabled() can check config.enabled
133
+ setUFOConfig(config);
134
+
135
+ // If UFO is disabled via config, skip all initialization
136
+ // This is gated behind platform_ufo_enable_killswitch_config feature flag
137
+ if (!isUFOEnabled()) {
138
+ initialized = true;
139
+ return;
140
+ }
141
+
132
142
  // Initialize pressure observer for CPU usage monitoring
133
143
  initialisePressureObserver();
134
144
  initialiseMemoryObserver();
135
- setUFOConfig(config);
136
145
  if (fg('platform_ufo_enable_otel_context_manager')) {
137
146
  // Configure global OTel context manager
138
147
  const contextManager = new UFOContextManager();
@@ -1,4 +1,5 @@
1
1
  import React, { useContext, useEffect, useLayoutEffect, useState } from 'react';
2
+ import { isUFOEnabled } from '../config';
2
3
  import UFOInteractionContext from '../interaction-context';
3
4
  import UFOInteractionIDContext, { subscribeToInteractionIdChanges } from '../interaction-id-context';
4
5
  const useLayoutEffectSAFE = typeof window === 'undefined' ? useEffect : useLayoutEffect;
@@ -71,18 +72,25 @@ export default function UFOLoadHold({
71
72
  hold = true,
72
73
  experimental = false
73
74
  }) {
75
+ // Check if UFO is enabled (gated behind platform_ufo_enable_killswitch_config feature flag)
76
+ // Note: isUFOEnabled() returns a stable value based on config, so it's safe to call before hooks
77
+ const ufoEnabled = isUFOEnabled();
74
78
  const currentInteractionId = useInteractionIdValue();
75
79
 
76
80
  // react-18: useId instead
77
81
  const context = useContext(UFOInteractionContext);
78
82
  useLayoutEffectSAFE(() => {
83
+ // Skip hold registration if UFO is disabled
84
+ if (!ufoEnabled) {
85
+ return;
86
+ }
79
87
  if (hold && context != null) {
80
88
  if (experimental && context.holdExperimental) {
81
89
  return context.holdExperimental(name);
82
90
  }
83
91
  return context.hold(name);
84
92
  }
85
- }, [hold, context, name, currentInteractionId]);
93
+ }, [hold, context, name, currentInteractionId, ufoEnabled]);
86
94
 
87
95
  // react-18: can return children directly
88
96
  return children != null ? /*#__PURE__*/React.createElement(React.Fragment, null, children) : null;
@@ -4,7 +4,7 @@ import { unstable_NormalPriority as NormalPriority, unstable_scheduleCallback as
4
4
  import { v4 as createUUID } from 'uuid';
5
5
  import { fg } from '@atlaskit/platform-feature-flags';
6
6
  import coinflip from '../coinflip';
7
- import { getConfig, getDoNotAbortActivePressInteraction, getInteractionRate, getMinorInteractions } from '../config';
7
+ import { getConfig, getDoNotAbortActivePressInteraction, getInteractionRate, getMinorInteractions, isUFOEnabled } from '../config';
8
8
  import { getActiveTrace, setInteractionActiveTrace } from '../experience-trace-id-context';
9
9
  import UFOInteractionContext from '../interaction-context';
10
10
  import UFOInteractionIDContext from '../interaction-id-context';
@@ -23,6 +23,10 @@ export default function UFOSegment({
23
23
  mode = 'single',
24
24
  type = 'first-party'
25
25
  }) {
26
+ // If UFO is disabled, render children without any tracking overhead
27
+ // This is gated behind platform_ufo_enable_killswitch_config feature flag
28
+ // Note: isUFOEnabled() returns a stable value based on config, so it's safe to call before hooks
29
+ const ufoEnabled = isUFOEnabled();
26
30
  const parentContext = useContext(UFOInteractionContext);
27
31
  const segmentIdMap = useMemo(() => {
28
32
  if (!(parentContext !== null && parentContext !== void 0 && parentContext.segmentIdMap)) {
@@ -257,6 +261,11 @@ export default function UFOSegment({
257
261
  };
258
262
  }, [interactionId, parentContext, interactionContext, labelStack]);
259
263
  const reactProfilerId = useMemo(() => labelStack.map(l => l.name).join('/'), [labelStack]);
264
+
265
+ // If UFO is disabled, just render children without tracking overhead
266
+ if (!ufoEnabled) {
267
+ return /*#__PURE__*/React.createElement(React.Fragment, null, children);
268
+ }
260
269
  const ufoSegment = /*#__PURE__*/React.createElement(UFOInteractionContext.Provider, {
261
270
  value: interactionContext
262
271
  }, /*#__PURE__*/React.createElement(Profiler, {
@@ -270,5 +279,4 @@ export default function UFOSegment({
270
279
  }, ufoSegment);
271
280
  }
272
281
  return ufoSegment;
273
- }
274
- UFOSegment.displayName = 'UFOSegment';
282
+ }
@@ -16,5 +16,4 @@ export function UFOThirdPartySegment(props) {
16
16
  ignore: fg('platform_ufo_exclude_3p_elements_from_ttai'),
17
17
  reason: "third-party-element"
18
18
  }, children));
19
- }
20
- UFOThirdPartySegment.displayName = 'UFOThirdPartySegment';
19
+ }