From 75c7e34f904fa6952e6cd12769cb9ba3a08783ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Tue, 3 Jul 2018 20:58:43 +0200 Subject: [PATCH] Anonymize Sentry --- src/commands/testCrash.js | 11 +++---- src/components/modals/Debug.js | 13 ++++++-- src/helpers/anonymizer.js | 16 ++++++++++ src/logger.js | 20 +++++------- src/sentry/install.js | 56 ++++++++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 22 deletions(-) create mode 100644 src/helpers/anonymizer.js diff --git a/src/commands/testCrash.js b/src/commands/testCrash.js index 0725988a..e5521c0c 100644 --- a/src/commands/testCrash.js +++ b/src/commands/testCrash.js @@ -2,16 +2,15 @@ // This is a test example for dev testing purpose. -import { Observable } from 'rxjs' import { createCommand, Command } from 'helpers/ipc' type Input = void type Result = void -const cmd: Command = createCommand('testCrash', () => - Observable.create(() => { - process.exit(1) - }), -) +const cmd: Command = createCommand('testCrash', () => { + // $FlowFixMe + crashTest() // eslint-disable-line + throw new Error() +}) export default cmd diff --git a/src/components/modals/Debug.js b/src/components/modals/Debug.js index bcd5284a..c87bbf9f 100644 --- a/src/components/modals/Debug.js +++ b/src/components/modals/Debug.js @@ -31,12 +31,16 @@ class Debug extends Component<*, *> { ) } - onCrash = () => { + onInternalCrash = () => { testCrash.send().subscribe({ error: this.error, }) } + onCrashHere = () => { + throw new Error('CrashTest') + } + onClickStressDevice = (device: *) => async () => { try { const currency = getCryptoCurrencyById('bitcoin') @@ -142,8 +146,11 @@ class Debug extends Component<*, *> { )} - + diff --git a/src/helpers/anonymizer.js b/src/helpers/anonymizer.js new file mode 100644 index 00000000..e9237fb2 --- /dev/null +++ b/src/helpers/anonymizer.js @@ -0,0 +1,16 @@ +// @flow + +export default { + url: (url: string): string => + url + .replace(/\/addresses\/[^/]+/g, '/addresses/') + .replace(/blockHash=[^&]+/g, 'blockHash='), + + appURI: (uri: string): string => uri.replace(/account\/[^/]/g, 'account/'), + + filepath: (filepath: string): string => { + const i = filepath.indexOf('/node_modules') + if (i !== -1) return `.${filepath.slice(i)}` + return filepath + }, +} diff --git a/src/logger.js b/src/logger.js index e2f64c76..2b4956a2 100644 --- a/src/logger.js +++ b/src/logger.js @@ -3,6 +3,7 @@ import winston from 'winston' import Transport from 'winston-transport' import resolveLogsDirectory, { RotatingLogFileParameters } from 'helpers/resolveLogsDirectory' +import anonymizer from 'helpers/anonymizer' import { DEBUG_NETWORK, @@ -85,13 +86,6 @@ const logger = winston.createLogger({ transports, }) -const anonymousMode = !__DEV__ - -function anonymizeURL(url) { - if (!anonymousMode) return url - return url.replace(/\/addresses\/[^/]+/g, '/addresses/') -} - const logCmds = !__DEV__ || DEBUG_COMMANDS const logDb = !__DEV__ || DEBUG_DB const logRedux = !__DEV__ || DEBUG_ACTION @@ -165,7 +159,7 @@ export default { }, network: ({ method, url }: { method: string, url: string }) => { - const log = `➡📡 ${method} ${anonymizeURL(url)}` + const log = `➡📡 ${method} ${anonymizer.url(url)}` if (logNetwork) { logger.log('info', log, { type: 'network' }) } @@ -182,7 +176,7 @@ export default { status: number, responseTime: number, }) => { - const log = `✔📡 HTTP ${status} ${method} ${anonymizeURL( + const log = `✔📡 HTTP ${status} ${method} ${anonymizer.url( url, )} – finished in ${responseTime.toFixed(0)}ms` if (logNetwork) { @@ -203,7 +197,7 @@ export default { error: string, responseTime: number, }) => { - const log = `✖📡 HTTP ${status} ${method} ${anonymizeURL( + const log = `✖📡 HTTP ${status} ${method} ${anonymizer.url( url, )} – ${error} – failed after ${responseTime.toFixed(0)}ms` if (logNetwork) { @@ -220,9 +214,9 @@ export default { url: string, responseTime: number, }) => { - const log = `✖📡 NETWORK DOWN – ${method} ${anonymizeURL(url)} – after ${responseTime.toFixed( - 0, - )}ms` + const log = `✖📡 NETWORK DOWN – ${method} ${anonymizer.url( + url, + )} – after ${responseTime.toFixed(0)}ms` if (logNetwork) { logger.log('info', log, { type: 'network-down' }) } diff --git a/src/sentry/install.js b/src/sentry/install.js index 95a505d7..a3651e86 100644 --- a/src/sentry/install.js +++ b/src/sentry/install.js @@ -1,4 +1,6 @@ // @flow +import anonymizer from 'helpers/anonymizer' +/* eslint-disable no-continue */ require('../env') @@ -11,6 +13,60 @@ export default (Raven: any, shouldSendCallback: () => boolean, userId: string) = tags: { git_commit: __GIT_REVISION__ }, environment: __DEV__ ? 'development' : 'production', shouldSendCallback, + dataCallback: (data: mixed) => { + // We are mutating the data to anonymize everything. + + if (typeof data !== 'object' || !data) return data + + delete data.server_name // hides the user machine name + if (typeof data.request === 'object' && data.request) { + const { request } = data + if (typeof request.url === 'string') { + request.url = anonymizer.appURI(request.url) + } + } + + if (data.breadcrumbs && typeof data.breadcrumbs === 'object') { + const { breadcrumbs } = data + if (Array.isArray(breadcrumbs.values)) { + const { values } = breadcrumbs + for (const b of values) { + if (!b || typeof b !== 'object') continue + if (b.category === 'xhr' && b.data && typeof b.data === 'object') { + const { data } = b + if (typeof data.url === 'string') { + data.url = anonymizer.url(data.url) + } + } + } + } + } + + if (data.exception && typeof data.exception === 'object') { + const { exception } = data + if (Array.isArray(exception.values)) { + const { values } = exception + for (const value of values) { + if (value && typeof value === 'object') { + const { stacktrace } = value + if (stacktrace && typeof stacktrace === 'object') { + if (Array.isArray(stacktrace.frames)) { + const { frames } = stacktrace + for (const frame of frames) { + if (frame && typeof frame === 'object' && typeof frame.filename === 'string') { + frame.filename = anonymizer.filepath(frame.filename) + } + } + } + } + } + } + } + } + + console.log('Sentry=>', data) // eslint-disable-line + return data + }, }) const user = { ip_address: null,