Skip to content

Commit

Permalink
Merge pull request #51815 from callstack-internal/feat/perf-analytics…
Browse files Browse the repository at this point in the history
…-markers

[NOQA] fix: performance analytics markers
  • Loading branch information
mountiny authored Nov 12, 2024
2 parents 0ba31d2 + 41978b1 commit f338d04
Show file tree
Hide file tree
Showing 22 changed files with 53 additions and 123 deletions.
19 changes: 7 additions & 12 deletions contributingGuides/PERFORMANCE_METRICS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,16 @@ Project is using Firebase for tracking these metrics. However, not all of them a
| `js_loaded` || The time it takes for the JavaScript bundle to load. <br><br>**Platforms:** Android, iOS | **Android:** Starts in the `onCreate` method.<br><br>**iOS:** Starts in the AppDelegate's `didFinishLaunchingWithOptions` method. | Stops at the first render of the app via native module on the JS side. |
| `_app_in_foreground` || The time when the app is running in the foreground and available to the user.<br><br>**Platforms:** Android, iOS | **Android:** Starts when the first activity to reach the foreground has its `onResume()` method called. <br><br>**iOS:** Starts when the application receives the `UIApplicationDidBecomeActiveNotification` notification. | **Android:** Stops when the last activity to leave the foreground has its `onStop()` method called. <br><br>**iOS:** Stops when it receives the `UIApplicationWillResignActiveNotification` notification. |
| `_app_in_background` || Time when the app is running in the background.<br><br>**Platforms:** Android, iOS | **Android:** Starts when the last activity to leave the foreground has its `onStop()` method called. <br><br>**iOS:** Starts when the application receives the `UIApplicationWillResignActiveNotification` notification. | **Android:** Stops when the first activity to reach the foreground has its `onResume()` method called. <br><br>**iOS:** Stops when it receives the `UIApplicationDidBecomeActiveNotification` notification. |
| `homepage_initial_render` || Time taken for the initial render of the app for a logged in user.<br><br>**Platforms:** All | Starts with the first render of the `AuthScreens` component. | Stops once the `AuthScreens` component is mounted. |
| `sidebar_loaded` || Time taken for the Sidebar to load.<br><br>**Platforms:** All | Starts when the Sidebar is mounted. | Stops when the Splash Screen is hidden. |
| `sidebar_loaded` || Time taken for the Sidebar to load.<br><br>**Platforms:** All | Starts when the Sidebar is mounted. | Stops when the LHN finishes laying out. |
| `calc_most_recent_last_modified_action` || Time taken to find the most recently modified report action or report.<br><br>**Platforms:** All | Starts when the app reconnects to the network | Ends when the app reconnects to the network and the most recent report action or report is found. |
| `search_render` || Time taken to render the Chat Finder page.<br><br>**Platforms:** All | Starts when the Chat Finder icon in LHN is pressed. | Stops when the list of available options is rendered for the first time. |
| `load_search_options` || Time taken to generate the list of options used in Chat Finder.<br><br>**Platforms:** All | Starts when the `getSearchOptions` function is called. | Stops when the list of available options is generated. |
| `search_filter_options` || Time taken to filter search options in Chat Finder by given search value.<br><br>**Platforms:** All | Starts when user types something in the Chat Finder search input. | Stops when the list of filtered options is generated. |
| `open_search` || Time taken to open up the Search Router.<br><br>**Platforms:** All | Starts when the Search Router icon in LHN is pressed. | Stops when the list of available options finishes laying out. |
| `load_search_options` || Time taken to generate the list of options used in the Search Router.<br><br>**Platforms:** All | Starts when the `getSearchOptions` function is called. | Stops when the list of available options is generated. |
| `search_filter_options` || Time taken to filter search options in the Search Router by the given search value.<br><br>**Platforms:** All | Starts when user types something in the Search Router search input. | Stops when the list of filtered options is generated. |
| `trie_initialization` || Time taken to build the emoji trie.<br><br>**Platforms:** All | Starts when emoji trie begins to build. | Stops when emoji trie building is complete. |
| `open_report` || Time taken to open a report.<br><br>**Platforms:** All | Starts when the row in the `LHNOptionsList` is pressed. | Stops when the `ReportActionsList` finishes laying out. |
| `switch_report` || Time taken to open report.<br><br>**Platforms:** All | Starts when the chat in the LHN is pressed. | Stops when the `ReportActionsList` finishes laying out. |
| `open_report` || Time taken to open a report.<br><br>**Platforms:** All | Starts when the row in the `LHNOptionsList` is pressed. | Stops when the `ReportActionsList` finishes laying out. |
| `open_report_from_preview` || Time taken to open a report from preview.<br><br>(previously `switch_report_from_preview`)<br><br>**Platforms:** All | Starts when the user presses the Report Preview. | Stops when the `ReportActionsList` finishes laying out. |
| `switch_report_from_preview` || **[REMOVED]** Time taken to open a report from preview. | Starts when the user presses the Report Preview. | Stops when the `ReportActionsList` finishes laying out. |
| `chat_render` || Time taken to render the Report screen.<br><br>**Platforms:** All | Starts when the `ReportScreen` is being rendered for the first time. | Stops once the `ReportScreen` component is mounted. |
| `report_initial_render` || Time taken to render the Report screen.<br><br>**Platforms:** All | Starts when the first item is rendered in the `LHNOptionsList`. | Stops when the `ReportActionsList` finishes laying out. |
| `open_report_thread` || Time taken to open a thread in a report.<br><br>**Platforms:** All | Starts when user presses Report Action Item. | Stops when the `ReportActionsList` finishes laying out. |
| `message_sent` | | Time taken to send a message.<br><br>**Platforms:** All | Starts when the new message is sent. | Stops when the message is being rendered in the chat. |
| `send_message` | | Time taken to send a message.<br><br>**Platforms:** All | Starts when the new message is sent. | Stops when the message is being rendered in the chat. |

