Skip to content

Commit

Permalink
[MM-13955] Add telemetry for Android (mattermost#2719)
Browse files Browse the repository at this point in the history
* add markers for Android profiling

* update per comments

* Remove beta build flag

* update per comment, latest change on telemetry server and others

* rebase and fix merge conflicts, and update per comments

* update commit hash of mattermost-redux
  • Loading branch information
saturninoabril authored May 7, 2019
1 parent 5ce9208 commit e086d66
Show file tree
Hide file tree
Showing 28 changed files with 554 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,30 @@
import com.wix.reactnativenotifications.core.AppLifecycleFacade;
import com.wix.reactnativenotifications.core.JsIOHelper;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactMarker;
import com.facebook.react.bridge.ReactMarkerConstants;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import android.support.annotation.Nullable;

import android.util.Log;

public class MainApplication extends NavigationApplication implements INotificationsApplication, INotificationsDrawerApplication {
public NotificationsLifecycleFacade notificationsLifecycleFacade;
public Boolean sharedExtensionIsOpened = false;
public Boolean replyFromPushNotification = false;

public long APP_START_TIME;

public long RELOAD;
public long CONTENT_APPEARED;

public long PROCESS_PACKAGES_START;
public long PROCESS_PACKAGES_END;

@Override
public boolean isDebug() {
return BuildConfig.DEBUG;
Expand Down Expand Up @@ -109,6 +126,9 @@ public void onCreate() {
setActivityCallbacks(notificationsLifecycleFacade);

SoLoader.init(this, /* native exopackage */ false);

// Uncomment to listen to react markers for build that has telemetry enabled
// addReactMarkerListener();
}

@Override
Expand All @@ -133,4 +153,36 @@ public IPushNotification getPushNotification(Context context, Bundle bundle, App
public IPushNotificationsDrawer getPushNotificationsDrawer(Context context, AppLaunchHelper defaultAppLaunchHelper) {
return new CustomPushNotificationDrawer(context, defaultAppLaunchHelper);
}

private void addReactMarkerListener() {
ReactMarker.addListener(new ReactMarker.MarkerListener() {
@Override
public void logMarker(ReactMarkerConstants name, @Nullable String tag, int instanceKey) {
if (name.toString() == ReactMarkerConstants.RELOAD.toString()) {
APP_START_TIME = System.currentTimeMillis();
RELOAD = System.currentTimeMillis();
} else if (name.toString() == ReactMarkerConstants.PROCESS_PACKAGES_START.toString()) {
PROCESS_PACKAGES_START = System.currentTimeMillis();
} else if (name.toString() == ReactMarkerConstants.PROCESS_PACKAGES_END.toString()) {
PROCESS_PACKAGES_END = System.currentTimeMillis();
} else if (name.toString() == ReactMarkerConstants.CONTENT_APPEARED.toString()) {
CONTENT_APPEARED = System.currentTimeMillis();
ReactContext ctx = getReactGateway().getReactContext();

if (ctx != null) {
WritableMap map = Arguments.createMap();

map.putDouble("appReload", RELOAD);
map.putDouble("appContentAppeared", CONTENT_APPEARED);

map.putDouble("processPackagesStart", PROCESS_PACKAGES_START);
map.putDouble("processPackagesEnd", PROCESS_PACKAGES_END);

ctx.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).
emit("nativeMetrics", map);
}
}
}
});
}
}
14 changes: 14 additions & 0 deletions app/actions/views/channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import {
} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeamId, getTeamByName} from 'mattermost-redux/selectors/entities/teams';

import telemetry from 'app/telemetry';

import {
getChannelByName,
getDirectChannelName,
Expand Down Expand Up @@ -536,6 +538,12 @@ export function leaveChannel(channel, reset = false) {
}

export function setChannelLoading(loading = true) {
if (loading) {
telemetry.start(['channel:loading']);
} else {
telemetry.end(['channel:loading']);
}

return {
type: ViewTypes.SET_CHANNEL_LOADER,
loading,
Expand Down Expand Up @@ -593,6 +601,9 @@ export function increasePostVisibility(channelId, postId) {
return true;
}

telemetry.reset();
telemetry.start(['posts:loading']);

dispatch({
type: ViewTypes.LOADING_POSTS,
data: true,
Expand Down Expand Up @@ -630,6 +641,9 @@ export function increasePostVisibility(channelId, postId) {
}

dispatch(batchActions(actions));
telemetry.end(['posts:loading']);
telemetry.save();

return hasMorePost;
};
}
Expand Down
3 changes: 3 additions & 0 deletions app/components/post/post.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export default class Post extends PureComponent {
renderReplies: PropTypes.bool,
isFirstReply: PropTypes.bool,
isLastReply: PropTypes.bool,
isLastPost: PropTypes.bool,
consecutivePost: PropTypes.bool,
hasComments: PropTypes.bool,
isSearchResult: PropTypes.bool,
Expand Down Expand Up @@ -237,6 +238,7 @@ export default class Post extends PureComponent {
channelIsReadOnly,
commentedOnPost,
highlight,
isLastPost,
isLastReply,
isSearchResult,
onHashtagPress,
Expand Down Expand Up @@ -336,6 +338,7 @@ export default class Post extends PureComponent {
ref={'postBody'}
highlight={highlight}
channelIsReadOnly={channelIsReadOnly}
isLastPost={isLastPost}
isSearchResult={isSearchResult}
navigator={this.props.navigator}
onFailedPostPress={this.handleFailedPostPress}
Expand Down
18 changes: 18 additions & 0 deletions app/components/post_body/post_body.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import {getMarkdownTextStyles, getMarkdownBlockStyles} from 'app/utils/markdown'
import {preventDoubleTap} from 'app/utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';

import telemetry from 'app/telemetry';

let FileAttachmentList;
let PostAddChannelMember;
let PostBodyAdditionalContent;
Expand All @@ -43,6 +45,7 @@ export default class PostBody extends PureComponent {
highlight: PropTypes.bool,
isFailed: PropTypes.bool,
isFlagged: PropTypes.bool,
isLastPost: PropTypes.bool,
isPending: PropTypes.bool,
isPostAddChannelMember: PropTypes.bool,
isPostEphemeral: PropTypes.bool,
Expand Down Expand Up @@ -95,6 +98,17 @@ export default class PostBody extends PureComponent {
isLongPost: false,
};

logTelemetry = () => {
telemetry.end([
'channel:switch_initial',
'channel:switch_loaded',
'posts:list_update',
'team:switch',
'start:overall',
]);
telemetry.save();
}

measurePost = (event) => {
const {height} = event.nativeEvent.layout;
const {showLongPost} = this.props;
Expand All @@ -104,6 +118,10 @@ export default class PostBody extends PureComponent {
isLongPost: true,
});
}

if (this.props.isLastPost) {
this.logTelemetry();
}
};

openLongPost = preventDoubleTap(() => {
Expand Down
5 changes: 5 additions & 0 deletions app/components/post_list/post_list.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import mattermostManaged from 'app/mattermost_managed';
import {makeExtraData} from 'app/utils/list_view';
import {changeOpacity} from 'app/utils/theme';
import {matchDeepLink} from 'app/utils/url';
import telemetry from 'app/telemetry';

import DateHeader from './date_header';
import NewMessagesDivider from './new_messages_divider';
Expand Down Expand Up @@ -48,6 +49,7 @@ export default class PostList extends PureComponent {
highlightPostId: PropTypes.string,
initialIndex: PropTypes.number,
isSearchResult: PropTypes.bool,
lastPostIndex: PropTypes.number.isRequired,
lastViewedAt: PropTypes.number, // Used by container // eslint-disable-line no-unused-prop-types
navigator: PropTypes.object,
onLoadMoreUp: PropTypes.func,
Expand Down Expand Up @@ -103,6 +105,8 @@ export default class PostList extends PureComponent {
this.handleDeepLink(this.props.deepLinkURL);
this.props.actions.setDeepLinkURL('');
}

telemetry.start(['posts:list_update']);
}

componentWillUnmount() {
Expand Down Expand Up @@ -256,6 +260,7 @@ export default class PostList extends PureComponent {
<Post
postId={postId}
highlight={this.props.highlightPostId === postId}
isLastPost={this.props.lastPostIndex === index}
{...postProps}
/>
);
Expand Down
1 change: 1 addition & 0 deletions app/components/post_list/post_list.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ describe('PostList', () => {
navigator: {
showModal: jest.fn(),
},
lastPostIndex: -1,
postIds: ['post-id-1', 'post-id-2'],
serverURL,
siteURL: 'https://site-url.fake',
Expand Down
6 changes: 6 additions & 0 deletions app/components/sidebars/drawer_layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
I18nManager,
} from 'react-native';

import telemetry from 'app/telemetry';

const MIN_SWIPE_DISTANCE = 3;
const DEVICE_WIDTH = parseFloat(Dimensions.get('window').width);
const THRESHOLD = DEVICE_WIDTH / 2;
Expand Down Expand Up @@ -234,6 +236,9 @@ export default class DrawerLayout extends Component {
...options,
}).start(() => {
if (this.props.onDrawerOpen) {
telemetry.end(['channel:open_drawer']);
telemetry.save();

this.props.onDrawerOpen();
}
this._emitStateChanged(IDLE);
Expand All @@ -250,6 +255,7 @@ export default class DrawerLayout extends Component {
...options,
}).start(() => {
if (this.props.onDrawerClose) {
telemetry.end(['channel:close_drawer']);
this.props.onDrawerClose();
}
this._emitStateChanged(IDLE);
Expand Down
20 changes: 20 additions & 0 deletions app/components/sidebars/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,28 @@ import {getCurrentTeamId, getMyTeamsCount} from 'mattermost-redux/selectors/enti
import {setChannelDisplayName, setChannelLoading} from 'app/actions/views/channel';
import {makeDirectChannel} from 'app/actions/views/more_dms';
import {isLandscape, isTablet, getDimensions} from 'app/selectors/device';
import telemetry from 'app/telemetry';

import MainSidebar from './main_sidebar.js';

export function logChannelSwitch(channelId, currentChannelId) {
return (dispatch, getState) => {
if (channelId === currentChannelId) {
return;
}

const metrics = [];
if (getState().entities.posts.postsInChannel[channelId]) {
metrics.push('channel:switch_loaded');
} else {
metrics.push('channel:switch_initial');
}

telemetry.reset();
telemetry.start(metrics);
};
}

function mapStateToProps(state) {
const {currentUserId} = state.entities.users;

Expand All @@ -34,6 +53,7 @@ function mapDispatchToProps(dispatch) {
actions: bindActionCreators({
getTeams,
joinChannel,
logChannelSwitch,
makeDirectChannel,
setChannelDisplayName,
setChannelLoading,
Expand Down
8 changes: 7 additions & 1 deletion app/components/sidebars/main/main_sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,16 @@ import ChannelsList from './channels_list';
import DrawerSwiper from './drawer_swipper';
import TeamsList from './teams_list';

import telemetry from 'app/telemetry';

const DRAWER_INITIAL_OFFSET = 40;
const DRAWER_LANDSCAPE_OFFSET = 150;

export default class ChannelSidebar extends Component {
static propTypes = {
actions: PropTypes.shape({
getTeams: PropTypes.func.isRequired,
logChannelSwitch: PropTypes.func.isRequired,
makeDirectChannel: PropTypes.func.isRequired,
setChannelDisplayName: PropTypes.func.isRequired,
setChannelLoading: PropTypes.func.isRequired,
Expand Down Expand Up @@ -165,11 +168,14 @@ export default class ChannelSidebar extends Component {
};

selectChannel = (channel, currentChannelId, closeDrawer = true) => {
const {setChannelLoading} = this.props.actions;
const {logChannelSwitch, setChannelLoading} = this.props.actions;

logChannelSwitch(channel.id, currentChannelId);

tracker.channelSwitch = Date.now();

if (closeDrawer) {
telemetry.start(['channel:close_drawer']);
this.closeChannelDrawer();
setChannelLoading(channel.id !== currentChannelId);
}
Expand Down
9 changes: 8 additions & 1 deletion app/components/sidebars/main/teams_list/teams_list.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {ListTypes, ViewTypes} from 'app/constants';
import {preventDoubleTap} from 'app/utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
import tracker from 'app/utils/time_tracker';
import telemetry from 'app/telemetry';

import TeamsListItem from './teams_list_item';

Expand Down Expand Up @@ -55,9 +56,15 @@ export default class TeamsList extends PureComponent {
}

selectTeam = (teamId) => {
const {actions, closeChannelDrawer, currentTeamId} = this.props;

if (teamId !== currentTeamId) {
telemetry.reset();
telemetry.start(['team:switch']);
}

StatusBar.setHidden(false, 'slide');
requestAnimationFrame(() => {
const {actions, closeChannelDrawer, currentTeamId} = this.props;
if (teamId !== currentTeamId) {
tracker.teamSwitch = Date.now();
actions.handleTeamChange(teamId);
Expand Down
8 changes: 8 additions & 0 deletions app/mattermost.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {deleteFileCache} from 'app/utils/file';
import avoidNativeBridge from 'app/utils/avoid_native_bridge';
import {t} from 'app/utils/i18n';
import LocalConfig from 'assets/config';
import telemetry from 'app/telemetry';

import App from './app';
import './fetch_preconfig';
Expand Down Expand Up @@ -435,6 +436,11 @@ const handleAppInActive = () => {
AppState.addEventListener('change', handleAppStateChange);

const launchEntry = () => {
telemetry.start([
'start:select_server_screen',
'start:channel_screen',
]);

Navigation.startSingleScreenApp({
screen: {
screen: 'Entry',
Expand All @@ -452,6 +458,8 @@ const launchEntry = () => {
},
animationType: 'fade',
});

telemetry.startSinceLaunch(['start:splash_screen']);
};

configurePushNotifications();
Expand Down
4 changes: 4 additions & 0 deletions app/screens/channel/channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import PushNotifications from 'app/push_notifications';
import tracker from 'app/utils/time_tracker';
import LocalConfig from 'assets/config';

import telemetry from 'app/telemetry';

import ChannelNavBar from './channel_nav_bar';
import ChannelPostList from './channel_post_list';

Expand Down Expand Up @@ -104,6 +106,8 @@ export default class Channel extends PureComponent {
}

EventEmitter.emit('renderDrawer');

telemetry.end(['start:channel_screen']);
}

componentWillReceiveProps(nextProps) {
Expand Down
Loading

0 comments on commit e086d66

Please sign in to comment.