forked from Ivasoft/mattermost-mobile
Gekidou Sentry Installation (#6726)
* Sentry - Clean Install * Update config.yml * update CI to install Sentry CLI * update CI to install Sentry CLI * Squashed commit of the following: commite1996e59deMerge:87cc8d6f22e8352f3eAuthor: Avinash Lingaloo <avinashlng1080@gmail.com> Date: Fri Nov 4 20:59:29 2022 +0400 Merge branch 'android-pr-sentry-clean' of https://github.com/mattermost/mattermost-mobile into android-pr-sentry-clean commit2e8352f3e1Author: Elias Nahum <nahumhbl@gmail.com> Date: Fri Nov 4 15:48:24 2022 +0200 update CI to install Sentry CLI commit87cc8d6f2bAuthor: Elias Nahum <nahumhbl@gmail.com> Date: Fri Nov 4 15:48:24 2022 +0200 update CI to install Sentry CLI commit8dca885a02Author: Avinash Lingaloo <avinashlng1080@gmail.com> Date: Fri Nov 4 16:48:47 2022 +0400 Update config.yml commit684bbb4aefAuthor: Mylon Suren <23694620+mylonsuren@users.noreply.github.com> Date: Thu Nov 3 11:37:58 2022 -0400 Remove down arrow next to team name and make team name unclickable (#6715) commit88ff8fac30Author: Jason Frerich <jason.frerich@mattermost.com> Date: Wed Nov 2 19:35:23 2022 -0500 [Bug] Emit boolean with "of" operator (#6729) commitdebcc99480Author: Jason Frerich <jason.frerich@mattermost.com> Date: Wed Nov 2 12:15:54 2022 -0500 [Gekidou MM-48006] Show keyboard when select a modifier (#6714) * Delete @sentry+react-native+4.6.1.patch * correction from PR review * Add logError to DatabaseManager * removes sentry context from android build job * removes team+channel data * shift active server listener to home/index * Revert "shift active server listener to home/index" This reverts commit75e26faadd. * refactor after PR Review Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
This commit is contained in:
@@ -111,7 +111,9 @@ commands:
|
||||
key: v2-npm-{{ checksum "package.json" }}-{{ arch }}
|
||||
- run:
|
||||
name: Getting JavaScript dependencies
|
||||
command: NODE_ENV=development npm ci --ignore-scripts
|
||||
command: |
|
||||
NODE_ENV=development npm ci --ignore-scripts
|
||||
node node_modules/\@sentry/cli/scripts/install.js
|
||||
- save_cache:
|
||||
name: Save npm cache
|
||||
key: v2-npm-{{ checksum "package.json" }}-{{ arch }}
|
||||
|
||||
@@ -110,7 +110,7 @@ class DatabaseManager {
|
||||
|
||||
return this.appDatabase;
|
||||
} catch (e) {
|
||||
// TODO : report to sentry? Show something on the UI ?
|
||||
logError('Unable to create the App Database!!', e);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
@@ -164,8 +164,6 @@ class DatabaseManager {
|
||||
|
||||
return serverDatabase;
|
||||
} catch (e) {
|
||||
// TODO : report to sentry? Show something on the UI ?
|
||||
|
||||
logError('Error initializing database', e);
|
||||
}
|
||||
}
|
||||
@@ -249,7 +247,7 @@ class DatabaseManager {
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// TODO : report to sentry? Show something on the UI ?
|
||||
logError('Error adding server to App database', e);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -12,10 +12,12 @@ import {Edge, SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-cont
|
||||
import FreezeScreen from '@components/freeze_screen';
|
||||
import TeamSidebar from '@components/team_sidebar';
|
||||
import {Navigation as NavigationConstants, Screens} from '@constants';
|
||||
import {useServerUrl} from '@context/server';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {useIsTablet} from '@hooks/device';
|
||||
import {resetToTeams} from '@screens/navigation';
|
||||
import NavigationStore from '@store/navigation_store';
|
||||
import {addSentryContext} from '@utils/sentry';
|
||||
|
||||
import AdditionalTabletView from './additional_tablet_view';
|
||||
import CategoriesList from './categories_list';
|
||||
@@ -50,6 +52,7 @@ const ChannelListScreen = (props: ChannelProps) => {
|
||||
const isFocused = useIsFocused();
|
||||
const navigation = useNavigation();
|
||||
const insets = useSafeAreaInsets();
|
||||
const serverUrl = useServerUrl();
|
||||
const params = route.params as {direction: string};
|
||||
const canAddOtherServers = managedConfig?.allowOtherServers !== 'false';
|
||||
|
||||
@@ -111,6 +114,10 @@ const ChannelListScreen = (props: ChannelProps) => {
|
||||
return () => back.remove();
|
||||
}, [handleBackPress]);
|
||||
|
||||
useEffect(() => {
|
||||
addSentryContext(serverUrl);
|
||||
}, [serverUrl]);
|
||||
|
||||
return (
|
||||
<FreezeScreen freeze={!isFocused}>
|
||||
{<Animated.View style={top}/>}
|
||||
|
||||
@@ -1,22 +1,39 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import keyMirror from '@utils/key_mirror';
|
||||
|
||||
const SentryLevels = keyMirror({debug: null, info: null, warning: null, error: null});
|
||||
|
||||
export function logError(...args: any[]) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(...args);
|
||||
addBreadcrumb(SentryLevels.error, ...args);
|
||||
}
|
||||
|
||||
export function logWarning(...args: any[]) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(...args);
|
||||
addBreadcrumb(SentryLevels.warning, ...args);
|
||||
}
|
||||
|
||||
export function logInfo(...args: any[]) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(...args);
|
||||
addBreadcrumb(SentryLevels.info, ...args);
|
||||
}
|
||||
|
||||
export function logDebug(...args: any[]) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug(...args);
|
||||
addBreadcrumb(SentryLevels.debug, ...args);
|
||||
}
|
||||
|
||||
const addBreadcrumb = (logLevel: keyof typeof SentryLevels, ...args: any[]) => {
|
||||
const Sentry = require('@sentry/react-native');
|
||||
Sentry.addBreadcrumb({
|
||||
level: logLevel,
|
||||
message: args.join(','),
|
||||
type: 'console-log',
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Database} from '@nozbe/watermelondb';
|
||||
import {Breadcrumb} from '@sentry/types';
|
||||
import {Platform} from 'react-native';
|
||||
import {Navigation} from 'react-native-navigation';
|
||||
|
||||
import Config from '@assets/config.json';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import {getConfig} from '@queries/servers/system';
|
||||
import {getCurrentUser} from '@queries/servers/user';
|
||||
|
||||
import {ClientError} from './client_error';
|
||||
import {logError, logWarning} from './log';
|
||||
import {logWarning} from './log';
|
||||
|
||||
export const BREADCRUMB_UNCAUGHT_APP_ERROR = 'uncaught-app-error';
|
||||
export const BREADCRUMB_UNCAUGHT_NON_ERROR = 'uncaught-non-error';
|
||||
@@ -17,6 +22,7 @@ export const LOGGER_JAVASCRIPT_WARNING = 'javascript_warning';
|
||||
export const LOGGER_NATIVE = 'native';
|
||||
|
||||
let Sentry: any;
|
||||
|
||||
export function initializeSentry() {
|
||||
if (!Config.SentryEnabled) {
|
||||
return;
|
||||
@@ -33,7 +39,21 @@ export function initializeSentry() {
|
||||
return;
|
||||
}
|
||||
|
||||
Sentry.init({dsn, ...Config.SentryOptions});
|
||||
Sentry.init({
|
||||
dsn,
|
||||
tracesSampleRate: 0.2,
|
||||
integrations: [
|
||||
new Sentry.ReactNativeTracing({
|
||||
|
||||
// Pass instrumentation to be used as `routingInstrumentation`
|
||||
routingInstrumentation: new Sentry.ReactNativeNavigationInstrumentation(
|
||||
Navigation,
|
||||
),
|
||||
}),
|
||||
],
|
||||
sendDefaultPii: false,
|
||||
...Config.SentryOptions,
|
||||
});
|
||||
}
|
||||
|
||||
function getDsn() {
|
||||
@@ -55,12 +75,7 @@ export function captureException(error: Error | string, logger: string) {
|
||||
logWarning('captureException called with missing arguments', error, logger);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Get current server config and other relevant data
|
||||
|
||||
capture(() => {
|
||||
Sentry.captureException(error, {logger});
|
||||
});
|
||||
Sentry.captureException(error, {logger});
|
||||
}
|
||||
|
||||
export function captureJSException(error: Error | ClientError, isFatal: boolean) {
|
||||
@@ -120,128 +135,70 @@ function captureClientErrorAsBreadcrumb(error: ClientError, isFatal: boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper function to any calls to Sentry so that we can gather any necessary extra data
|
||||
// before sending.
|
||||
function capture(captureFunc: () => void, config?: ClientConfig) {
|
||||
if (config?.EnableDiagnostics !== 'true') {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let hasUserContext = false;
|
||||
const userContext = getUserContext();
|
||||
if (userContext) {
|
||||
hasUserContext = true;
|
||||
Sentry.setUserContext(userContext);
|
||||
}
|
||||
|
||||
const extraContext = getExtraContext();
|
||||
if (Object.keys(extraContext).length) {
|
||||
Sentry.setExtraContext(extraContext);
|
||||
}
|
||||
|
||||
const buildTags = getBuildTags();
|
||||
if (buildTags) {
|
||||
Sentry.setTagsContext(buildTags);
|
||||
}
|
||||
|
||||
if (hasUserContext) {
|
||||
logWarning('Capturing with Sentry at ' + getDsn() + '...');
|
||||
|
||||
captureFunc();
|
||||
} else {
|
||||
logWarning('No user context, skipping capture');
|
||||
}
|
||||
} catch (e) {
|
||||
// Don't want this to get into an infinite loop again...
|
||||
logError('Exception occurred while sending to Sentry');
|
||||
logError(e);
|
||||
}
|
||||
}
|
||||
|
||||
function getUserContext() {
|
||||
// TODO: Get current user data from active database
|
||||
const getUserContext = async (database: Database) => {
|
||||
const currentUser = {
|
||||
id: 'currentUserId',
|
||||
locale: 'en',
|
||||
roles: 'multi-server-test-role',
|
||||
};
|
||||
|
||||
if (!currentUser) {
|
||||
return null;
|
||||
}
|
||||
const user = await getCurrentUser(database);
|
||||
|
||||
return {
|
||||
userID: currentUser.id, // This can be changed to id after we upgrade to Sentry >= 0.14.10,
|
||||
userID: user?.id ?? currentUser.id,
|
||||
email: '',
|
||||
username: '',
|
||||
extra: {
|
||||
locale: currentUser.locale,
|
||||
roles: currentUser.roles,
|
||||
},
|
||||
locale: user?.locale ?? currentUser.locale,
|
||||
roles: user?.roles ?? currentUser.roles,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
function getExtraContext() {
|
||||
const context = {};
|
||||
const getExtraContext = async (database: Database) => {
|
||||
const context = {
|
||||
config: {},
|
||||
currentChannel: {},
|
||||
currentTeam: {},
|
||||
};
|
||||
|
||||
// TODO: Add context based on the active database
|
||||
|
||||
// const currentTeam = getCurrentTeam(state);
|
||||
// if (currentTeam) {
|
||||
// context.currentTeam = {
|
||||
// id: currentTeam.id,
|
||||
// };
|
||||
// }
|
||||
|
||||
// const currentTeamMember = getCurrentTeamMembership(state);
|
||||
// if (currentTeamMember) {
|
||||
// context.currentTeamMember = {
|
||||
// roles: currentTeamMember.roles,
|
||||
// };
|
||||
// }
|
||||
|
||||
// const currentChannel = getCurrentChannel(state);
|
||||
// if (currentChannel) {
|
||||
// context.currentChannel = {
|
||||
// id: currentChannel.id,
|
||||
// type: currentChannel.type,
|
||||
// };
|
||||
// }
|
||||
|
||||
// const currentChannelMember = getMyCurrentChannelMembership(state);
|
||||
// if (currentChannelMember) {
|
||||
// context.currentChannelMember = {
|
||||
// roles: currentChannelMember.roles,
|
||||
// };
|
||||
// }
|
||||
|
||||
// const config = getConfig(state);
|
||||
// if (config) {
|
||||
// context.config = {
|
||||
// BuildDate: config.BuildDate,
|
||||
// BuildEnterpriseReady: config.BuildEnterpriseReady,
|
||||
// BuildHash: config.BuildHash,
|
||||
// BuildHashEnterprise: config.BuildHashEnterprise,
|
||||
// BuildNumber: config.BuildNumber,
|
||||
// };
|
||||
// }
|
||||
const config = await getConfig(database);
|
||||
if (config) {
|
||||
context.config = {
|
||||
BuildDate: config.BuildDate,
|
||||
BuildEnterpriseReady: config.BuildEnterpriseReady,
|
||||
BuildHash: config.BuildHash,
|
||||
BuildHashEnterprise: config.BuildHashEnterprise,
|
||||
BuildNumber: config.BuildNumber,
|
||||
};
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
};
|
||||
|
||||
function getBuildTags() {
|
||||
let tags;
|
||||
const getBuildTags = async (database: Database) => {
|
||||
const tags = {
|
||||
serverBuildHash: '',
|
||||
serverBuildNumber: '',
|
||||
};
|
||||
|
||||
// TODO: Add context based on the active database
|
||||
|
||||
// const config = getConfig(state);
|
||||
// if (config) {
|
||||
// tags = {
|
||||
// serverBuildHash: config.BuildHash,
|
||||
// serverBuildNumber: config.BuildNumber,
|
||||
// };
|
||||
// }
|
||||
const config = await getConfig(database);
|
||||
if (config) {
|
||||
tags.serverBuildHash = config.BuildHash;
|
||||
tags.serverBuildNumber = config.BuildNumber;
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
};
|
||||
|
||||
export const addSentryContext = async (serverUrl: string) => {
|
||||
const database = DatabaseManager.serverDatabases[serverUrl]?.database;
|
||||
if (database) {
|
||||
const userContext = await getUserContext(database);
|
||||
Sentry.setContext('User-Information', userContext);
|
||||
|
||||
const buildContext = await getBuildTags(database);
|
||||
Sentry.setContext('App-Build Information', buildContext);
|
||||
|
||||
const extraContext = await getExtraContext(database);
|
||||
Sentry.setContext('Server-Information', extraContext);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -12,7 +12,8 @@ if [[ "${SENTRY_ENABLED}" = "true" ]]; then
|
||||
./makeSentryProperties.sh
|
||||
|
||||
export SENTRY_PROPERTIES=sentry.properties
|
||||
../node_modules/@sentry/cli/bin/sentry-cli react-native xcode ./react-native-xcode.sh
|
||||
../node_modules/@sentry/cli/bin/sentry-cli react-native xcode \
|
||||
../node_modules/react-native/scripts/react-native-xcode.sh
|
||||
else
|
||||
echo "Sentry native integration is not enabled"
|
||||
../node_modules/react-native/scripts/react-native-xcode.sh
|
||||
|
||||
@@ -6,7 +6,8 @@ if [[ "${SENTRY_ENABLED}" = "true" ]]; then
|
||||
./makeSentryProperties.sh
|
||||
|
||||
export SENTRY_PROPERTIES=sentry.properties
|
||||
../node_modules/@sentry/cli/bin/sentry-cli upload-dsym
|
||||
../node_modules/@sentry/cli/bin/sentry-cli upload-dif "$DWARF_DSYM_FOLDER_PATH"
|
||||
|
||||
else
|
||||
echo "Not uploading debugging symbols to Sentry because Sentry is disabled"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user