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:
commit e1996e59de8e135b19957dc9b0a0677f8b851c8b
Merge: 87cc8d6f2 2e8352f3e
Author: 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
commit 2e8352f3e15527c73ec3a634eae32b29aa6a9faf
Author: Elias Nahum <nahumhbl@gmail.com>
Date: Fri Nov 4 15:48:24 2022 +0200
update CI to install Sentry CLI
commit 87cc8d6f2b06945a4d0a2d4373836fd261b62c15
Author: Elias Nahum <nahumhbl@gmail.com>
Date: Fri Nov 4 15:48:24 2022 +0200
update CI to install Sentry CLI
commit 8dca885a0204c894bfcf544807976bac766b3b99
Author: Avinash Lingaloo <avinashlng1080@gmail.com>
Date: Fri Nov 4 16:48:47 2022 +0400
Update config.yml
commit 684bbb4aef
Author: 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)
commit 88ff8fac30
Author: Jason Frerich <jason.frerich@mattermost.com>
Date: Wed Nov 2 19:35:23 2022 -0500
[Bug] Emit boolean with "of" operator (#6729)
commit debcc99480
Author: 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 commit 75e26faadd8c4359dd4d02c30375c03fadcc91bd.
* refactor after PR Review
Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
This commit is contained in:
parent
25ddc894f2
commit
987d024708
7 changed files with 104 additions and 121 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue