From 363cd132077b540b3bca6a6dab1b17a0b73ff481 Mon Sep 17 00:00:00 2001
From: Youssef Muhamad <emaildeyoussefmuhamad@gmail.com>
Date: Thu, 30 Jul 2020 16:51:13 -0300
Subject: [PATCH] [NEW] Log events from Room, Settings and Edit status (#2206)

* Create method to track user event to isolate the logic to improve future refactoring

* Track Onboarding view

* Track NewServer view

* Refactor track method due to firebase already send the current screen

* Track default login and all the oAuth options

* Track default sign up in RegisterView

* Change trackUserEvent signature and update all the files

* Track the remaining login services

* track add server, change server and search

* Track SidebarView and refactor to use react-navigation

* Track profile events and handle exceptions

* Track create channel flux

* Track send message to user via NewMessageView

* Track create direct message flux

* Handle failure of create channel and group in the saga

* Track create discussion flux

* Track navigate to directory and its actions

* Track read, favorite and hide a channel, handling its errors

* Track all channels sorting and grouping

* Resolve requests to improve the importing logs and events

* Remove unused events file

* Remove unused events file

* log proposed Room events

* Log proposed Message actions events

* Log EditStatus proposed events

* Log Settings proposed events

* Leave a bugsnag breadcrumb when logging an event

* Move all logEvent to the top of code block and log remaining fail events

* Move all the non-logic-dependent logEvent to the top of code block

* Move all non-logic and non-data dependent logEvent to the top of code block

* Improve the logging of sidebar events

* Improve events from onboarding and newserver

* Improve events from login and register view, and log enter with apple

* Improve NewMessageView events

* Improve CreateChannel events

* Improve CreateDiscussion and SelectedUsers create group events

* Improve RoomsList events and log trivial events

* Improve ProfileView events

* Remove single line function body for the sidebarNavigate

* Improve SettingsView events

* Log more events from ScreenLockConfigView

* Navigate to Status and AdminPanel View using the defined sidebarNavigate method

* Improve StatusView events

* Improve RoomView events

Co-authored-by: Diego Mello <diegolmello@gmail.com>
---
 app/containers/MessageActions/index.js        | 38 ++++++--
 app/containers/MessageBox/RecordAudio.js      | 10 +-
 app/containers/MessageBox/index.js            | 22 +++--
 app/utils/log/events.js                       | 93 ++++++++++++++++++-
 app/utils/review.js                           |  3 +
 app/views/DefaultBrowserView.js               |  4 +-
 app/views/LanguageView/index.js               |  6 +-
 app/views/RoomView/index.js                   |  3 +-
 app/views/RoomsListView/SortDropdown/index.js |  2 +-
 app/views/ScreenLockConfigView.js             |  6 ++
 app/views/SelectedUsersView.js                |  1 -
 app/views/SettingsView/index.js               | 19 +++-
 app/views/StatusView.js                       |  8 +-
 app/views/ThemeView.js                        |  3 +
 14 files changed, 188 insertions(+), 30 deletions(-)

diff --git a/app/containers/MessageActions/index.js b/app/containers/MessageActions/index.js
index 0c9c78a3e..ff4c4dbf2 100644
--- a/app/containers/MessageActions/index.js
+++ b/app/containers/MessageActions/index.js
@@ -7,7 +7,7 @@ import moment from 'moment';
 import RocketChat from '../../lib/rocketchat';
 import database from '../../lib/database';
 import I18n from '../../i18n';
-import log from '../../utils/log';
+import log, { logEvent } from '../../utils/log';
 import Navigation from '../../lib/Navigation';
 import { getMessageTranslation } from '../message/utils';
 import { LISTENER } from '../Toast';
@@ -15,6 +15,7 @@ import EventEmitter from '../../utils/events';
 import { showConfirmationAlert } from '../../utils/info';
 import { useActionSheet } from '../ActionSheet';
 import Header, { HEADER_HEIGHT } from './Header';
+import events from '../../utils/log/events';
 
 const MessageActions = React.memo(forwardRef(({
 	room,
@@ -112,11 +113,18 @@ const MessageActions = React.memo(forwardRef(({
 
 	const getPermalink = message => RocketChat.getPermalinkMessage(message);
 
-	const handleReply = message => replyInit(message, true);
+	const handleReply = (message) => {
+		logEvent(events.ROOM_MSG_ACTION_REPLY);
+		replyInit(message, true);
+	};
 
-	const handleEdit = message => editInit(message);
+	const handleEdit = (message) => {
+		logEvent(events.ROOM_MSG_ACTION_EDIT);
+		editInit(message);
+	};
 
 	const handleCreateDiscussion = (message) => {
+		logEvent(events.ROOM_MSG_ACTION_DISCUSSION);
 		const params = { message, channel: room, showCloseModal: true };
 		if (isMasterDetail) {
 			Navigation.navigate('ModalStackNavigator', { screen: 'CreateDiscussionView', params });
@@ -126,6 +134,7 @@ const MessageActions = React.memo(forwardRef(({
 	};
 
 	const handleUnread = async(message) => {
+		logEvent(events.ROOM_MSG_ACTION_UNREAD);
 		const { id: messageId, ts } = message;
 		const { rid } = room;
 		try {
@@ -144,54 +153,66 @@ const MessageActions = React.memo(forwardRef(({
 				Navigation.navigate('RoomsListView');
 			}
 		} catch (e) {
+			logEvent(events.ROOM_MSG_ACTION_UNREAD_F);
 			log(e);
 		}
 	};
 
 	const handlePermalink = async(message) => {
+		logEvent(events.ROOM_MSG_ACTION_PERMALINK);
 		try {
 			const permalink = await getPermalink(message);
 			Clipboard.setString(permalink);
 			EventEmitter.emit(LISTENER, { message: I18n.t('Permalink_copied_to_clipboard') });
 		} catch {
-			// Do nothing
+			logEvent(events.ROOM_MSG_ACTION_PERMALINK_F);
 		}
 	};
 
 	const handleCopy = async(message) => {
+		logEvent(events.ROOM_MSG_ACTION_COPY);
 		await Clipboard.setString(message.msg);
 		EventEmitter.emit(LISTENER, { message: I18n.t('Copied_to_clipboard') });
 	};
 
 	const handleShare = async(message) => {
+		logEvent(events.ROOM_MSG_ACTION_SHARE);
 		try {
 			const permalink = await getPermalink(message);
 			Share.share({ message: permalink });
 		} catch {
-			// Do nothing
+			logEvent(events.ROOM_MSG_ACTION_SHARE_F);
 		}
 	};
 
-	const handleQuote = message => replyInit(message, false);
+	const handleQuote = (message) => {
+		logEvent(events.ROOM_MSG_ACTION_QUOTE);
+		replyInit(message, false);
+	};
 
 	const handleStar = async(message) => {
+		logEvent(message.starred ? events.ROOM_MSG_ACTION_UNSTAR : events.ROOM_MSG_ACTION_STAR);
 		try {
 			await RocketChat.toggleStarMessage(message.id, message.starred);
 			EventEmitter.emit(LISTENER, { message: message.starred ? I18n.t('Message_unstarred') : I18n.t('Message_starred') });
 		} catch (e) {
+			logEvent(events.ROOM_MSG_ACTION_STAR_F);
 			log(e);
 		}
 	};
 
 	const handlePin = async(message) => {
+		logEvent(events.ROOM_MSG_ACTION_PIN);
 		try {
 			await RocketChat.togglePinMessage(message.id, message.pinned);
 		} catch (e) {
+			logEvent(events.ROOM_MSG_ACTION_PIN_F);
 			log(e);
 		}
 	};
 
 	const handleReaction = (shortname, message) => {
+		logEvent(events.ROOM_MSG_ACTION_REACTION);
 		if (shortname) {
 			onReactionPress(shortname, message.id);
 		} else {
@@ -234,10 +255,12 @@ const MessageActions = React.memo(forwardRef(({
 	};
 
 	const handleReport = async(message) => {
+		logEvent(events.ROOM_MSG_ACTION_REPORT);
 		try {
 			await RocketChat.reportMessage(message.id);
 			Alert.alert(I18n.t('Message_Reported'));
 		} catch (e) {
+			logEvent(events.ROOM_MSG_ACTION_REPORT_F);
 			log(e);
 		}
 	};
@@ -248,8 +271,10 @@ const MessageActions = React.memo(forwardRef(({
 			callToAction: I18n.t('Delete'),
 			onPress: async() => {
 				try {
+					logEvent(events.ROOM_MSG_ACTION_DELETE);
 					await RocketChat.deleteMessage(message.id, message.subscription.id);
 				} catch (e) {
+					logEvent(events.ROOM_MSG_ACTION_DELETE_F);
 					log(e);
 				}
 			}
@@ -381,6 +406,7 @@ const MessageActions = React.memo(forwardRef(({
 	};
 
 	const showMessageActions = async(message) => {
+		logEvent(events.ROOM_SHOW_MSG_ACTIONS);
 		await getPermissions();
 		showActionSheet({
 			options: getOptions(message),
diff --git a/app/containers/MessageBox/RecordAudio.js b/app/containers/MessageBox/RecordAudio.js
index 2325d5ecd..5d277023b 100644
--- a/app/containers/MessageBox/RecordAudio.js
+++ b/app/containers/MessageBox/RecordAudio.js
@@ -10,6 +10,7 @@ import styles from './styles';
 import I18n from '../../i18n';
 import { themes } from '../../constants/colors';
 import { CustomIcon } from '../../lib/Icons';
+import { logEvent, events } from '../../utils/log';
 
 const RECORDING_EXTENSION = '.aac';
 const RECORDING_SETTINGS = {
@@ -103,6 +104,7 @@ export default class RecordAudio extends React.PureComponent {
 	}
 
 	startRecordingAudio = async() => {
+		logEvent(events.ROOM_AUDIO_RECORD);
 		if (!this.isRecorderBusy) {
 			this.isRecorderBusy = true;
 			try {
@@ -120,13 +122,14 @@ export default class RecordAudio extends React.PureComponent {
 					await Audio.requestPermissionsAsync();
 				}
 			} catch (error) {
-				// Do nothing
+				logEvent(events.ROOM_AUDIO_RECORD_F);
 			}
 			this.isRecorderBusy = false;
 		}
 	};
 
 	finishRecordingAudio = async() => {
+		logEvent(events.ROOM_AUDIO_FINISH);
 		if (!this.isRecorderBusy) {
 			const { onFinish } = this.props;
 
@@ -147,7 +150,7 @@ export default class RecordAudio extends React.PureComponent {
 
 				onFinish(fileInfo);
 			} catch (error) {
-				// Do nothing
+				logEvent(events.ROOM_AUDIO_FINISH_F);
 			}
 			this.setState({ isRecording: false, recordingDurationMillis: 0 });
 			deactivateKeepAwake();
@@ -156,12 +159,13 @@ export default class RecordAudio extends React.PureComponent {
 	};
 
 	cancelRecordingAudio = async() => {
+		logEvent(events.ROOM_AUDIO_CANCEL);
 		if (!this.isRecorderBusy) {
 			this.isRecorderBusy = true;
 			try {
 				await this.recording.stopAndUnloadAsync();
 			} catch (error) {
-				// Do nothing
+				logEvent(events.ROOM_AUDIO_CANCEL_F);
 			}
 			this.setState({ isRecording: false, recordingDurationMillis: 0 });
 			deactivateKeepAwake();
diff --git a/app/containers/MessageBox/index.js b/app/containers/MessageBox/index.js
index 2d4a61944..0a4021b58 100644
--- a/app/containers/MessageBox/index.js
+++ b/app/containers/MessageBox/index.js
@@ -17,8 +17,8 @@ import RocketChat from '../../lib/rocketchat';
 import styles from './styles';
 import database from '../../lib/database';
 import { emojis } from '../../emojis';
+import log, { logEvent, events } from '../../utils/log';
 import RecordAudio from './RecordAudio';
-import log from '../../utils/log';
 import I18n from '../../i18n';
 import ReplyPreview from './ReplyPreview';
 import debounce from '../../utils/debounce';
@@ -585,37 +585,41 @@ class MessageBox extends Component {
 	}
 
 	takePhoto = async() => {
+		logEvent(events.ROOM_BOX_ACTION_PHOTO);
 		try {
 			const image = await ImagePicker.openCamera(this.imagePickerConfig);
 			if (this.canUploadFile(image)) {
 				this.openShareView([image]);
 			}
 		} catch (e) {
-			// Do nothing
+			logEvent(events.ROOM_BOX_ACTION_PHOTO_F);
 		}
 	}
 
 	takeVideo = async() => {
+		logEvent(events.ROOM_BOX_ACTION_VIDEO);
 		try {
 			const video = await ImagePicker.openCamera(this.videoPickerConfig);
 			if (this.canUploadFile(video)) {
 				this.openShareView([video]);
 			}
 		} catch (e) {
-			// Do nothing
+			logEvent(events.ROOM_BOX_ACTION_VIDEO_F);
 		}
 	}
 
 	chooseFromLibrary = async() => {
+		logEvent(events.ROOM_BOX_ACTION_LIBRARY);
 		try {
 			const attachments = await ImagePicker.openPicker(this.libraryPickerConfig);
 			this.openShareView(attachments);
 		} catch (e) {
-			// Do nothing
+			logEvent(events.ROOM_BOX_ACTION_LIBRARY_F);
 		}
 	}
 
 	chooseFile = async() => {
+		logEvent(events.ROOM_BOX_ACTION_FILE);
 		try {
 			const res = await DocumentPicker.pick({
 				type: [DocumentPicker.types.allFiles]
@@ -631,6 +635,7 @@ class MessageBox extends Component {
 			}
 		} catch (e) {
 			if (!DocumentPicker.isCancel(e)) {
+				logEvent(events.ROOM_BOX_ACTION_FILE_F);
 				log(e);
 			}
 		}
@@ -648,6 +653,7 @@ class MessageBox extends Component {
 	}
 
 	createDiscussion = () => {
+		logEvent(events.ROOM_BOX_ACTION_DISCUSSION);
 		const { isMasterDetail } = this.props;
 		const params = { channel: this.room, showCloseModal: true };
 		if (isMasterDetail) {
@@ -658,6 +664,7 @@ class MessageBox extends Component {
 	}
 
 	showMessageBoxActions = () => {
+		logEvent(events.ROOM_SHOW_BOX_ACTIONS);
 		const { showActionSheet } = this.props;
 		showActionSheet({ options: this.options });
 	}
@@ -668,10 +675,9 @@ class MessageBox extends Component {
 		this.clearInput();
 	}
 
-	openEmoji = async() => {
-		await this.setState({
-			showEmojiKeyboard: true
-		});
+	openEmoji = () => {
+		logEvent(events.ROOM_OPEN_EMOJI);
+		this.setState({ showEmojiKeyboard: true });
 	}
 
 	recordingCallback = (recording) => {
diff --git a/app/utils/log/events.js b/app/utils/log/events.js
index 6c5f16e67..6ef7ba4cb 100644
--- a/app/utils/log/events.js
+++ b/app/utils/log/events.js
@@ -43,6 +43,16 @@ export default {
 	SIDEBAR_NAVIGATE_TO_SETTINGS: 'sidebar_navigate_to_settings',
 	SIDEBAR_NAVIGATE_TO_ADMINPANEL: 'sidebar_navigate_to_admin_panel',
 
+	// STATUS VIEW
+	STATUS_DONE: 'status_done',
+	STATUS_ONLINE: 'status_online',
+	STATUS_BUSY: 'status_busy',
+	STATUS_AWAY: 'status_away',
+	STATUS_OFFLINE: 'status_offline',
+	STATUS_F: 'status_f',
+	STATUS_CUSTOM: 'status_custom',
+	STATUS_CUSTOM_F: 'status_custom_f',
+
 	// ROOMS LIST VIEW
 	RL_TOGGLE_SERVER_DROPDOWN: 'rl_toggle_server_dropdown',
 	RL_ADD_SERVER: 'rl_add_server',
@@ -62,7 +72,7 @@ export default {
 	RL_TOGGLE_SORT_DROPDOWN: 'rl_toggle_sort_dropdown',
 	RL_SORT_CHANNELS_BY_NAME: 'rl_sort_channels_by_name',
 	RL_SORT_CHANNELS_BY_ACTIVITY: 'rl_sort_channels_by_activity',
-	RL_SORT_CHANNELS_FAIL: 'rl_sort_channels_fail',
+	RL_SORT_CHANNELS_F: 'rl_sort_channels_f',
 	RL_GROUP_CHANNELS_BY_TYPE: 'rl_group_channels_by_type',
 	RL_GROUP_CHANNELS_BY_FAVORITE: 'rl_group_channels_by_favorite',
 	RL_GROUP_CHANNELS_BY_UNREAD: 'rl_group_channels_by_unread',
@@ -104,5 +114,84 @@ export default {
 	PROFILE_SAVE_AVATAR: 'profile_save_avatar',
 	PROFILE_SAVE_AVATAR_F: 'profile_save_avatar_f',
 	PROFILE_SAVE_CHANGES: 'profile_save_changes',
-	PROFILE_SAVE_CHANGES_F: 'profile_save_changes_f'
+	PROFILE_SAVE_CHANGES_F: 'profile_save_changes_f',
+
+	// SETTINGS VIEW
+	SE_CONTACT_US: 'se_contact_us',
+	SE_CONTACT_US_F: 'se_contact_us_f',
+	SE_NAVIGATE_TO_LANGUAGE: 'se_navigate_to_language',
+	SE_REVIEW_THIS_APP: 'se_review_this_app',
+	SE_REVIEW_THIS_APP_F: 'se_review_this_app_f',
+	SE_SHARE_THIS_APP: 'se_share_this_app',
+	SE_NAVIGATE_TO_DEFAULTBROWSER: 'se_navigate_to_default_browser',
+	SE_NAVIGATE_TO_THEME: 'se_navigate_to_theme',
+	SE_NAVIGATE_TO_SCREENLOCKCONFIG: 'se_navigate_to_screen_lock_cfg',
+	SE_NAVIGATE_TO_PROFILE: 'se_navigate_to_profile',
+	SE_READ_LICENSE: 'se_read_license',
+	SE_COPY_APP_VERSION: 'se_copy_app_version',
+	SE_COPY_SERVER_VERSION: 'se_copy_server_version',
+	SE_TOGGLE_CRASH_REPORT: 'se_toggle_crash_report',
+	SE_CLEAR_LOCAL_SERVER_CACHE: 'se_clear_local_server_cache',
+	SE_LOG_OUT: 'se_log_out',
+
+	// LANGUAGE VIEW
+	LANG_SET_LANGUAGE: 'lang_set_language',
+	LANG_SET_LANGUAGE_F: 'lang_set_language_f',
+
+	// DEFAULT BROWSER VIEW
+	DB_CHANGE_DEFAULT_BROWSER: 'db_change_default_browser',
+	DB_CHANGE_DEFAULT_BROWSER_F: 'db_change_default_browser_f',
+
+	// THEME VIEW
+	THEME_SET_THEME_GROUP: 'theme_set_theme_group',
+	THEME_SET_DARK_LEVEL: 'theme_set_dark_level',
+
+	// SCREEN LOCK CONFIG VIEW
+	SLC_SAVE_SCREEN_LOCK: 'slc_save_screen_lock',
+	SLC_TOGGLE_AUTOLOCK: 'slc_toggle_autolock',
+	SLC_TOGGLE_BIOMETRY: 'slc_toggle_biometry',
+	SLC_CHANGE_PASSCODE: 'slc_change_passcode',
+	SLC_CHANGE_AUTOLOCK_TIME: 'slc_change_autolock_time',
+
+	// ROOM VIEW
+	ROOM_SEND_MESSAGE: 'room_send_message',
+	ROOM_OPEN_EMOJI: 'room_open_emoji',
+	ROOM_AUDIO_RECORD: 'room_audio_record',
+	ROOM_AUDIO_RECORD_F: 'room_audio_record_f',
+	ROOM_AUDIO_FINISH: 'room_audio_finish',
+	ROOM_AUDIO_FINISH_F: 'room_audio_finish_f',
+	ROOM_AUDIO_CANCEL: 'room_audio_cancel',
+	ROOM_AUDIO_CANCEL_F: 'room_audio_cancel_f',
+	ROOM_SHOW_BOX_ACTIONS: 'room_show_box_actions',
+	ROOM_BOX_ACTION_PHOTO: 'room_box_action_photo',
+	ROOM_BOX_ACTION_PHOTO_F: 'room_box_action_photo_f',
+	ROOM_BOX_ACTION_VIDEO: 'room_box_action_video',
+	ROOM_BOX_ACTION_VIDEO_F: 'room_box_action_video_f',
+	ROOM_BOX_ACTION_LIBRARY: 'room_box_action_library',
+	ROOM_BOX_ACTION_LIBRARY_F: 'room_box_action_library_f',
+	ROOM_BOX_ACTION_FILE: 'room_box_action_file',
+	ROOM_BOX_ACTION_FILE_F: 'room_box_action_file_f',
+	ROOM_BOX_ACTION_DISCUSSION: 'room_box_action_discussion',
+	ROOM_SHOW_MSG_ACTIONS: 'room_show_msg_actions',
+	ROOM_MSG_ACTION_REPLY: 'room_msg_action_reply',
+	ROOM_MSG_ACTION_QUOTE: 'room_msg_action_quote',
+	ROOM_MSG_ACTION_EDIT: 'room_msg_action_edit',
+	ROOM_MSG_ACTION_DELETE: 'room_msg_action_delete',
+	ROOM_MSG_ACTION_DELETE_F: 'room_msg_action_delete_f',
+	ROOM_MSG_ACTION_PERMALINK: 'room_msg_action_permalink',
+	ROOM_MSG_ACTION_PERMALINK_F: 'room_msg_action_permalink_f',
+	ROOM_MSG_ACTION_DISCUSSION: 'room_msg_action_discussion',
+	ROOM_MSG_ACTION_UNREAD: 'room_msg_action_unread',
+	ROOM_MSG_ACTION_UNREAD_F: 'room_msg_action_unread_f',
+	ROOM_MSG_ACTION_COPY: 'room_msg_action_copy',
+	ROOM_MSG_ACTION_SHARE: 'room_msg_action_share',
+	ROOM_MSG_ACTION_SHARE_F: 'room_msg_action_share_f',
+	ROOM_MSG_ACTION_STAR: 'room_msg_action_star',
+	ROOM_MSG_ACTION_UNSTAR: 'room_msg_action_unstar',
+	ROOM_MSG_ACTION_STAR_F: 'room_msg_action_star_f',
+	ROOM_MSG_ACTION_PIN: 'room_msg_action_pin',
+	ROOM_MSG_ACTION_PIN_F: 'room_msg_action_pin_f',
+	ROOM_MSG_ACTION_REACTION: 'room_msg_action_reaction',
+	ROOM_MSG_ACTION_REPORT: 'room_msg_action_report',
+	ROOM_MSG_ACTION_REPORT_F: 'room_msg_action_report_f'
 };
diff --git a/app/utils/review.js b/app/utils/review.js
index 1c38f67c8..17ba73c90 100644
--- a/app/utils/review.js
+++ b/app/utils/review.js
@@ -5,6 +5,7 @@ import { isIOS } from './deviceInfo';
 import I18n from '../i18n';
 import { showErrorAlert } from './info';
 import { STORE_REVIEW_LINK } from '../constants/links';
+import { logEvent, events } from './log';
 
 const store = isIOS ? 'App Store' : 'Play Store';
 
@@ -31,6 +32,7 @@ const onCancelPress = () => {
 };
 
 export const onReviewPress = async() => {
+	logEvent(events.SE_REVIEW_THIS_APP);
 	await onCancelPress();
 	try {
 		const supported = await Linking.canOpenURL(STORE_REVIEW_LINK);
@@ -38,6 +40,7 @@ export const onReviewPress = async() => {
 			Linking.openURL(STORE_REVIEW_LINK);
 		}
 	} catch (e) {
+		logEvent(events.SE_REVIEW_THIS_APP_F);
 		showErrorAlert(I18n.t('Review_app_unable_store', { store }));
 	}
 };
diff --git a/app/views/DefaultBrowserView.js b/app/views/DefaultBrowserView.js
index d0b9597ef..555301b0c 100644
--- a/app/views/DefaultBrowserView.js
+++ b/app/views/DefaultBrowserView.js
@@ -16,6 +16,7 @@ import { CustomIcon } from '../lib/Icons';
 import { DEFAULT_BROWSER_KEY } from '../utils/openLink';
 import { isIOS } from '../utils/deviceInfo';
 import SafeAreaView from '../containers/SafeAreaView';
+import { logEvent, events } from '../utils/log';
 
 const DEFAULT_BROWSERS = [
 	{
@@ -113,12 +114,13 @@ class DefaultBrowserView extends React.Component {
 	}
 
 	changeDefaultBrowser = async(newBrowser) => {
+		logEvent(events.DB_CHANGE_DEFAULT_BROWSER, { browser: newBrowser });
 		try {
 			const browser = newBrowser !== 'inApp' ? newBrowser : null;
 			await RNUserDefaults.set(DEFAULT_BROWSER_KEY, browser);
 			this.setState({ browser });
 		} catch {
-			// do nothing
+			logEvent(events.DB_CHANGE_DEFAULT_BROWSER_F);
 		}
 	}
 
diff --git a/app/views/LanguageView/index.js b/app/views/LanguageView/index.js
index 640602d83..8a5eac1dd 100644
--- a/app/views/LanguageView/index.js
+++ b/app/views/LanguageView/index.js
@@ -6,7 +6,7 @@ import { connect } from 'react-redux';
 import RocketChat from '../../lib/rocketchat';
 import I18n from '../../i18n';
 import { showErrorAlert } from '../../utils/info';
-import log from '../../utils/log';
+import log, { logEvent, events } from '../../utils/log';
 import { setUser as setUserAction } from '../../actions/login';
 import StatusBar from '../../containers/StatusBar';
 import { CustomIcon } from '../../lib/Icons';
@@ -112,6 +112,7 @@ class LanguageView extends React.Component {
 	}
 
 	changeLanguage = async(language) => {
+		logEvent(events.LANG_SET_LANGUAGE);
 		const { user, setUser } = this.props;
 
 		const params = {};
@@ -134,10 +135,11 @@ class LanguageView extends React.Component {
 						record.language = params.language;
 					});
 				} catch (e) {
-					// do nothing
+					logEvent(events.LANG_SET_LANGUAGE_F);
 				}
 			});
 		} catch (e) {
+			logEvent(events.LANG_SET_LANGUAGE_F);
 			showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t('saving_preferences') }));
 			log(e);
 		}
diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js
index 4a54117dd..d68aca41b 100644
--- a/app/views/RoomView/index.js
+++ b/app/views/RoomView/index.js
@@ -24,7 +24,7 @@ import MessageBox from '../../containers/MessageBox';
 import ReactionPicker from './ReactionPicker';
 import UploadProgress from './UploadProgress';
 import styles from './styles';
-import log from '../../utils/log';
+import log, { logEvent, events } from '../../utils/log';
 import EventEmitter from '../../utils/events';
 import I18n from '../../i18n';
 import RoomHeaderView, { RightButtons, LeftButtons } from './Header';
@@ -644,6 +644,7 @@ class RoomView extends React.Component {
 	}
 
 	sendMessage = (message, tmid) => {
+		logEvent(events.ROOM_SEND_MESSAGE);
 		const { user } = this.props;
 		RocketChat.sendMessage(this.rid, message, this.tmid || tmid, user).then(() => {
 			if (this.list && this.list.current) {
diff --git a/app/views/RoomsListView/SortDropdown/index.js b/app/views/RoomsListView/SortDropdown/index.js
index 75cc2cec8..f50c939d7 100644
--- a/app/views/RoomsListView/SortDropdown/index.js
+++ b/app/views/RoomsListView/SortDropdown/index.js
@@ -65,7 +65,7 @@ class Sort extends PureComponent {
 			setSortPreference(param);
 			RocketChat.saveSortPreference(param);
 		} catch (e) {
-			logEvent(events.RL_SORT_CHANNELS_FAIL);
+			logEvent(events.RL_SORT_CHANNELS_F);
 			log(e);
 		}
 	}
diff --git a/app/views/ScreenLockConfigView.js b/app/views/ScreenLockConfigView.js
index f235f6caf..a1d60e07f 100644
--- a/app/views/ScreenLockConfigView.js
+++ b/app/views/ScreenLockConfigView.js
@@ -16,6 +16,7 @@ import { supportedBiometryLabel, changePasscode, checkHasPasscode } from '../uti
 import { DisclosureImage } from '../containers/DisclosureIndicator';
 import { DEFAULT_AUTO_LOCK } from '../constants/localAuthentication';
 import SafeAreaView from '../containers/SafeAreaView';
+import { events, logEvent } from '../utils/log';
 
 const styles = StyleSheet.create({
 	listPadding: {
@@ -113,6 +114,7 @@ class ScreenLockConfigView extends React.Component {
 	}
 
 	save = async() => {
+		logEvent(events.SLC_SAVE_SCREEN_LOCK);
 		const { autoLock, autoLockTime, biometry } = this.state;
 		const serversDB = database.servers;
 		await serversDB.action(async() => {
@@ -125,10 +127,12 @@ class ScreenLockConfigView extends React.Component {
 	}
 
 	changePasscode = async({ force }) => {
+		logEvent(events.SLC_CHANGE_PASSCODE);
 		await changePasscode({ force });
 	}
 
 	toggleAutoLock = () => {
+		logEvent(events.SLC_TOGGLE_AUTOLOCK);
 		this.setState(({ autoLock }) => ({ autoLock: !autoLock, autoLockTime: DEFAULT_AUTO_LOCK }), async() => {
 			const { autoLock } = this.state;
 			if (autoLock) {
@@ -143,6 +147,7 @@ class ScreenLockConfigView extends React.Component {
 	}
 
 	toggleBiometry = () => {
+		logEvent(events.SLC_TOGGLE_BIOMETRY);
 		this.setState(({ biometry }) => ({ biometry: !biometry }), () => this.save());
 	}
 
@@ -152,6 +157,7 @@ class ScreenLockConfigView extends React.Component {
 	}
 
 	changeAutoLockTime = (autoLockTime) => {
+		logEvent(events.SLC_CHANGE_AUTOLOCK_TIME);
 		this.setState({ autoLockTime }, () => this.save());
 	}
 
diff --git a/app/views/SelectedUsersView.js b/app/views/SelectedUsersView.js
index 2856f0331..396728a86 100644
--- a/app/views/SelectedUsersView.js
+++ b/app/views/SelectedUsersView.js
@@ -183,7 +183,6 @@ class SelectedUsersView extends React.Component {
 			if (this.isGroupChat() && users.length === maxUsers) {
 				return showErrorAlert(I18n.t('Max_number_of_users_allowed_is_number', { maxUsers }), I18n.t('Oops'));
 			}
-
 			logEvent(events.SELECTED_USERS_ADD_USER);
 			addUser(user);
 		} else {
diff --git a/app/views/SettingsView/index.js b/app/views/SettingsView/index.js
index cee79fa92..a3617623f 100644
--- a/app/views/SettingsView/index.js
+++ b/app/views/SettingsView/index.js
@@ -26,7 +26,9 @@ import openLink from '../../utils/openLink';
 import scrollPersistTaps from '../../utils/scrollPersistTaps';
 import { showErrorAlert, showConfirmationAlert } from '../../utils/info';
 import styles from './styles';
-import { loggerConfig, analytics } from '../../utils/log';
+import {
+	loggerConfig, analytics, logEvent, events
+} from '../../utils/log';
 import { PLAY_MARKET_LINK, APP_STORE_LINK, LICENSE_LINK } from '../../constants/links';
 import { withTheme } from '../../theme';
 import SidebarView from '../SidebarView';
@@ -86,6 +88,7 @@ class SettingsView extends React.Component {
 	}
 
 	handleLogout = () => {
+		logEvent(events.SE_LOG_OUT);
 		showConfirmationAlert({
 			message: I18n.t('You_will_be_logged_out_of_this_application'),
 			callToAction: I18n.t('Logout'),
@@ -97,6 +100,7 @@ class SettingsView extends React.Component {
 	}
 
 	handleClearCache = () => {
+		logEvent(events.SE_CLEAR_LOCAL_SERVER_CACHE);
 		showConfirmationAlert({
 			message: I18n.t('This_will_clear_all_your_offline_data'),
 			callToAction: I18n.t('Clear'),
@@ -114,12 +118,12 @@ class SettingsView extends React.Component {
 	}
 
 	toggleCrashReport = (value) => {
+		logEvent(events.SE_TOGGLE_CRASH_REPORT);
 		AsyncStorage.setItem(CRASH_REPORT_KEY, JSON.stringify(value));
 		const { toggleCrashReport } = this.props;
 		toggleCrashReport(value);
 		loggerConfig.autoNotify = value;
 		analytics().setAnalyticsCollectionEnabled(value);
-
 		if (value) {
 			loggerConfig.clearBeforeSendCallbacks();
 		} else {
@@ -136,11 +140,13 @@ class SettingsView extends React.Component {
 	}
 
 	navigateToScreen = (screen) => {
+		logEvent(events[`SE_NAVIGATE_TO_${ screen.replace('View', '').toUpperCase() }`]);
 		const { navigation } = this.props;
 		navigation.navigate(screen);
 	}
 
 	sendEmail = async() => {
+		logEvent(events.SE_CONTACT_US);
 		const subject = encodeURI('React Native App Support');
 		const email = encodeURI('support@rocket.chat');
 		const description = encodeURI(`
@@ -150,20 +156,24 @@ class SettingsView extends React.Component {
 		try {
 			await Linking.openURL(`mailto:${ email }?subject=${ subject }&body=${ description }`);
 		} catch (e) {
+			logEvent(events.SE_CONTACT_US_F);
 			showErrorAlert(I18n.t('error-email-send-failed', { message: 'support@rocket.chat' }));
 		}
 	}
 
 	shareApp = () => {
+		logEvent(events.SE_SHARE_THIS_APP);
 		Share.share({ message: isAndroid ? PLAY_MARKET_LINK : APP_STORE_LINK });
 	}
 
 	copyServerVersion = () => {
-		const { server } = this.props;
-		this.saveToClipboard(server.version);
+		const { server: { version } } = this.props;
+		logEvent(events.SE_COPY_SERVER_VERSION, { serverVersion: version });
+		this.saveToClipboard(version);
 	}
 
 	copyAppVersion = () => {
+		logEvent(events.SE_COPY_APP_VERSION, { appVersion: getReadableVersion });
 		this.saveToClipboard(getReadableVersion);
 	}
 
@@ -173,6 +183,7 @@ class SettingsView extends React.Component {
 	}
 
 	onPressLicense = () => {
+		logEvent(events.SE_READ_LICENSE);
 		const { theme } = this.props;
 		openLink(LICENSE_LINK, theme);
 	}
diff --git a/app/views/StatusView.js b/app/views/StatusView.js
index 5676e0bb0..4cc2fa80d 100644
--- a/app/views/StatusView.js
+++ b/app/views/StatusView.js
@@ -11,7 +11,7 @@ import TextInput from '../containers/TextInput';
 import EventEmitter from '../utils/events';
 import Loading from '../containers/Loading';
 import RocketChat from '../lib/rocketchat';
-import log from '../utils/log';
+import log, { logEvent, events } from '../utils/log';
 
 import { LISTENER } from '../containers/Toast';
 import { themes } from '../constants/colors';
@@ -92,6 +92,7 @@ class StatusView extends React.Component {
 	}
 
 	submit = async() => {
+		logEvent(events.STATUS_DONE);
 		const { statusText } = this.state;
 		const { user } = this.props;
 		if (statusText !== user.statusText) {
@@ -114,11 +115,14 @@ class StatusView extends React.Component {
 		try {
 			const result = await RocketChat.setUserStatus(user.status, statusText);
 			if (result.success) {
+				logEvent(events.STATUS_CUSTOM);
 				EventEmitter.emit(LISTENER, { message: I18n.t('Status_saved_successfully') });
 			} else {
+				logEvent(events.STATUS_CUSTOM_F);
 				EventEmitter.emit(LISTENER, { message: I18n.t('error-could-not-change-status') });
 			}
 		} catch {
+			logEvent(events.STATUS_CUSTOM_F);
 			EventEmitter.emit(LISTENER, { message: I18n.t('error-could-not-change-status') });
 		}
 
@@ -166,6 +170,7 @@ class StatusView extends React.Component {
 			<ListItem
 				title={I18n.t(name)}
 				onPress={async() => {
+					logEvent(events[`STATUS_${ item.id.toUpperCase() }`]);
 					if (user.status !== item.id) {
 						try {
 							const result = await RocketChat.setUserStatus(item.id, statusText);
@@ -173,6 +178,7 @@ class StatusView extends React.Component {
 								store.dispatch(setUser({ status: item.id }));
 							}
 						} catch (e) {
+							logEvent(events.SET_STATUS_FAIL);
 							log(e);
 						}
 					}
diff --git a/app/views/ThemeView.js b/app/views/ThemeView.js
index f6c4f96cb..0c8e2e625 100644
--- a/app/views/ThemeView.js
+++ b/app/views/ThemeView.js
@@ -16,6 +16,7 @@ import { CustomIcon } from '../lib/Icons';
 import { THEME_PREFERENCES_KEY } from '../lib/rocketchat';
 import { supportSystemTheme } from '../utils/deviceInfo';
 import SafeAreaView from '../containers/SafeAreaView';
+import { events, logEvent } from '../utils/log';
 
 const THEME_GROUP = 'THEME_GROUP';
 const DARK_GROUP = 'DARK_GROUP';
@@ -96,9 +97,11 @@ class ThemeView extends React.Component {
 		const { value, group } = item;
 		let changes = {};
 		if (group === THEME_GROUP && currentTheme !== value) {
+			logEvent(events.THEME_SET_THEME_GROUP, { theme_group: value });
 			changes = { currentTheme: value };
 		}
 		if (group === DARK_GROUP && darkLevel !== value) {
+			logEvent(events.THEME_SET_DARK_LEVEL, { dark_level: value });
 			changes = { darkLevel: value };
 		}
 		this.setTheme(changes);