## Documentation Maintenance

Expand All @@ -46,4 +41,4 @@ To ensure this documentation remains accurate and useful, please adhere to the f
## Additional Resources

- [Firebase Documentation](https://firebase.google.com/docs)
- [Firebase Performance Monitoring](https://firebase.google.com/docs/perf-mon)
- [Firebase Performance Monitoring](https://firebase.google.com/docs/perf-mon)
8 changes: 2 additions & 6 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1254,17 +1254,13 @@ const CONST = {
},
TIMING: {
CALCULATE_MOST_RECENT_LAST_MODIFIED_ACTION: 'calc_most_recent_last_modified_action',
SEARCH_ROUTER_RENDER: 'search_router_render',
CHAT_RENDER: 'chat_render',
OPEN_SEARCH: 'open_search',
OPEN_REPORT: 'open_report',
HOMEPAGE_INITIAL_RENDER: 'homepage_initial_render',
REPORT_INITIAL_RENDER: 'report_initial_render',
SWITCH_REPORT: 'switch_report',
OPEN_REPORT_FROM_PREVIEW: 'open_report_from_preview',
OPEN_REPORT_THREAD: 'open_report_thread',
SIDEBAR_LOADED: 'sidebar_loaded',
LOAD_SEARCH_OPTIONS: 'load_search_options',
MESSAGE_SENT: 'message_sent',
SEND_MESSAGE: 'send_message',
COLD: 'cold',
WARM: 'warm',
REPORT_ACTION_ITEM_LAYOUT_DEBOUNCE_TIME: 1500,
Expand Down
2 changes: 0 additions & 2 deletions src/Expensify.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import NavigationRoot from './libs/Navigation/NavigationRoot';
import NetworkConnection from './libs/NetworkConnection';
import PushNotification from './libs/Notification/PushNotification';
import './libs/Notification/PushNotification/subscribePushNotification';
import Performance from './libs/Performance';
import setCrashlyticsUserId from './libs/setCrashlyticsUserId';
import StartupTimer from './libs/StartupTimer';
// This lib needs to be imported, but it has nothing to export since all it contains is an Onyx connection
Expand Down Expand Up @@ -138,7 +137,6 @@ function Expensify() {

const onSplashHide = useCallback(() => {
setSplashScreenState(CONST.BOOT_SPLASH_STATE.HIDDEN);
Performance.markEnd(CONST.TIMING.SIDEBAR_LOADED);
}, [setSplashScreenState]);

useLayoutEffect(() => {
Expand Down
2 changes: 2 additions & 0 deletions src/components/LHNOptionsList/OptionRowLHN.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import * as ReportUtils from '@libs/ReportUtils';
import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportActionContextMenu';
import FreeTrial from '@pages/settings/Subscription/FreeTrial';
import variables from '@styles/variables';
import Timing from '@userActions/Timing';
import * as User from '@userActions/User';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
Expand Down Expand Up @@ -193,6 +194,7 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti
ref={popoverAnchor}
onPress={(event) => {
Performance.markStart(CONST.TIMING.OPEN_REPORT);
Timing.start(CONST.TIMING.OPEN_REPORT);

event?.preventDefault();
// Enable Composer to focus on clicking the same chat after opening the context menu.
Expand Down
2 changes: 2 additions & 0 deletions src/components/ReportActionItem/ReportPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import * as CurrencyUtils from '@libs/CurrencyUtils';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import HapticFeedback from '@libs/HapticFeedback';
import Navigation from '@libs/Navigation/Navigation';
import Performance from '@libs/Performance';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReceiptUtils from '@libs/ReceiptUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
Expand Down Expand Up @@ -456,6 +457,7 @@ function ReportPreview({
<View style={[styles.chatItemMessage, containerStyles]}>
<PressableWithoutFeedback
onPress={() => {
Performance.markStart(CONST.TIMING.OPEN_REPORT_FROM_PREVIEW);
Timing.start(CONST.TIMING.OPEN_REPORT_FROM_PREVIEW);
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(iouReportID));
}}
Expand Down
4 changes: 2 additions & 2 deletions src/components/Search/SearchRouter/SearchButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ function SearchButton({style}: SearchButtonProps) {
accessibilityLabel={translate('common.search')}
style={[styles.flexRow, styles.touchableButtonImage, style]}
onPress={Session.checkIfActionIsAllowed(() => {
Timing.start(CONST.TIMING.SEARCH_ROUTER_RENDER);
Performance.markStart(CONST.TIMING.SEARCH_ROUTER_RENDER);
Timing.start(CONST.TIMING.OPEN_SEARCH);
Performance.markStart(CONST.TIMING.OPEN_SEARCH);

openSearchRouter();
})}
Expand Down
4 changes: 2 additions & 2 deletions src/components/Search/SearchRouter/SearchRouterList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ type SearchRouterListProps = {
};

const setPerformanceTimersEnd = () => {
Timing.end(CONST.TIMING.SEARCH_ROUTER_RENDER);
Performance.markEnd(CONST.TIMING.SEARCH_ROUTER_RENDER);
Timing.end(CONST.TIMING.OPEN_SEARCH);
Performance.markEnd(CONST.TIMING.OPEN_SEARCH);
};

function getContextualSearchQuery(reportName: string) {
Expand Down
19 changes: 1 addition & 18 deletions src/libs/E2E/tests/chatOpeningTest.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ const test = (config: NativeConfig) => {

console.debug('[E2E] Logged in, getting chat opening metrics and submitting them…');

const [renderChatPromise, renderChatResolve] = getPromiseWithResolve();
const [chatTTIPromise, chatTTIResolve] = getPromiseWithResolve();

Promise.all([renderChatPromise, chatTTIPromise]).then(() => {
chatTTIPromise.then(() => {
console.debug(`[E2E] Submitting!`);

E2EClient.submitTestDone();
Expand All @@ -46,22 +45,6 @@ const test = (config: NativeConfig) => {

console.debug(`[E2E] Entry: ${JSON.stringify(entry)}`);

if (entry.name === CONST.TIMING.CHAT_RENDER) {
E2EClient.submitTestResults({
branch: Config.E2E_BRANCH,
name: `${name} Chat opening`,
metric: entry.duration,
unit: 'ms',
})
.then(() => {
console.debug('[E2E] Done with chat opening, exiting…');
renderChatResolve();
})
.catch((err) => {
console.debug('[E2E] Error while submitting test results:', err);
});
}

if (entry.name === CONST.TIMING.OPEN_REPORT) {
E2EClient.submitTestResults({
branch: Config.E2E_BRANCH,
Expand Down
23 changes: 8 additions & 15 deletions src/libs/E2E/tests/linkingTest.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {DeviceEventEmitter} from 'react-native';
import type {NativeConfig} from 'react-native-config';
import Config from 'react-native-config';
import Timing from '@libs/actions/Timing';
import type {NativeConfig} from 'react-native-config';
import E2ELogin from '@libs/E2E/actions/e2eLogin';
import waitForAppLoaded from '@libs/E2E/actions/waitForAppLoaded';
import E2EClient from '@libs/E2E/client';
Expand Down Expand Up @@ -32,9 +31,9 @@ const test = (config: NativeConfig) => {
}

const [appearMessagePromise, appearMessageResolve] = getPromiseWithResolve();
const [switchReportPromise, switchReportResolve] = getPromiseWithResolve();
const [openReportPromise, openReportResolve] = getPromiseWithResolve();

Promise.all([appearMessagePromise, switchReportPromise])
Promise.all([appearMessagePromise, openReportPromise])
.then(() => {
console.debug('[E2E] Test completed successfully, exiting…');
E2EClient.submitTestDone();
Expand All @@ -57,21 +56,15 @@ const test = (config: NativeConfig) => {
Performance.subscribeToMeasurements((entry) => {
if (entry.name === CONST.TIMING.SIDEBAR_LOADED) {
console.debug('[E2E] Sidebar loaded, navigating to a report…');
Performance.markStart(CONST.TIMING.OPEN_REPORT);
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID));
return;
}

if (entry.name === CONST.TIMING.REPORT_INITIAL_RENDER) {
console.debug('[E2E] Navigating to linked report action…');
Timing.start(CONST.TIMING.SWITCH_REPORT);
Performance.markStart(CONST.TIMING.SWITCH_REPORT);

Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(linkedReportID, linkedReportActionID));
return;
}

if (entry.name === CONST.TIMING.SWITCH_REPORT) {
if (entry.name === CONST.TIMING.OPEN_REPORT) {
console.debug('[E2E] Linking: 1');
console.debug('[E2E] Navigating to the linked report action…');
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(linkedReportID, linkedReportActionID));

E2EClient.submitTestResults({
branch: Config.E2E_BRANCH,
Expand All @@ -80,7 +73,7 @@ const test = (config: NativeConfig) => {
unit: 'ms',
});

switchReportResolve();
openReportResolve();
}
});
});
Expand Down
2 changes: 1 addition & 1 deletion src/libs/E2E/tests/openSearchRouterTest.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const test = (config: NativeConfig) => {
props.onPress();
}

if (entry.name === CONST.TIMING.SEARCH_ROUTER_RENDER) {
if (entry.name === CONST.TIMING.OPEN_SEARCH) {
E2EClient.submitTestResults({
branch: Config.E2E_BRANCH,
name: `${name} Open Search Router TTI`,
Expand Down
2 changes: 1 addition & 1 deletion src/libs/E2E/tests/reportTypingTest.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const test = (config: NativeConfig) => {
});

Performance.subscribeToMeasurements((entry) => {
if (entry.name === CONST.TIMING.MESSAGE_SENT) {
if (entry.name === CONST.TIMING.SEND_MESSAGE) {
E2EClient.submitTestResults({
branch: Config.E2E_BRANCH,
name: `${name} Message sent`,
Expand Down
5 changes: 0 additions & 5 deletions src/libs/Navigation/AppNavigator/AuthScreens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ import * as PriorityMode from '@userActions/PriorityMode';
import * as Report from '@userActions/Report';
import * as Session from '@userActions/Session';
import toggleTestToolsModal from '@userActions/TestTool';
import Timing from '@userActions/Timing';
import * as User from '@userActions/User';
import CONFIG from '@src/CONFIG';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -248,8 +247,6 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie

// eslint-disable-next-line react-compiler/react-compiler
if (isInitialRender.current) {
Timing.start(CONST.TIMING.HOMEPAGE_INITIAL_RENDER);

const currentURL = getCurrentUrl();
if (currentURL) {
initialReportID = new URL(currentURL).pathname.match(CONST.REGEX.REPORT_ID_FROM_PATH)?.at(1);
Expand Down Expand Up @@ -313,8 +310,6 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie
}
Download.clearDownloads();

Timing.end(CONST.TIMING.HOMEPAGE_INITIAL_RENDER);

const unsubscribeOnyxModal = onyxSubscribe({
key: ONYXKEYS.MODAL,
callback: (modalArg) => {
Expand Down
2 changes: 1 addition & 1 deletion src/libs/actions/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ function setSidebarLoaded() {
}

Onyx.set(ONYXKEYS.IS_SIDEBAR_LOADED, true);
Performance.markStart(CONST.TIMING.REPORT_INITIAL_RENDER);
Performance.markEnd(CONST.TIMING.SIDEBAR_LOADED);
}

let appState: AppStateStatus;
Expand Down
11 changes: 1 addition & 10 deletions src/pages/home/ReportScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@ import usePrevious from '@hooks/usePrevious';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useThemeStyles from '@hooks/useThemeStyles';
import useViewportOffsetTop from '@hooks/useViewportOffsetTop';
import Timing from '@libs/actions/Timing';
import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
import clearReportNotifications from '@libs/Notification/clearReportNotifications';
import Performance from '@libs/Performance';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
Expand Down Expand Up @@ -230,11 +228,7 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro
const [scrollPosition, setScrollPosition] = useState<ScrollPosition>({});

const wasReportAccessibleRef = useRef(false);
// eslint-disable-next-line react-compiler/react-compiler
if (firstRenderRef.current) {
Timing.start(CONST.TIMING.CHAT_RENDER);
Performance.markStart(CONST.TIMING.CHAT_RENDER);
}

const [isComposerFocus, setIsComposerFocus] = useState(false);
const shouldAdjustScrollView = useMemo(() => isComposerFocus && !modal?.willAlertModalBecomeVisible, [isComposerFocus, modal]);
const viewportOffsetTop = useViewportOffsetTop(shouldAdjustScrollView);
Expand Down Expand Up @@ -487,9 +481,6 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro
useAppFocusEvent(clearNotifications);

useEffect(() => {
Timing.end(CONST.TIMING.CHAT_RENDER);
Performance.markEnd(CONST.TIMING.CHAT_RENDER);

const interactionTask = InteractionManager.runAfterInteractions(() => {
ComposerActions.setShouldShowComposeInput(true);
});
Expand Down
Loading

0 comments on commit f338d04

Please sign in to comment.