diff --git a/src/CONST.js b/src/CONST.js index 2d82c601f3cd..9e4707b16a81 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -372,6 +372,7 @@ const CONST = { SWITCH_REPORT: 'switch_report', SIDEBAR_LOADED: 'sidebar_loaded', COLD: 'cold', + WARM: 'warm', REPORT_ACTION_ITEM_LAYOUT_DEBOUNCE_TIME: 1500, SHOW_LOADING_SPINNER_DEBOUNCE_TIME: 250, TOOLTIP_SENSE: 1000, diff --git a/src/libs/Navigation/AppNavigator/MainDrawerNavigator.js b/src/libs/Navigation/AppNavigator/MainDrawerNavigator.js index ecc67769e8b8..49c2b6093ac3 100644 --- a/src/libs/Navigation/AppNavigator/MainDrawerNavigator.js +++ b/src/libs/Navigation/AppNavigator/MainDrawerNavigator.js @@ -2,11 +2,14 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; import lodashGet from 'lodash/get'; import {withOnyx} from 'react-native-onyx'; +import _ from 'underscore'; import FullScreenLoadingIndicator from '../../../components/FullscreenLoadingIndicator'; import ONYXKEYS from '../../../ONYXKEYS'; import SCREENS from '../../../SCREENS'; import Permissions from '../../Permissions'; +import Timing from '../../actions/Timing'; +import CONST from '../../../CONST'; // Screens import ReportScreen from '../../../pages/home/ReportScreen'; @@ -57,7 +60,12 @@ const getInitialReportScreenParams = (reports, ignoreDefaultRooms, policies) => class MainDrawerNavigator extends Component { constructor(props) { super(props); + this.trackAppStartTiming = this.trackAppStartTiming.bind(this); this.initialParams = getInitialReportScreenParams(props.reports, !Permissions.canUseDefaultRooms(props.betas), props.policies); + + // When we have chat reports the moment this component got created + // we know that the data was served from storage/cache + this.isFromCache = _.size(props.reports) > 0; } shouldComponentUpdate(nextProps) { @@ -70,6 +78,15 @@ class MainDrawerNavigator extends Component { return true; } + trackAppStartTiming() { + // We only want to report timing events when rendering from cached data + if (!this.isFromCache) { + return; + } + + Timing.end(CONST.TIMING.SIDEBAR_LOADED); + } + render() { // Wait until reports are fetched and there is a reportID in initialParams if (!this.initialParams.reportID) { @@ -87,6 +104,7 @@ class MainDrawerNavigator extends Component { return ( ); diff --git a/src/libs/actions/App.js b/src/libs/actions/App.js index 874b45f1fc57..b405ae82aa49 100644 --- a/src/libs/actions/App.js +++ b/src/libs/actions/App.js @@ -9,7 +9,6 @@ import ONYXKEYS from '../../ONYXKEYS'; import CONST from '../../CONST'; import Log from '../Log'; import Performance from '../Performance'; -import Timing from './Timing'; import * as Policy from './Policy'; import Navigation from '../Navigation/Navigation'; import ROUTES from '../../ROUTES'; @@ -95,7 +94,6 @@ function setSidebarLoaded() { } Onyx.set(ONYXKEYS.IS_SIDEBAR_LOADED, true); - Timing.end(CONST.TIMING.SIDEBAR_LOADED); Performance.markEnd(CONST.TIMING.SIDEBAR_LOADED); Performance.markStart(CONST.TIMING.REPORT_INITIAL_RENDER); } diff --git a/src/libs/actions/Timing.js b/src/libs/actions/Timing.js index 1c681dfea25e..ab0b72e0e31a 100644 --- a/src/libs/actions/Timing.js +++ b/src/libs/actions/Timing.js @@ -32,29 +32,32 @@ function end(eventName, secondaryName = '') { return; } - const {startTime, shouldUseFirebase} = timestampData[eventName]; - const eventTime = Date.now() - startTime; + Environment.getEnvironment().then((envName) => { + const {startTime, shouldUseFirebase} = timestampData[eventName]; + const eventTime = Date.now() - startTime; - if (shouldUseFirebase) { - Firebase.stopTrace(eventName); - } + if (shouldUseFirebase) { + Firebase.stopTrace(eventName); + } - const grafanaEventName = secondaryName - ? `expensify.cash.${eventName}.${secondaryName}` - : `expensify.cash.${eventName}`; + const baseEventName = `${envName}.new.expensify.${eventName}`; + const grafanaEventName = secondaryName + ? `${baseEventName}.${secondaryName}` + : baseEventName; - console.debug(`Timing:${grafanaEventName}`, eventTime); - delete timestampData[eventName]; + console.debug(`Timing:${grafanaEventName}`, eventTime); + delete timestampData[eventName]; - if (Environment.isDevelopment()) { - // Don't create traces on dev as this will mess up the accuracy of data in release builds of the app - return; - } + if (Environment.isDevelopment()) { + // Don't create traces on dev as this will mess up the accuracy of data in release builds of the app + return; + } - API.write('SendPerformanceTiming', { - name: grafanaEventName, - value: eventTime, - platform: `${getPlatform()}`, + API.write('SendPerformanceTiming', { + name: grafanaEventName, + value: eventTime, + platform: `${getPlatform()}`, + }); }); } diff --git a/src/pages/home/report/ReportActionsView.js b/src/pages/home/report/ReportActionsView.js index 9983cc804525..711a0045026b 100755 --- a/src/pages/home/report/ReportActionsView.js +++ b/src/pages/home/report/ReportActionsView.js @@ -60,6 +60,7 @@ class ReportActionsView extends React.Component { this.didLayout = false; this.didSubscribeToReportTypingEvents = false; this.unsubscribeVisibilityListener = null; + this.hasCachedActions = _.size(props.reportActions) > 0; // We need this.sortedAndFilteredReportActions to be set before this.state is initialized because the function to calculate the newMarkerReportActionID uses the sorted report actions this.sortedAndFilteredReportActions = this.getSortedReportActionsForDisplay(props.reportActions); @@ -348,7 +349,7 @@ class ReportActionsView extends React.Component { } this.didLayout = true; - Timing.end(CONST.TIMING.SWITCH_REPORT, CONST.TIMING.COLD); + Timing.end(CONST.TIMING.SWITCH_REPORT, this.hasCachedActions ? CONST.Timing.WARM : CONST.TIMING.COLD); // Capture the init measurement only once not per each chat switch as the value gets overwritten if (!ReportActionsView.initMeasured) { diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 09a3f9a21d6a..393662dd12a8 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -61,6 +61,9 @@ const propTypes = { /** Current reportID from the route in react navigation state object */ reportIDFromRoute: PropTypes.string, + /** Callback when onLayout of sidebar is called */ + onLayout: PropTypes.func, + /** Whether we are viewing below the responsive breakpoint */ isSmallScreenWidth: PropTypes.bool.isRequired, @@ -78,6 +81,7 @@ const defaultProps = { avatar: ReportUtils.getDefaultAvatar(), }, reportIDFromRoute: '', + onLayout: () => {}, priorityMode: CONST.PRIORITY_MODE.DEFAULT, }; @@ -189,6 +193,7 @@ class SidebarLinks extends React.Component { shouldDisableFocusOptions={this.props.isSmallScreenWidth} optionMode={this.props.priorityMode === CONST.PRIORITY_MODE.GSD ? 'compact' : 'default'} onLayout={() => { + this.props.onLayout(); App.setSidebarLoaded(); this.isSidebarLoaded = true; }} diff --git a/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js b/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js index 3410b95e4163..bcca70f3f354 100644 --- a/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js +++ b/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js @@ -63,6 +63,7 @@ class BaseSidebarScreen extends Component { isSmallScreenWidth={this.props.isSmallScreenWidth} isDrawerOpen={this.props.isDrawerOpen} reportIDFromRoute={this.props.reportIDFromRoute} + onLayout={this.props.onLayout} /> diff --git a/src/pages/home/sidebar/SidebarScreen/sidebarPropTypes.js b/src/pages/home/sidebar/SidebarScreen/sidebarPropTypes.js index 3affaa2d00be..ec44cd8de44b 100644 --- a/src/pages/home/sidebar/SidebarScreen/sidebarPropTypes.js +++ b/src/pages/home/sidebar/SidebarScreen/sidebarPropTypes.js @@ -4,5 +4,8 @@ const sidebarPropTypes = { /** reportID in the current navigation state */ reportIDFromRoute: PropTypes.string, + + /** Callback when onLayout of sidebar is called */ + onLayout: PropTypes.func, }; export default sidebarPropTypes;