@atlaskit/react-ufo 3.13.28 → 3.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/cjs/create-payload/index.js +3 -1
- package/dist/cjs/ignore-holds/index.js +62 -0
- package/dist/cjs/interaction-ignore/ufo-interaction-ignore.js +7 -49
- package/dist/cjs/interaction-metrics-init/index.js +3 -0
- package/dist/cjs/machine-utilisation/index.js +82 -9
- package/dist/cjs/segment/index.js +7 -0
- package/dist/cjs/segment/segment.js +3 -1
- package/dist/cjs/segment/third-party-segment.js +25 -0
- package/dist/cjs/vc/vc-observer-new/metric-calculator/fy25_03/index.js +11 -2
- package/dist/cjs/vc/vc-observer-new/viewport-observer/index.js +30 -6
- package/dist/cjs/vc/vc-observer-new/viewport-observer/utils/get-component-name-and-child-props.js +85 -0
- package/dist/es2019/create-payload/index.js +4 -1
- package/dist/es2019/ignore-holds/index.js +51 -0
- package/dist/es2019/interaction-ignore/ufo-interaction-ignore.js +7 -45
- package/dist/es2019/interaction-metrics-init/index.js +4 -1
- package/dist/es2019/machine-utilisation/index.js +72 -5
- package/dist/es2019/segment/index.js +2 -1
- package/dist/es2019/segment/segment.js +2 -1
- package/dist/es2019/segment/third-party-segment.js +18 -0
- package/dist/es2019/vc/vc-observer-new/metric-calculator/fy25_03/index.js +11 -2
- package/dist/es2019/vc/vc-observer-new/viewport-observer/index.js +32 -6
- package/dist/es2019/vc/vc-observer-new/viewport-observer/utils/get-component-name-and-child-props.js +71 -0
- package/dist/esm/create-payload/index.js +4 -2
- package/dist/esm/ignore-holds/index.js +53 -0
- package/dist/esm/interaction-ignore/ufo-interaction-ignore.js +7 -47
- package/dist/esm/interaction-metrics-init/index.js +4 -1
- package/dist/esm/machine-utilisation/index.js +76 -8
- package/dist/esm/segment/index.js +2 -1
- package/dist/esm/segment/segment.js +3 -1
- package/dist/esm/segment/third-party-segment.js +18 -0
- package/dist/esm/vc/vc-observer-new/metric-calculator/fy25_03/index.js +11 -2
- package/dist/esm/vc/vc-observer-new/viewport-observer/index.js +30 -6
- package/dist/esm/vc/vc-observer-new/viewport-observer/utils/get-component-name-and-child-props.js +76 -0
- package/dist/types/create-payload/index.d.ts +160 -0
- package/dist/types/ignore-holds/index.d.ts +31 -0
- package/dist/types/interaction-ignore/ufo-interaction-ignore.d.ts +6 -21
- package/dist/types/machine-utilisation/index.d.ts +10 -1
- package/dist/types/machine-utilisation/types.d.ts +6 -0
- package/dist/types/segment/index.d.ts +1 -0
- package/dist/types/segment/segment.d.ts +4 -2
- package/dist/types/segment/third-party-segment.d.ts +6 -0
- package/dist/types/vc/vc-observer-new/types.d.ts +1 -1
- package/dist/types/vc/vc-observer-new/viewport-observer/utils/get-component-name-and-child-props.d.ts +15 -0
- package/dist/types-ts4.5/create-payload/index.d.ts +160 -0
- package/dist/types-ts4.5/ignore-holds/index.d.ts +31 -0
- package/dist/types-ts4.5/interaction-ignore/ufo-interaction-ignore.d.ts +6 -21
- package/dist/types-ts4.5/machine-utilisation/index.d.ts +10 -1
- package/dist/types-ts4.5/machine-utilisation/types.d.ts +6 -0
- package/dist/types-ts4.5/segment/index.d.ts +1 -0
- package/dist/types-ts4.5/segment/segment.d.ts +4 -2
- package/dist/types-ts4.5/segment/third-party-segment.d.ts +6 -0
- package/dist/types-ts4.5/vc/vc-observer-new/types.d.ts +1 -1
- package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/utils/get-component-name-and-child-props.d.ts +15 -0
- package/package.json +10 -1
|
@@ -1,49 +1,11 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import UFOIgnoreHolds from '../ignore-holds';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
* Use
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* ```js
|
|
10
|
-
* <App>
|
|
11
|
-
* <Main />
|
|
12
|
-
* <Sidebar>
|
|
13
|
-
* <UFOInteractionIgnore>
|
|
14
|
-
* <InsightsButton />
|
|
15
|
-
* </UFOInteractionIgnore>
|
|
16
|
-
* </Sidebar>
|
|
17
|
-
* </App>
|
|
18
|
-
* ```
|
|
19
|
-
*
|
|
20
|
-
* Has an `ignore` prop, to allow you to use it conditionally
|
|
5
|
+
* Legacy wrapper component that delegates to `UFOIgnoreHolds`.
|
|
6
|
+
* Use `UFOIgnoreHolds` instead for new implementations.
|
|
7
|
+
* This component is maintained for backward compatibility only.
|
|
21
8
|
*/
|
|
22
|
-
export default function UFOInteractionIgnore({
|
|
23
|
-
|
|
24
|
-
ignore = true
|
|
25
|
-
}) {
|
|
26
|
-
const parentContext = useContext(InteractionContext);
|
|
27
|
-
const ignoredInteractionContext = useMemo(() => {
|
|
28
|
-
if (!parentContext) {
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
return {
|
|
32
|
-
...parentContext,
|
|
33
|
-
hold(...args) {
|
|
34
|
-
if (!ignore) {
|
|
35
|
-
return parentContext.hold(...args);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
}, [parentContext, ignore]);
|
|
40
|
-
|
|
41
|
-
// react-18: Use children directly
|
|
42
|
-
const kids = children != null ? children : null;
|
|
43
|
-
if (!ignoredInteractionContext) {
|
|
44
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, kids);
|
|
45
|
-
}
|
|
46
|
-
return /*#__PURE__*/React.createElement(InteractionContext.Provider, {
|
|
47
|
-
value: ignoredInteractionContext
|
|
48
|
-
}, kids);
|
|
9
|
+
export default function UFOInteractionIgnore(props) {
|
|
10
|
+
return /*#__PURE__*/React.createElement(UFOIgnoreHolds, props);
|
|
49
11
|
}
|
|
@@ -5,7 +5,7 @@ import { experimentalVC, sinkExperimentalHandler } from '../create-experimental-
|
|
|
5
5
|
import { setupHiddenTimingCapture } from '../hidden-timing';
|
|
6
6
|
import { postInteractionLog, sinkInteractionHandler, sinkPostInteractionLogHandler } from '../interaction-metrics';
|
|
7
7
|
import { getPerformanceObserver } from '../interactions-performance-observer';
|
|
8
|
-
import { initialisePressureObserver } from '../machine-utilisation';
|
|
8
|
+
import { initialiseMemoryObserver, initialisePressureObserver } from '../machine-utilisation';
|
|
9
9
|
import { getVCObserver } from '../vc';
|
|
10
10
|
import scheduleIdleCallback from './schedule-idle-callback';
|
|
11
11
|
let initialized = false;
|
|
@@ -77,6 +77,9 @@ export function init(analyticsWebClientAsync, config) {
|
|
|
77
77
|
if (fg('platform_ufo_report_cpu_usage')) {
|
|
78
78
|
initialisePressureObserver();
|
|
79
79
|
}
|
|
80
|
+
if (fg('platform_ufo_report_memory_usage')) {
|
|
81
|
+
initialiseMemoryObserver();
|
|
82
|
+
}
|
|
80
83
|
setUFOConfig(config);
|
|
81
84
|
if ((_config$vc = config.vc) !== null && _config$vc !== void 0 && _config$vc.enabled) {
|
|
82
85
|
var _config$experimentalI;
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
const BUFFER_MAX_LENGTH = 1000; // ensure we don't blow up this buffer
|
|
2
2
|
let pressureRecordBuffer = [];
|
|
3
3
|
let pressureObserver = null;
|
|
4
|
+
let memoryRecordBuffer = [];
|
|
5
|
+
let memoryInterval;
|
|
4
6
|
export function resetPressureRecordBuffer() {
|
|
5
7
|
pressureRecordBuffer.length = 0;
|
|
6
8
|
}
|
|
7
|
-
export function
|
|
9
|
+
export function resetMemoryRecordBuffer() {
|
|
10
|
+
memoryRecordBuffer.length = 0;
|
|
11
|
+
}
|
|
12
|
+
export function removeOldPressureBufferRecords(filter) {
|
|
8
13
|
pressureRecordBuffer = pressureRecordBuffer.filter(({
|
|
9
14
|
time
|
|
10
15
|
}) => time > filter);
|
|
11
16
|
}
|
|
17
|
+
export function removeOldMemoryBufferRecords(filter) {
|
|
18
|
+
memoryRecordBuffer = memoryRecordBuffer.filter(({
|
|
19
|
+
time
|
|
20
|
+
}) => time > filter);
|
|
21
|
+
}
|
|
12
22
|
export function createPressureStateReport(start, end) {
|
|
13
23
|
try {
|
|
14
24
|
// To differentiate between the API not available, vs no PressureRecords added
|
|
@@ -30,7 +40,7 @@ export function createPressureStateReport(start, end) {
|
|
|
30
40
|
critical: 0
|
|
31
41
|
});
|
|
32
42
|
const pressureStateTotal = Object.values(pressureStateCount).reduce((total, count) => total + count) || 1;
|
|
33
|
-
|
|
43
|
+
removeOldPressureBufferRecords(end);
|
|
34
44
|
return {
|
|
35
45
|
count: pressureStateCount,
|
|
36
46
|
percentage: {
|
|
@@ -44,23 +54,80 @@ export function createPressureStateReport(start, end) {
|
|
|
44
54
|
return null;
|
|
45
55
|
}
|
|
46
56
|
}
|
|
57
|
+
function convertBytesToMegabytes(bytes) {
|
|
58
|
+
return Math.round(Math.round(bytes / (1024 * 1024) * 100) / 100);
|
|
59
|
+
}
|
|
60
|
+
export function createMemoryStateReport(start, end) {
|
|
61
|
+
try {
|
|
62
|
+
if (!('memory' in performance)) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const accumulatedMemoryUsage = memoryRecordBuffer.reduce((acc, snapshot) => {
|
|
66
|
+
if (snapshot.time >= start && snapshot.time <= end) {
|
|
67
|
+
acc.totalJSHeapSize += snapshot.totalJSHeapSize;
|
|
68
|
+
acc.usedJSHeapSize += snapshot.usedJSHeapSize;
|
|
69
|
+
acc.snapshotCount += 1;
|
|
70
|
+
}
|
|
71
|
+
return acc;
|
|
72
|
+
}, {
|
|
73
|
+
totalJSHeapSize: 0,
|
|
74
|
+
usedJSHeapSize: 0,
|
|
75
|
+
snapshotCount: 0
|
|
76
|
+
});
|
|
77
|
+
const memoryStateReport = {
|
|
78
|
+
jsHeapSizeLimitInMB: convertBytesToMegabytes(memoryRecordBuffer[0].jsHeapSizeLimit),
|
|
79
|
+
// just use the first record, since this value always remains the same over time
|
|
80
|
+
avgTotalJSHeapSizeInMB: convertBytesToMegabytes(accumulatedMemoryUsage.totalJSHeapSize / accumulatedMemoryUsage.snapshotCount),
|
|
81
|
+
avgUsedJSHeapSizeInMB: convertBytesToMegabytes(accumulatedMemoryUsage.usedJSHeapSize / accumulatedMemoryUsage.snapshotCount)
|
|
82
|
+
};
|
|
83
|
+
removeOldMemoryBufferRecords(end);
|
|
84
|
+
return memoryStateReport;
|
|
85
|
+
} catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
47
89
|
export function initialisePressureObserver() {
|
|
48
90
|
try {
|
|
49
91
|
if ('PressureObserver' in globalThis) {
|
|
50
|
-
var _pressureObserver$obs;
|
|
51
92
|
pressureObserver = new PressureObserver(records => {
|
|
52
93
|
if (pressureRecordBuffer.length + records.length <= BUFFER_MAX_LENGTH) {
|
|
53
94
|
pressureRecordBuffer.push(...records);
|
|
54
95
|
}
|
|
55
96
|
});
|
|
56
|
-
|
|
97
|
+
pressureObserver.observe('cpu', {
|
|
57
98
|
sampleInterval: 100
|
|
58
|
-
})
|
|
99
|
+
}).catch();
|
|
59
100
|
}
|
|
60
101
|
} catch (err) {
|
|
61
102
|
/* do nothing, this is a best efforts metric */
|
|
62
103
|
}
|
|
63
104
|
}
|
|
105
|
+
export function initialiseMemoryObserver() {
|
|
106
|
+
try {
|
|
107
|
+
// only set up the interval if `performance.memory` is available in the browser
|
|
108
|
+
if ('memory' in performance) {
|
|
109
|
+
memoryInterval = setInterval(() => {
|
|
110
|
+
// another check of `performance.memory` availability to satisfy typescript
|
|
111
|
+
if ('memory' in performance) {
|
|
112
|
+
const memory = performance.memory;
|
|
113
|
+
if (memoryRecordBuffer.length <= BUFFER_MAX_LENGTH) {
|
|
114
|
+
memoryRecordBuffer.push({
|
|
115
|
+
time: performance.now(),
|
|
116
|
+
jsHeapSizeLimit: memory.jsHeapSizeLimit,
|
|
117
|
+
totalJSHeapSize: memory.totalJSHeapSize,
|
|
118
|
+
usedJSHeapSize: memory.usedJSHeapSize
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}, 100);
|
|
123
|
+
}
|
|
124
|
+
} catch {
|
|
125
|
+
/* do nothing, this is a best efforts metric */
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
export function disconnectMemoryObserver() {
|
|
129
|
+
clearInterval(memoryInterval);
|
|
130
|
+
}
|
|
64
131
|
export function disconnectPressureObserver() {
|
|
65
132
|
var _pressureObserver;
|
|
66
133
|
(_pressureObserver = pressureObserver) === null || _pressureObserver === void 0 ? void 0 : _pressureObserver.disconnect();
|
|
@@ -20,7 +20,8 @@ const AsyncSegmentHighlight = /*#__PURE__*/lazy(() => import( /* webpackChunkNam
|
|
|
20
20
|
export default function UFOSegment({
|
|
21
21
|
name: segmentName,
|
|
22
22
|
children,
|
|
23
|
-
mode = 'single'
|
|
23
|
+
mode = 'single',
|
|
24
|
+
type = 'first-party'
|
|
24
25
|
}) {
|
|
25
26
|
var _getConfig2;
|
|
26
27
|
const parentContext = useContext(UFOInteractionContext);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
4
|
+
import UFOIgnoreHolds from '../ignore-holds';
|
|
5
|
+
import UFOSegment from './segment';
|
|
6
|
+
export function UFOThirdPartySegment(props) {
|
|
7
|
+
const {
|
|
8
|
+
children,
|
|
9
|
+
...otherProps
|
|
10
|
+
} = props;
|
|
11
|
+
return /*#__PURE__*/React.createElement(UFOSegment, _extends({
|
|
12
|
+
type: "third-party"
|
|
13
|
+
}, otherProps), /*#__PURE__*/React.createElement(UFOIgnoreHolds, {
|
|
14
|
+
ignore: fg('platform_ufo_exclude_3p_elements_from_ttai'),
|
|
15
|
+
reason: "third-party-element"
|
|
16
|
+
}, children));
|
|
17
|
+
}
|
|
18
|
+
UFOThirdPartySegment.displayName = 'UFOThirdPartySegment';
|
|
@@ -3,7 +3,16 @@ import AbstractVCCalculatorBase from '../abstract-base-vc-calculator';
|
|
|
3
3
|
import isViewportEntryData from '../utils/is-viewport-entry-data';
|
|
4
4
|
const ABORTING_WINDOW_EVENT = ['wheel', 'scroll', 'keydown', 'resize'];
|
|
5
5
|
const REVISION_NO = 'fy25.03';
|
|
6
|
-
const
|
|
6
|
+
const getConsideredEntryTypes = () => {
|
|
7
|
+
const entryTypes = ['mutation:child-element', 'mutation:element', 'mutation:attribute', 'layout-shift', 'window:event'];
|
|
8
|
+
|
|
9
|
+
// If not exclude 3p elements from ttvc,
|
|
10
|
+
// including the tags into the ConsideredEntryTypes so that it won't be ignored for TTVC calculation
|
|
11
|
+
if (!fg('platform_ufo_exclude_3p_elements_from_ttvc')) {
|
|
12
|
+
entryTypes.push('mutation:third-party-element');
|
|
13
|
+
}
|
|
14
|
+
return entryTypes;
|
|
15
|
+
};
|
|
7
16
|
|
|
8
17
|
// TODO: AFO-3523
|
|
9
18
|
// Those are the attributes we have found when testing the 'fy25.03' manually.
|
|
@@ -17,7 +26,7 @@ export default class VCCalculator_FY25_03 extends AbstractVCCalculatorBase {
|
|
|
17
26
|
super(REVISION_NO);
|
|
18
27
|
}
|
|
19
28
|
isEntryIncluded(entry) {
|
|
20
|
-
if (!
|
|
29
|
+
if (!getConsideredEntryTypes().includes(entry.data.type)) {
|
|
21
30
|
return false;
|
|
22
31
|
}
|
|
23
32
|
if (entry.data.type === 'mutation:attribute') {
|
|
@@ -5,6 +5,7 @@ import { RLLPlaceholderHandlers } from '../../vc-observer/observers/rll-placehol
|
|
|
5
5
|
import { createIntersectionObserver } from './intersection-observer';
|
|
6
6
|
import createMutationObserver from './mutation-observer';
|
|
7
7
|
import createPerformanceObserver from './performance-observer';
|
|
8
|
+
import { checkThirdPartySegmentWithIgnoreReason, createMutationTypeWithIgnoredReason } from './utils/get-component-name-and-child-props';
|
|
8
9
|
function isElementVisible(element) {
|
|
9
10
|
if (!(element instanceof HTMLElement)) {
|
|
10
11
|
return true;
|
|
@@ -86,7 +87,7 @@ export default class ViewportObserver {
|
|
|
86
87
|
return this.mapVisibleNodeRects.get(n);
|
|
87
88
|
});
|
|
88
89
|
addedNodes.forEach(addedNodeRef => {
|
|
89
|
-
var _this$
|
|
90
|
+
var _this$intersectionObs4;
|
|
90
91
|
const addedNode = addedNodeRef.deref();
|
|
91
92
|
if (!addedNode) {
|
|
92
93
|
return;
|
|
@@ -108,7 +109,17 @@ export default class ViewportObserver {
|
|
|
108
109
|
(_this$intersectionObs2 = this.intersectionObserver) === null || _this$intersectionObs2 === void 0 ? void 0 : _this$intersectionObs2.watchAndTag(addedNode, 'mutation:media');
|
|
109
110
|
return;
|
|
110
111
|
}
|
|
111
|
-
|
|
112
|
+
const {
|
|
113
|
+
isWithinThirdPartySegment,
|
|
114
|
+
ignoredReason
|
|
115
|
+
} = checkThirdPartySegmentWithIgnoreReason(addedNode);
|
|
116
|
+
if (isWithinThirdPartySegment) {
|
|
117
|
+
var _this$intersectionObs3;
|
|
118
|
+
const assignedReason = createMutationTypeWithIgnoredReason(ignoredReason || 'third-party-element');
|
|
119
|
+
(_this$intersectionObs3 = this.intersectionObserver) === null || _this$intersectionObs3 === void 0 ? void 0 : _this$intersectionObs3.watchAndTag(addedNode, assignedReason);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
(_this$intersectionObs4 = this.intersectionObserver) === null || _this$intersectionObs4 === void 0 ? void 0 : _this$intersectionObs4.watchAndTag(addedNode, createElementMutationsWatcher(removedNodeRects));
|
|
112
123
|
});
|
|
113
124
|
});
|
|
114
125
|
_defineProperty(this, "handleAttributeMutation", ({
|
|
@@ -117,8 +128,8 @@ export default class ViewportObserver {
|
|
|
117
128
|
oldValue,
|
|
118
129
|
newValue
|
|
119
130
|
}) => {
|
|
120
|
-
var _this$
|
|
121
|
-
(_this$
|
|
131
|
+
var _this$intersectionObs5;
|
|
132
|
+
(_this$intersectionObs5 = this.intersectionObserver) === null || _this$intersectionObs5 === void 0 ? void 0 : _this$intersectionObs5.watchAndTag(target, ({
|
|
122
133
|
target,
|
|
123
134
|
rect
|
|
124
135
|
}) => {
|
|
@@ -157,6 +168,21 @@ export default class ViewportObserver {
|
|
|
157
168
|
}
|
|
158
169
|
};
|
|
159
170
|
}
|
|
171
|
+
const {
|
|
172
|
+
isWithinThirdPartySegment,
|
|
173
|
+
ignoredReason
|
|
174
|
+
} = checkThirdPartySegmentWithIgnoreReason(target);
|
|
175
|
+
if (isWithinThirdPartySegment) {
|
|
176
|
+
const assignedReason = createMutationTypeWithIgnoredReason(ignoredReason || 'third-party-element');
|
|
177
|
+
return {
|
|
178
|
+
type: assignedReason,
|
|
179
|
+
mutationData: {
|
|
180
|
+
attributeName,
|
|
181
|
+
oldValue,
|
|
182
|
+
newValue
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
}
|
|
160
186
|
const lastElementRect = this.mapVisibleNodeRects.get(target);
|
|
161
187
|
if (lastElementRect && sameRectSize(rect, lastElementRect)) {
|
|
162
188
|
return {
|
|
@@ -239,12 +265,12 @@ export default class ViewportObserver {
|
|
|
239
265
|
this.isStarted = true;
|
|
240
266
|
}
|
|
241
267
|
stop() {
|
|
242
|
-
var _this$mutationObserve2, _this$
|
|
268
|
+
var _this$mutationObserve2, _this$intersectionObs6, _this$performanceObse2;
|
|
243
269
|
if (!this.isStarted) {
|
|
244
270
|
return;
|
|
245
271
|
}
|
|
246
272
|
(_this$mutationObserve2 = this.mutationObserver) === null || _this$mutationObserve2 === void 0 ? void 0 : _this$mutationObserve2.disconnect();
|
|
247
|
-
(_this$
|
|
273
|
+
(_this$intersectionObs6 = this.intersectionObserver) === null || _this$intersectionObs6 === void 0 ? void 0 : _this$intersectionObs6.disconnect();
|
|
248
274
|
(_this$performanceObse2 = this.performanceObserver) === null || _this$performanceObse2 === void 0 ? void 0 : _this$performanceObse2.disconnect();
|
|
249
275
|
this.isStarted = false;
|
|
250
276
|
}
|
package/dist/es2019/vc/vc-observer-new/viewport-observer/utils/get-component-name-and-child-props.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Using the React Fiber tree to traverse up the DOM and check if a node is within a specific component
|
|
2
|
+
// and extract child component props if needed.
|
|
3
|
+
export function checkWithinComponentAndExtractChildProps(node, targetComponentName, childComponentConfig) {
|
|
4
|
+
// Get the React fiber from the DOM node
|
|
5
|
+
const key = Object.keys(node).find(key => key.startsWith('__reactFiber$') || key.startsWith('__reactInternalInstance$'));
|
|
6
|
+
if (!key) {
|
|
7
|
+
return {
|
|
8
|
+
isWithin: false
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
const fiber = node[key];
|
|
12
|
+
if (!fiber) {
|
|
13
|
+
return {
|
|
14
|
+
isWithin: false
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Traverse up the fiber tree
|
|
19
|
+
let currentFiber = fiber;
|
|
20
|
+
let childProp;
|
|
21
|
+
while (currentFiber) {
|
|
22
|
+
let componentName;
|
|
23
|
+
if (currentFiber.type) {
|
|
24
|
+
if (typeof currentFiber.type === 'function') {
|
|
25
|
+
componentName = currentFiber.type.displayName || currentFiber.type.name;
|
|
26
|
+
} else if (typeof currentFiber.type === 'object' && (currentFiber.type.displayName || currentFiber.type.name)) {
|
|
27
|
+
componentName = currentFiber.type.displayName || currentFiber.type.name;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Check if this is a child component we're looking for
|
|
32
|
+
if (childComponentConfig && componentName === childComponentConfig.componentName) {
|
|
33
|
+
const props = currentFiber.memoizedProps || currentFiber.pendingProps;
|
|
34
|
+
if (props && props[childComponentConfig.propName] !== undefined) {
|
|
35
|
+
// Overwrite with the nearest child prop (closest to the target component)
|
|
36
|
+
childProp = childComponentConfig.extractValue ? childComponentConfig.extractValue(props) : props[childComponentConfig.propName];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Check if we found the target component
|
|
41
|
+
if (componentName === targetComponentName) {
|
|
42
|
+
return {
|
|
43
|
+
isWithin: true,
|
|
44
|
+
...(childComponentConfig && {
|
|
45
|
+
childProp: childProp
|
|
46
|
+
})
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
currentFiber = currentFiber.return;
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
isWithin: false
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Check if the node is within a UFOThirdPartySegment and extract any UFOIgnoreHolds reason
|
|
57
|
+
export function checkThirdPartySegmentWithIgnoreReason(node) {
|
|
58
|
+
const result = checkWithinComponentAndExtractChildProps(node, 'UFOThirdPartySegment', {
|
|
59
|
+
componentName: 'UFOIgnoreHolds',
|
|
60
|
+
propName: 'reason'
|
|
61
|
+
});
|
|
62
|
+
return {
|
|
63
|
+
isWithinThirdPartySegment: result.isWithin,
|
|
64
|
+
ignoredReason: result.childProp
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Helper function to create mutation type from UFOIgnoreHoldsReason
|
|
69
|
+
export function createMutationTypeWithIgnoredReason(reason) {
|
|
70
|
+
return `mutation:${reason}`;
|
|
71
|
+
}
|
|
@@ -23,7 +23,7 @@ import { getGlobalErrorCount } from '../global-error-handler';
|
|
|
23
23
|
import { getPageVisibilityState } from '../hidden-timing';
|
|
24
24
|
import * as initialPageLoadExtraTiming from '../initial-page-load-extra-timing';
|
|
25
25
|
import { interactionSpans as atlaskitInteractionSpans } from '../interaction-metrics';
|
|
26
|
-
import { createPressureStateReport } from '../machine-utilisation';
|
|
26
|
+
import { createMemoryStateReport, createPressureStateReport } from '../machine-utilisation';
|
|
27
27
|
import * as resourceTiming from '../resource-timing';
|
|
28
28
|
import { filterResourceTimings } from '../resource-timing/common/utils/resource-timing-buffer';
|
|
29
29
|
import { roundEpsilon } from '../round-number';
|
|
@@ -799,7 +799,7 @@ function _createInteractionMetricsPayload() {
|
|
|
799
799
|
source: 'measured',
|
|
800
800
|
tags: ['observability'],
|
|
801
801
|
attributes: {
|
|
802
|
-
properties: _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({
|
|
802
|
+
properties: _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({
|
|
803
803
|
// basic
|
|
804
804
|
'event:hostname': ((_window$location = window.location) === null || _window$location === void 0 ? void 0 : _window$location.hostname) || 'unknown',
|
|
805
805
|
'event:product': config.product,
|
|
@@ -814,6 +814,8 @@ function _createInteractionMetricsPayload() {
|
|
|
814
814
|
'experience:name': newUFOName
|
|
815
815
|
}, fg('platform_ufo_report_cpu_usage') ? {
|
|
816
816
|
'event:cpu:usage': createPressureStateReport(interaction.start, interaction.end)
|
|
817
|
+
} : {}), fg('platform_ufo_report_memory_usage') ? {
|
|
818
|
+
'event:memory:usage': createMemoryStateReport(interaction.start, interaction.end)
|
|
817
819
|
} : {}), getBrowserMetadata()), getSSRProperties(type)), getAssetsMetrics(interaction, pageLoadInteractionMetrics === null || pageLoadInteractionMetrics === void 0 ? void 0 : pageLoadInteractionMetrics.SSRDoneTime)), getPPSMetrics(interaction)), paintMetrics), getNavigationMetrics(type)), vcMetrics), experimentalMetrics), (_config$additionalPay = config.additionalPayloadData) === null || _config$additionalPay === void 0 ? void 0 : _config$additionalPay.call(config, interaction)), getTracingContextData(interaction)), getStylesheetMetrics()), getErrorCounts(interaction)), {}, {
|
|
818
820
|
interactionMetrics: _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({
|
|
819
821
|
namePrefix: config.namePrefix || '',
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
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; }
|
|
3
|
+
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; }
|
|
4
|
+
import React, { useContext, useMemo } from 'react';
|
|
5
|
+
import InteractionContext from '@atlaskit/interaction-context';
|
|
6
|
+
/**
|
|
7
|
+
* Prevent a subtree from holding up an interaction
|
|
8
|
+
* Use this when you have a component which loads in late, but
|
|
9
|
+
* isn't considered to be a breach of SLO
|
|
10
|
+
*
|
|
11
|
+
* ```js
|
|
12
|
+
* <App>
|
|
13
|
+
* <Main />
|
|
14
|
+
* <Sidebar>
|
|
15
|
+
* <UFOIgnoreHolds>
|
|
16
|
+
* <InsightsButton />
|
|
17
|
+
* </UFOIgnoreHolds>
|
|
18
|
+
* </Sidebar>
|
|
19
|
+
* </App>
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* Has an `ignore` prop, to allow you to use it conditionally
|
|
23
|
+
* Has a `reason` prop, to specify why the hold is being ignored
|
|
24
|
+
*/
|
|
25
|
+
export default function UFOIgnoreHolds(_ref) {
|
|
26
|
+
var children = _ref.children,
|
|
27
|
+
_ref$ignore = _ref.ignore,
|
|
28
|
+
ignore = _ref$ignore === void 0 ? true : _ref$ignore,
|
|
29
|
+
reason = _ref.reason;
|
|
30
|
+
var parentContext = useContext(InteractionContext);
|
|
31
|
+
var ignoredInteractionContext = useMemo(function () {
|
|
32
|
+
if (!parentContext) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return _objectSpread(_objectSpread({}, parentContext), {}, {
|
|
36
|
+
hold: function hold() {
|
|
37
|
+
if (!ignore) {
|
|
38
|
+
return parentContext.hold.apply(parentContext, arguments);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}, [parentContext, ignore]);
|
|
43
|
+
|
|
44
|
+
// react-18: Use children directly
|
|
45
|
+
var kids = children != null ? children : null;
|
|
46
|
+
if (!ignoredInteractionContext) {
|
|
47
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, kids);
|
|
48
|
+
}
|
|
49
|
+
return /*#__PURE__*/React.createElement(InteractionContext.Provider, {
|
|
50
|
+
value: ignoredInteractionContext
|
|
51
|
+
}, kids);
|
|
52
|
+
}
|
|
53
|
+
UFOIgnoreHolds.displayName = 'UFOIgnoreHolds';
|
|
@@ -1,51 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
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; }
|
|
4
|
-
import React, { useContext, useMemo } from 'react';
|
|
5
|
-
import InteractionContext from '@atlaskit/interaction-context';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import UFOIgnoreHolds from '../ignore-holds';
|
|
6
3
|
|
|
7
4
|
/**
|
|
8
|
-
*
|
|
9
|
-
* Use
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* ```js
|
|
13
|
-
* <App>
|
|
14
|
-
* <Main />
|
|
15
|
-
* <Sidebar>
|
|
16
|
-
* <UFOInteractionIgnore>
|
|
17
|
-
* <InsightsButton />
|
|
18
|
-
* </UFOInteractionIgnore>
|
|
19
|
-
* </Sidebar>
|
|
20
|
-
* </App>
|
|
21
|
-
* ```
|
|
22
|
-
*
|
|
23
|
-
* Has an `ignore` prop, to allow you to use it conditionally
|
|
5
|
+
* Legacy wrapper component that delegates to `UFOIgnoreHolds`.
|
|
6
|
+
* Use `UFOIgnoreHolds` instead for new implementations.
|
|
7
|
+
* This component is maintained for backward compatibility only.
|
|
24
8
|
*/
|
|
25
|
-
export default function UFOInteractionIgnore(
|
|
26
|
-
|
|
27
|
-
_ref$ignore = _ref.ignore,
|
|
28
|
-
ignore = _ref$ignore === void 0 ? true : _ref$ignore;
|
|
29
|
-
var parentContext = useContext(InteractionContext);
|
|
30
|
-
var ignoredInteractionContext = useMemo(function () {
|
|
31
|
-
if (!parentContext) {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
return _objectSpread(_objectSpread({}, parentContext), {}, {
|
|
35
|
-
hold: function hold() {
|
|
36
|
-
if (!ignore) {
|
|
37
|
-
return parentContext.hold.apply(parentContext, arguments);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
}, [parentContext, ignore]);
|
|
42
|
-
|
|
43
|
-
// react-18: Use children directly
|
|
44
|
-
var kids = children != null ? children : null;
|
|
45
|
-
if (!ignoredInteractionContext) {
|
|
46
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, kids);
|
|
47
|
-
}
|
|
48
|
-
return /*#__PURE__*/React.createElement(InteractionContext.Provider, {
|
|
49
|
-
value: ignoredInteractionContext
|
|
50
|
-
}, kids);
|
|
9
|
+
export default function UFOInteractionIgnore(props) {
|
|
10
|
+
return /*#__PURE__*/React.createElement(UFOIgnoreHolds, props);
|
|
51
11
|
}
|
|
@@ -6,7 +6,7 @@ import { experimentalVC, sinkExperimentalHandler } from '../create-experimental-
|
|
|
6
6
|
import { setupHiddenTimingCapture } from '../hidden-timing';
|
|
7
7
|
import { postInteractionLog, sinkInteractionHandler, sinkPostInteractionLogHandler } from '../interaction-metrics';
|
|
8
8
|
import { getPerformanceObserver } from '../interactions-performance-observer';
|
|
9
|
-
import { initialisePressureObserver } from '../machine-utilisation';
|
|
9
|
+
import { initialiseMemoryObserver, initialisePressureObserver } from '../machine-utilisation';
|
|
10
10
|
import { getVCObserver } from '../vc';
|
|
11
11
|
import scheduleIdleCallback from './schedule-idle-callback';
|
|
12
12
|
var initialized = false;
|
|
@@ -78,6 +78,9 @@ export function init(analyticsWebClientAsync, config) {
|
|
|
78
78
|
if (fg('platform_ufo_report_cpu_usage')) {
|
|
79
79
|
initialisePressureObserver();
|
|
80
80
|
}
|
|
81
|
+
if (fg('platform_ufo_report_memory_usage')) {
|
|
82
|
+
initialiseMemoryObserver();
|
|
83
|
+
}
|
|
81
84
|
setUFOConfig(config);
|
|
82
85
|
if ((_config$vc = config.vc) !== null && _config$vc !== void 0 && _config$vc.enabled) {
|
|
83
86
|
var _config$experimentalI;
|