1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-10-22 19:26:13 +02:00
metamask-extension/app/scripts/lib/setupSentry.js
Mark Stacey e8b33fb7c8
Restore state snapshot for Sentry errors (#9028)
The state snapshot that was attached to Sentry errors was removed
recently in #8794 because it had become too large. The snapshot has
now been restored and reduced in size.

A utility function has been written to reduce the state object to just
the requested properties. This seemed safer than filtering out state
that is known to be large or to contain identifiable information.
This is not a great solution, as now knowledge about the state shape
resides in this large constant, but it will suffice for now. I am
hopeful that we can decorate our controllers with this metadata in the
future instead, as part of the upcoming background controller refactor.

A separate `getSentryState` global function has been added to get the
reduced state, so that the old `getCleanAppState` function that we used
to use could remain unchanged. It's still useful to get that full state
copy while debugging, and in e2e tests.
2020-07-17 12:09:38 -03:00

166 lines
4.6 KiB
JavaScript

import * as Sentry from '@sentry/browser'
import { Dedupe, ExtraErrorData } from '@sentry/integrations'
import extractEthjsErrorMessage from './extractEthjsErrorMessage'
const METAMASK_DEBUG = process.env.METAMASK_DEBUG
const METAMASK_ENVIRONMENT = process.env.METAMASK_ENVIRONMENT
const SENTRY_DSN_PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505'
const SENTRY_DSN_DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496'
// This describes the subset of Redux state attached to errors sent to Sentry
// These properties have some potential to be useful for debugging, and they do
// not contain any identifiable information.
export const SENTRY_STATE = {
gas: true,
history: true,
metamask: {
alertEnabledness: true,
completedOnboarding: true,
connectedStatusPopoverHasBeenShown: true,
conversionDate: true,
conversionRate: true,
currentBlockGasLimit: true,
currentCurrency: true,
currentLocale: true,
customNonceValue: true,
defaultHomeActiveTabName: true,
featureFlags: true,
firstTimeFlowType: true,
forgottenPassword: true,
incomingTxLastFetchedBlocksByNetwork: true,
ipfsGateway: true,
isAccountMenuOpen: true,
isInitialized: true,
isUnlocked: true,
metaMetricsId: true,
metaMetricsSendCount: true,
nativeCurrency: true,
network: true,
nextNonce: true,
participateInMetaMetrics: true,
preferences: true,
provider: {
nickname: true,
ticker: true,
type: true,
},
seedPhraseBackedUp: true,
settings: {
chainId: true,
ticker: true,
nickname: true,
},
showRestorePrompt: true,
threeBoxDisabled: true,
threeBoxLastUpdated: true,
threeBoxSynced: true,
threeBoxSyncingAllowed: true,
unapprovedDecryptMsgCount: true,
unapprovedEncryptionPublicKeyMsgCount: true,
unapprovedMsgCount: true,
unapprovedPersonalMsgCount: true,
unapprovedTypedMessagesCount: true,
useBlockie: true,
useNonceField: true,
usePhishDetect: true,
welcomeScreenSeen: true,
},
unconnectedAccount: true,
}
export default function setupSentry ({ release, getState }) {
let sentryTarget
if (METAMASK_DEBUG || process.env.IN_TEST) {
console.log(`Setting up Sentry Remote Error Reporting for '${METAMASK_ENVIRONMENT}': SENTRY_DSN_DEV`)
sentryTarget = SENTRY_DSN_DEV
} else {
console.log(`Setting up Sentry Remote Error Reporting for '${METAMASK_ENVIRONMENT}': SENTRY_DSN_PROD`)
sentryTarget = SENTRY_DSN_PROD
}
Sentry.init({
dsn: sentryTarget,
debug: METAMASK_DEBUG,
environment: METAMASK_ENVIRONMENT,
integrations: [
new Dedupe(),
new ExtraErrorData(),
],
release,
beforeSend: (report) => rewriteReport(report),
})
function rewriteReport (report) {
try {
// simplify certain complex error messages (e.g. Ethjs)
simplifyErrorMessages(report)
// modify report urls
rewriteReportUrls(report)
// append app state
if (getState) {
const appState = getState()
report.extra.appState = appState
}
} catch (err) {
console.warn(err)
}
return report
}
return Sentry
}
function simplifyErrorMessages (report) {
rewriteErrorMessages(report, (errorMessage) => {
// simplify ethjs error messages
errorMessage = extractEthjsErrorMessage(errorMessage)
// simplify 'Transaction Failed: known transaction'
if (errorMessage.indexOf('Transaction Failed: known transaction') === 0) {
// cut the hash from the error message
errorMessage = 'Transaction Failed: known transaction'
}
return errorMessage
})
}
function rewriteErrorMessages (report, rewriteFn) {
// rewrite top level message
if (typeof report.message === 'string') {
report.message = rewriteFn(report.message)
}
// rewrite each exception message
if (report.exception && report.exception.values) {
report.exception.values.forEach((item) => {
if (typeof item.value === 'string') {
item.value = rewriteFn(item.value)
}
})
}
}
function rewriteReportUrls (report) {
// update request url
report.request.url = toMetamaskUrl(report.request.url)
// update exception stack trace
if (report.exception && report.exception.values) {
report.exception.values.forEach((item) => {
if (item.stacktrace) {
item.stacktrace.frames.forEach((frame) => {
frame.filename = toMetamaskUrl(frame.filename)
})
}
})
}
}
function toMetamaskUrl (origUrl) {
const filePath = origUrl.split(window.location.origin)[1]
if (!filePath) {
return origUrl
}
const metamaskUrl = `metamask${filePath}`
return metamaskUrl
}