diff options
author | kumavis <kumavis@users.noreply.github.com> | 2018-10-30 09:57:51 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-30 09:57:51 +0800 |
commit | 73eeeda2157e8a7ef61ff1f1fd0f4b94821f2e6f (patch) | |
tree | 51b163f772d253b8e56588fd254ca918a8b058a2 | |
parent | 310229d22e5e916e8d6e3b1a469b9b196e0f70c2 (diff) | |
parent | 7ae5a23b6c0e9839f63bba52ab5bf7da00bef173 (diff) | |
download | tangerine-wallet-browser-73eeeda2157e8a7ef61ff1f1fd0f4b94821f2e6f.tar tangerine-wallet-browser-73eeeda2157e8a7ef61ff1f1fd0f4b94821f2e6f.tar.gz tangerine-wallet-browser-73eeeda2157e8a7ef61ff1f1fd0f4b94821f2e6f.tar.bz2 tangerine-wallet-browser-73eeeda2157e8a7ef61ff1f1fd0f4b94821f2e6f.tar.lz tangerine-wallet-browser-73eeeda2157e8a7ef61ff1f1fd0f4b94821f2e6f.tar.xz tangerine-wallet-browser-73eeeda2157e8a7ef61ff1f1fd0f4b94821f2e6f.tar.zst tangerine-wallet-browser-73eeeda2157e8a7ef61ff1f1fd0f4b94821f2e6f.zip |
Merge pull request #5560 from MetaMask/sentry-enhancements2
Sentry - various enhancements to help debugging (alternate)
-rw-r--r-- | app/scripts/background.js | 12 | ||||
-rw-r--r-- | app/scripts/controllers/blacklist.js | 25 | ||||
-rw-r--r-- | app/scripts/controllers/currency.js | 30 | ||||
-rw-r--r-- | app/scripts/lib/reportFailedTxToSentry.js | 6 | ||||
-rw-r--r-- | app/scripts/lib/setupFetchDebugging.js | 10 | ||||
-rw-r--r-- | app/scripts/lib/setupSentry.js (renamed from app/scripts/lib/setupRaven.js) | 75 | ||||
-rw-r--r-- | app/scripts/ui.js | 14 | ||||
-rw-r--r-- | package-lock.json | 63 | ||||
-rw-r--r-- | package.json | 4 | ||||
-rw-r--r-- | ui/app/reducers.js | 26 |
10 files changed, 185 insertions, 80 deletions
diff --git a/app/scripts/background.js b/app/scripts/background.js index 6b3ac2664..2a3c5b08b 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -23,7 +23,7 @@ const createStreamSink = require('./lib/createStreamSink') const NotificationManager = require('./lib/notification-manager.js') const MetamaskController = require('./metamask-controller') const rawFirstTimeState = require('./first-time-state') -const setupRaven = require('./lib/setupRaven') +const setupSentry = require('./lib/setupSentry') const reportFailedTxToSentry = require('./lib/reportFailedTxToSentry') const setupMetamaskMeshMetrics = require('./lib/setupMetamaskMeshMetrics') const EdgeEncryptor = require('./edge-encryptor') @@ -50,7 +50,7 @@ global.METAMASK_NOTIFIER = notificationManager // setup sentry error reporting const release = platform.getVersion() -const raven = setupRaven({ release }) +const sentry = setupSentry({ release }) // browser check if it is Edge - https://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser // Internet Explorer 6-11 @@ -195,14 +195,14 @@ async function loadStateFromPersistence () { // we were able to recover (though it might be old) versionedData = diskStoreState const vaultStructure = getObjStructure(versionedData) - raven.captureMessage('MetaMask - Empty vault found - recovered from diskStore', { + sentry.captureMessage('MetaMask - Empty vault found - recovered from diskStore', { // "extra" key is required by Sentry extra: { vaultStructure }, }) } else { // unable to recover, clear state versionedData = migrator.generateInitialState(firstTimeState) - raven.captureMessage('MetaMask - Empty vault found - unable to recover') + sentry.captureMessage('MetaMask - Empty vault found - unable to recover') } } @@ -210,7 +210,7 @@ async function loadStateFromPersistence () { migrator.on('error', (err) => { // get vault structure without secrets const vaultStructure = getObjStructure(versionedData) - raven.captureException(err, { + sentry.captureException(err, { // "extra" key is required by Sentry extra: { vaultStructure }, }) @@ -275,7 +275,7 @@ function setupController (initState, initLangCode) { if (status !== 'failed') return const txMeta = controller.txController.txStateManager.getTx(txId) try { - reportFailedTxToSentry({ raven, txMeta }) + reportFailedTxToSentry({ sentry, txMeta }) } catch (e) { console.error(e) } diff --git a/app/scripts/controllers/blacklist.js b/app/scripts/controllers/blacklist.js index 89c7cc888..e55b09d03 100644 --- a/app/scripts/controllers/blacklist.js +++ b/app/scripts/controllers/blacklist.js @@ -83,8 +83,25 @@ class BlacklistController { * */ async updatePhishingList () { - const response = await fetch('https://api.infura.io/v2/blacklist') - const phishing = await response.json() + // make request + let response + try { + response = await fetch('https://api.infura.io/v2/blacklist') + } catch (err) { + log.error(new Error(`BlacklistController - failed to fetch blacklist:\n${err.stack}`)) + return + } + // parse response + let rawResponse + let phishing + try { + const rawResponse = await response.text() + phishing = JSON.parse(rawResponse) + } catch (err) { + log.error(new Error(`BlacklistController - failed to parse blacklist:\n${rawResponse}`)) + return + } + // update current blacklist this.store.updateState({ phishing }) this._setupPhishingDetector(phishing) return phishing @@ -97,9 +114,9 @@ class BlacklistController { */ scheduleUpdates () { if (this._phishingUpdateIntervalRef) return - this.updatePhishingList().catch(log.warn) + this.updatePhishingList() this._phishingUpdateIntervalRef = setInterval(() => { - this.updatePhishingList().catch(log.warn) + this.updatePhishingList() }, POLLING_INTERVAL) } diff --git a/app/scripts/controllers/currency.js b/app/scripts/controllers/currency.js index 1e866d2c9..fce65fd9c 100644 --- a/app/scripts/controllers/currency.js +++ b/app/scripts/controllers/currency.js @@ -133,18 +133,40 @@ class CurrencyController { try { currentCurrency = this.getCurrentCurrency() nativeCurrency = this.getNativeCurrency() + // select api let apiUrl if (nativeCurrency === 'ETH') { + // ETH apiUrl = `https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}` } else { + // ETC apiUrl = `https://min-api.cryptocompare.com/data/price?fsym=${nativeCurrency.toUpperCase()}&tsyms=${currentCurrency.toUpperCase()}` } - const response = await fetch(apiUrl) - const parsedResponse = await response.json() + // attempt request + let response + try { + response = await fetch(apiUrl) + } catch (err) { + log.error(new Error(`CurrencyController - Failed to request currency from Infura:\n${err.stack}`)) + return + } + // parse response + let rawResponse + let parsedResponse + try { + rawResponse = await response.text() + parsedResponse = JSON.parse(rawResponse) + } catch (err) { + log.error(new Error(`CurrencyController - Failed to parse response "${rawResponse}"`)) + return + } + // set conversion rate if (nativeCurrency === 'ETH') { + // ETH this.setConversionRate(Number(parsedResponse.bid)) this.setConversionDate(Number(parsedResponse.timestamp)) } else { + // ETC if (parsedResponse[currentCurrency.toUpperCase()]) { this.setConversionRate(Number(parsedResponse[currentCurrency.toUpperCase()])) this.setConversionDate(parseInt((new Date()).getTime() / 1000)) @@ -154,9 +176,13 @@ class CurrencyController { } } } catch (err) { + // reset current conversion rate log.warn(`MetaMask - Failed to query currency conversion:`, nativeCurrency, currentCurrency, err) this.setConversionRate(0) this.setConversionDate('N/A') + // throw error + log.error(new Error(`CurrencyController - Failed to query rate for currency "${currentCurrency}":\n${err.stack}`)) + return } } diff --git a/app/scripts/lib/reportFailedTxToSentry.js b/app/scripts/lib/reportFailedTxToSentry.js index df5661e59..de4d57145 100644 --- a/app/scripts/lib/reportFailedTxToSentry.js +++ b/app/scripts/lib/reportFailedTxToSentry.js @@ -7,10 +7,10 @@ module.exports = reportFailedTxToSentry // for sending to sentry // -function reportFailedTxToSentry ({ raven, txMeta }) { +function reportFailedTxToSentry ({ sentry, txMeta }) { const errorMessage = 'Transaction Failed: ' + extractEthjsErrorMessage(txMeta.err.message) - raven.captureMessage(errorMessage, { + sentry.captureMessage(errorMessage, { // "extra" key is required by Sentry - extra: txMeta, + extra: { txMeta }, }) } diff --git a/app/scripts/lib/setupFetchDebugging.js b/app/scripts/lib/setupFetchDebugging.js index dd87b65a6..c1ef22d21 100644 --- a/app/scripts/lib/setupFetchDebugging.js +++ b/app/scripts/lib/setupFetchDebugging.js @@ -2,7 +2,7 @@ module.exports = setupFetchDebugging // // This is a utility to help resolve cases where `window.fetch` throws a -// `TypeError: Failed to Fetch` without any stack or context for the request +// `TypeError: Failed to Fetch` without any stack or context for the request // https://github.com/getsentry/sentry-javascript/pull/1293 // @@ -17,9 +17,11 @@ function setupFetchDebugging() { try { return await originalFetch.call(window, ...args) } catch (err) { - console.warn('FetchDebugger - fetch encountered an Error', err) - console.warn('FetchDebugger - overriding stack to point of original call') - err.stack = initialStack + if (!err.stack) { + console.warn('FetchDebugger - fetch encountered an Error without a stack', err) + console.warn('FetchDebugger - overriding stack to point of original call') + err.stack = initialStack + } throw err } } diff --git a/app/scripts/lib/setupRaven.js b/app/scripts/lib/setupSentry.js index e6e511640..69042bc19 100644 --- a/app/scripts/lib/setupRaven.js +++ b/app/scripts/lib/setupSentry.js @@ -1,58 +1,55 @@ -const Raven = require('raven-js') +const Sentry = require('@sentry/browser') const METAMASK_DEBUG = process.env.METAMASK_DEBUG const extractEthjsErrorMessage = require('./extractEthjsErrorMessage') -const PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505' -const DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496' +const SENTRY_DSN_PROD = 'https://3567c198f8a8412082d32655da2961d0@sentry.io/273505' +const SENTRY_DSN_DEV = 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496' -module.exports = setupRaven +module.exports = setupSentry -// Setup raven / sentry remote error reporting -function setupRaven (opts) { - const { release } = opts - let ravenTarget +// Setup sentry remote error reporting +function setupSentry (opts) { + const { release, getState } = opts + let sentryTarget // detect brave const isBrave = Boolean(window.chrome.ipcRenderer) if (METAMASK_DEBUG) { - console.log('Setting up Sentry Remote Error Reporting: DEV') - ravenTarget = DEV + console.log('Setting up Sentry Remote Error Reporting: SENTRY_DSN_DEV') + sentryTarget = SENTRY_DSN_DEV } else { - console.log('Setting up Sentry Remote Error Reporting: PROD') - ravenTarget = PROD + console.log('Setting up Sentry Remote Error Reporting: SENTRY_DSN_PROD') + sentryTarget = SENTRY_DSN_PROD } - const client = Raven.config(ravenTarget, { + Sentry.init({ + dsn: sentryTarget, + debug: METAMASK_DEBUG, release, - transport: function (opts) { - opts.data.extra.isBrave = isBrave - const report = opts.data + beforeSend: (report) => rewriteReport(report), + }) - try { - // handle error-like non-error exceptions - rewriteErrorLikeExceptions(report) - // simplify certain complex error messages (e.g. Ethjs) - simplifyErrorMessages(report) - // modify report urls - rewriteReportUrls(report) - } catch (err) { - console.warn(err) - } - // make request normally - client._makeRequest(opts) - }, + Sentry.configureScope(scope => { + scope.setExtra('isBrave', isBrave) }) - client.install() - return Raven -} + 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 + } -function rewriteErrorLikeExceptions (report) { - // handle errors that lost their error-ness in serialization (e.g. dnode) - rewriteErrorMessages(report, (errorMessage) => { - if (!errorMessage.includes('Non-Error exception captured with keys:')) return errorMessage - if (!(report.extra && report.extra.__serialized__ && report.extra.__serialized__.message)) return errorMessage - return `Non-Error Exception: ${report.extra.__serialized__.message}` - }) + return Sentry } function simplifyErrorMessages (report) { diff --git a/app/scripts/ui.js b/app/scripts/ui.js index 98a036338..c4f6615db 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -9,7 +9,7 @@ const extension = require('extensionizer') const ExtensionPlatform = require('./platforms/extension') const NotificationManager = require('./lib/notification-manager') const notificationManager = new NotificationManager() -const setupRaven = require('./lib/setupRaven') +const setupSentry = require('./lib/setupSentry') const log = require('loglevel') start().catch(log.error) @@ -21,7 +21,17 @@ async function start () { // setup sentry error reporting const release = global.platform.getVersion() - setupRaven({ release }) + setupSentry({ release, getState }) + // provide app state to append to error logs + function getState() { + // get app state + const state = window.getCleanAppState() + // remove unnecessary data + delete state.localeMessages + delete state.metamask.recentBlocks + // return state to be added to request + return state + } // inject css // const css = MetaMaskUiCss() diff --git a/package-lock.json b/package-lock.json index c6cfedb0a..43a3aac15 100644 --- a/package-lock.json +++ b/package-lock.json @@ -489,6 +489,16 @@ } } }, + "@sentry/browser": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-4.2.3.tgz", + "integrity": "sha512-XvuIc1aclz4zuP2LamDuSy62/gl1mmNxzF+Ni5L8mcghBDq0urnOdkblVQgzqGoH8mc2QfjEctGa5djWxg3Bpg==", + "requires": { + "@sentry/core": "4.2.3", + "@sentry/types": "4.2.3", + "@sentry/utils": "4.2.3" + } + }, "@sentry/cli": { "version": "1.30.3", "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-1.30.3.tgz", @@ -531,6 +541,48 @@ } } }, + "@sentry/core": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-4.2.3.tgz", + "integrity": "sha512-xo5rvksftnaEdnKbdokyfuqgMnuqw1DFp0lDboIFHlEBcQde/AdThEgLujJWmbVNI3Cg7g8/HvP65f7QBjKfOw==", + "requires": { + "@sentry/hub": "4.2.3", + "@sentry/minimal": "4.2.3", + "@sentry/types": "4.2.3", + "@sentry/utils": "4.2.3" + } + }, + "@sentry/hub": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-4.2.3.tgz", + "integrity": "sha512-7Jc/wz3vybYm1RX2wk/4zAQS8fo3uxvXYBkRfpm3OmnGgTlwDEmJwtegeGWFqufxLl85brZ19V1KAdulmO206A==", + "requires": { + "@sentry/types": "4.2.3", + "@sentry/utils": "4.2.3" + } + }, + "@sentry/minimal": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-4.2.3.tgz", + "integrity": "sha512-Hus7LUeJDGsYpT2RTe6bUjG7mHG9uQoyDmW6pYUMN2dhD+cP5cPoTIXO4yxokwgAeDa+GH2/UXoASWc4s2eA2w==", + "requires": { + "@sentry/hub": "4.2.3", + "@sentry/types": "4.2.3" + } + }, + "@sentry/types": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-4.2.3.tgz", + "integrity": "sha512-Z7laXlLtLSEXcKzgcD2caWPMTM8sAvR86rssYM5uYb3azC5PO0aAvuhjokkdv1+Ke1Bg7lkaNZamiCSyaH/9xg==" + }, + "@sentry/utils": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-4.2.3.tgz", + "integrity": "sha512-D6+M1081wCwGp8adWV3KFOxrxFmVyjMJ45x6/TnYvXdgDyc+t28oil21FHeKhwjld9eMqgQ5Tf1OOvos1MNBQg==", + "requires": { + "@sentry/types": "4.2.3" + } + }, "@sinonjs/formatio": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", @@ -6131,9 +6183,9 @@ } }, "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" }, "clone-buffer": { "version": "1.0.0", @@ -27458,11 +27510,6 @@ "eve-raphael": "0.5.0" } }, - "raven-js": { - "version": "3.24.2", - "resolved": "https://registry.npmjs.org/raven-js/-/raven-js-3.24.2.tgz", - "integrity": "sha512-Dy/FHDxuo5pXywVf8Nrs5utB2juMATpkxWGqHjVbpFD3m8CaWYLvkB5SEXjWFUZ5GvUsrBVVQ+Dfcp0x6Z7SOg==" - }, "raw-body": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", diff --git a/package.json b/package.json index 3e922c454..1164c6b4c 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ }, "dependencies": { "@material-ui/core": "1.0.0", + "@sentry/browser": "^4.1.1", "@zxing/library": "^0.8.0", "abi-decoder": "^1.0.9", "asmcrypto.js": "0.22.0", @@ -97,7 +98,7 @@ "browserify-derequire": "^0.9.4", "browserify-unibabel": "^3.0.0", "classnames": "^2.2.5", - "clone": "^2.1.1", + "clone": "^2.1.2", "copy-to-clipboard": "^3.0.8", "css-loader": "^0.28.11", "currency-formatter": "^1.4.2", @@ -186,7 +187,6 @@ "pumpify": "^1.3.4", "qrcode-npm": "0.0.3", "ramda": "^0.24.1", - "raven-js": "^3.24.2", "react": "^15.6.2", "react-addons-css-transition-group": "^15.6.0", "react-dom": "^15.6.2", diff --git a/ui/app/reducers.js b/ui/app/reducers.js index 80e76d570..e1a982f93 100644 --- a/ui/app/reducers.js +++ b/ui/app/reducers.js @@ -1,3 +1,4 @@ +const clone = require('clone') const extend = require('xtend') const copyToClipboard = require('copy-to-clipboard') @@ -52,19 +53,24 @@ function rootReducer (state, action) { return state } +window.getCleanAppState = function () { + const state = clone(window.METAMASK_CACHED_LOG_STATE) + // append additional information + state.version = global.platform.getVersion() + state.browser = window.navigator.userAgent + // ensure seedWords are not included + if (state.metamask) delete state.metamask.seedWords + if (state.appState.currentView) delete state.appState.currentView.seedWords + return state +} + window.logStateString = function (cb) { - const state = window.METAMASK_CACHED_LOG_STATE - const version = global.platform.getVersion() - const browser = window.navigator.userAgent - return global.platform.getPlatformInfo((err, platform) => { - if (err) { - return cb(err) - } - state.version = version + const state = window.getCleanAppState() + global.platform.getPlatformInfo((err, platform) => { + if (err) return cb(err) state.platform = platform - state.browser = browser const stateString = JSON.stringify(state, removeSeedWords, 2) - return cb(null, stateString) + cb(null, stateString) }) } |