Automatic error reporting ()

* Enable sentry global handlers if automaticErrorReporting is on

* Pass the exception through on session restore error

Passing the exception object itself through to the BugReportDialog means a stack trace can be correctly recorded in Sentry
This commit is contained in:
James Salter 2021-10-29 09:34:25 +01:00 committed by GitHub
parent d0bb6e0657
commit 3defb863b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 37 additions and 12 deletions
src

View file

@ -59,6 +59,7 @@ import SessionRestoreErrorDialog from "./components/views/dialogs/SessionRestore
import StorageEvictedDialog from "./components/views/dialogs/StorageEvictedDialog";
import { logger } from "matrix-js-sdk/src/logger";
import { setSentryUser } from "./sentry";
const HOMESERVER_URL_KEY = "mx_hs_url";
const ID_SERVER_URL_KEY = "mx_is_url";
@ -455,7 +456,7 @@ async function handleLoadSessionFailure(e: Error): Promise<boolean> {
logger.error("Unable to load session", e);
const modal = Modal.createTrackedDialog('Session Restore Error', '', SessionRestoreErrorDialog, {
error: e.message,
error: e,
});
const [success] = await modal.finished;
@ -582,6 +583,8 @@ async function doSetLoggedIn(
PosthogAnalytics.instance.updateAnonymityFromSettings(credentials.userId);
setSentryUser(credentials.userId);
const client = MatrixClientPeg.get();
if (credentials.freshLogin && SettingsStore.getValue("feature_dehydration")) {

View file

@ -28,13 +28,15 @@ import DialogButtons from "../elements/DialogButtons";
import { IDialogProps } from "./IDialogProps";
interface IProps extends IDialogProps {
error: string;
error: Error;
}
@replaceableComponent("views.dialogs.SessionRestoreErrorDialog")
export default class SessionRestoreErrorDialog extends React.Component<IProps> {
private sendBugReport = (): void => {
Modal.createTrackedDialog('Session Restore Error', 'Send Bug Report Dialog', BugReportDialog, {});
Modal.createTrackedDialog('Session Restore Error', 'Send Bug Report Dialog', BugReportDialog, {
error: this.props.error,
});
};
private onClearStorageClick = (): void => {

View file

@ -92,6 +92,7 @@ export default class LabsUserSettingsTab extends React.Component<{}, IState> {
<SettingsFlag name="enableWidgetScreenshots" level={SettingLevel.ACCOUNT} />
<SettingsFlag name="showHiddenEventsInTimeline" level={SettingLevel.DEVICE} />
<SettingsFlag name="lowBandwidth" level={SettingLevel.DEVICE} />
<SettingsFlag name="automaticErrorReporting" level={SettingLevel.DEVICE} />
{ hiddenReadReceipts }
</div>;
}

View file

@ -890,6 +890,7 @@
"Display Communities instead of Spaces": "Display Communities instead of Spaces",
"Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.",
"Developer mode": "Developer mode",
"Automatically send debug logs on any error": "Automatically send debug logs on any error",
"Collecting app version information": "Collecting app version information",
"Collecting logs": "Collecting logs",
"Uploading logs": "Uploading logs",

View file

@ -192,6 +192,11 @@ export async function sendSentryReport(userText: string, issueUrl: string, error
}
}
export function setSentryUser(mxid: string): void {
if (!SdkConfig.get().sentry || !SettingsStore.getValue("automaticErrorReporting")) return;
Sentry.setUser({ username: mxid });
}
interface ISentryConfig {
dsn: string;
environment?: string;
@ -199,21 +204,28 @@ interface ISentryConfig {
export async function initSentry(sentryConfig: ISentryConfig): Promise<void> {
if (!sentryConfig) return;
// Only enable Integrations.GlobalHandlers, which hooks uncaught exceptions, if automaticErrorReporting is true
const integrations = [
new Sentry.Integrations.InboundFilters(),
new Sentry.Integrations.FunctionToString(),
new Sentry.Integrations.Breadcrumbs(),
new Sentry.Integrations.UserAgent(),
new Sentry.Integrations.Dedupe(),
];
if (SettingsStore.getValue("automaticErrorReporting")) {
integrations.push(new Sentry.Integrations.GlobalHandlers(
{ onerror: false, onunhandledrejection: true }));
integrations.push(new Sentry.Integrations.TryCatch());
}
Sentry.init({
dsn: sentryConfig.dsn,
release: process.env.VERSION,
environment: sentryConfig.environment,
defaultIntegrations: false,
autoSessionTracking: false,
integrations: [
// specifically disable Integrations.GlobalHandlers, which hooks uncaught exceptions - we don't
// want to capture those at this stage, just explicit rageshakes
new Sentry.Integrations.InboundFilters(),
new Sentry.Integrations.FunctionToString(),
new Sentry.Integrations.Breadcrumbs(),
new Sentry.Integrations.UserAgent(),
new Sentry.Integrations.Dedupe(),
],
integrations,
// Set to 1.0 which is reasonable if we're only submitting Rageshakes; will need to be set < 1.0
// if we collect more frequently.
tracesSampleRate: 1.0,

View file

@ -762,6 +762,12 @@ export const SETTINGS: {[setting: string]: ISetting} = {
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
default: false,
},
"automaticErrorReporting": {
displayName: _td("Automatically send debug logs on any error"),
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
default: false,
controller: new ReloadOnChangeController(),
},
[UIFeature.RoomHistorySettings]: {
supportedLevels: LEVELS_UI_FEATURE,
default: true,