diff --git a/app/components/Root/Root.jsx b/app/components/Root/Root.jsx index 27576b6a2..176e708f9 100644 --- a/app/components/Root/Root.jsx +++ b/app/components/Root/Root.jsx @@ -10,6 +10,7 @@ import IntlWrapper from './IntlWrapper' import Routes from './Routes' import ContactsContextProvider from '../../context/contacts' import { walletConnectOptions } from '../../util/walletConnect' +import { setupSentryWrapper } from '../../util/SentryReactHelper' type Props = { store: Object, @@ -33,4 +34,4 @@ const Root = ({ store }: Props) => ( ) -export default Root +export default setupSentryWrapper(Root) diff --git a/app/index.js b/app/index.js index fa123d4de..8193050c7 100644 --- a/app/index.js +++ b/app/index.js @@ -6,6 +6,9 @@ import store from './store/configureStore' import Root from './components/Root' import './styles/tippy.compiled.global.css' import './styles/main.global.scss' +import { setupSentryReact } from './util/SentryReactHelper' + +setupSentryReact() if (module.hot) module.hot.accept() diff --git a/app/util/SentryReactHelper.js b/app/util/SentryReactHelper.js new file mode 100644 index 000000000..99bb12313 --- /dev/null +++ b/app/util/SentryReactHelper.js @@ -0,0 +1,22 @@ +import * as ElectronRedererSentry from '@sentry/electron/renderer' +import * as ReactSentry from '@sentry/react' + +const { sentryConfig, isSentryEnable } = require('../../config/sentry.config') + +export function setupSentryReact() { + if (isSentryEnable) { + ElectronRedererSentry.init( + { + dsn: process.env.SENTRY_DSN, + ...sentryConfig, + anrDetection: { captureStackTrace: true }, + }, + ReactSentry.init, + ) + } +} + +export const setupSentryWrapper = app => + isSentryEnable + ? ReactSentry.withProfiler(ReactSentry.withErrorBoundary(app)) + : app diff --git a/config/sentry.config.js b/config/sentry.config.js new file mode 100644 index 000000000..411e0fefd --- /dev/null +++ b/config/sentry.config.js @@ -0,0 +1,19 @@ +const { version } = require('../package.json') + +const isSentryEnable = + process.env.NODE_ENV === 'production' && !!process.env.SENTRY_DSN + +const sentryConfig = { + attachStacktrace: true, + autoSessionTracking: true, + debug: false, + enableTracing: true, + environment: 'NEON-2', + release: version, + replaysOnErrorSampleRate: 1.0, + replaysSessionSampleRate: 0.1, + tracePropagationTargets: ['localhost'], + tracesSampleRate: 1.0, +} + +module.exports = { sentryConfig, isSentryEnable } diff --git a/config/sentryElectron.setup.js b/config/sentryElectron.setup.js new file mode 100644 index 000000000..c251a01a5 --- /dev/null +++ b/config/sentryElectron.setup.js @@ -0,0 +1,43 @@ +const ElectronSentry = require('@sentry/electron/main') +const { IPCMode } = require('@sentry/electron/main') +const { session } = require('electron') + +const { sentryConfig, isSentryEnable } = require('./sentry.config') + +const exitReasons = [ + 'clean-exit', + 'abnormal-exit', + 'killed', + 'crashed', + 'oom', + 'launch-failed', + 'integrity-failure', +] + +const setupSentry = () => { + if (isSentryEnable) { + ElectronSentry.init({ + dsn: process.env.SENTRY_DSN, + ...sentryConfig, + getSessions: () => [ + session.defaultSession, + session.fromPartition('persist:my-session'), + ], + integrations: [ + new ElectronSentry.Integrations.BrowserWindowSession(), + new ElectronSentry.Integrations.ChildProcess({ + events: exitReasons, + breadcrumbs: exitReasons, + }), + new ElectronSentry.Integrations.ElectronMinidump(), + new ElectronSentry.Integrations.MainProcessSession({ + sendOnCreate: true, + }), + new ElectronSentry.Integrations.Console(), + ], + ipcMode: IPCMode.Both, + }) + } +} + +module.exports = { setupSentry } diff --git a/main.js b/main.js index 774a6a4e5..cc3e91751 100644 --- a/main.js +++ b/main.js @@ -14,11 +14,13 @@ const path = require('path') const url = require('url') const { autoUpdater } = require('electron-updater') const log = require('electron-log') +const { setupSentry } = require('./config/sentryElectron.setup') const port = process.env.PORT || 3000 let mainWindow = null let initialDeepLinkUri = null +setupSentry() if (process.defaultApp) { if (process.argv.length >= 2) { diff --git a/package.json b/package.json index 31691e93e..10d56a67d 100644 --- a/package.json +++ b/package.json @@ -129,6 +129,8 @@ "@ledgerhq/devices": "^7.0.0", "@ledgerhq/hw-transport-node-hid-noevents": "6.7.0", "@tippyjs/react": "^4.2.5", + "@sentry/electron": "^4.14.0", + "@sentry/react": "^7.83.0", "axios": "0.21.1", "axios-retry": "3.1.1", "bignumber.js": "5.0.0", @@ -317,4 +319,4 @@ "setupTestFrameworkScriptFile": "/__tests__/setupTests.js", "testURL": "http://localhost" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 20454ba91..28256ba07 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2933,6 +2933,100 @@ "@noble/hashes" "~1.3.0" "@scure/base" "~1.1.0" +"@sentry-internal/feedback@7.92.0": + version "7.92.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-7.92.0.tgz#1293b0a332f81cdf3970abd36894b9d25670c4e6" + integrity sha512-/jEALRtVqboxB9kcK2tag8QCO6XANTlGBb9RV3oeGXJe0DDNJXRq6wVZbfgztXJRrfgx4XVDcNt1pRVoGGG++g== + dependencies: + "@sentry/core" "7.92.0" + "@sentry/types" "7.92.0" + "@sentry/utils" "7.92.0" + +"@sentry-internal/tracing@7.92.0": + version "7.92.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.92.0.tgz#505d94a93b5df965ec6bfb35da43389988259d4d" + integrity sha512-ur55vPcUUUWFUX4eVLNP71ohswK7ZZpleNZw9Y1GfLqyI+0ILQUwjtzqItJrdClvVsdRZJMRmDV40Hp9Lbb9mA== + dependencies: + "@sentry/core" "7.92.0" + "@sentry/types" "7.92.0" + "@sentry/utils" "7.92.0" + +"@sentry/browser@7.92.0": + version "7.92.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.92.0.tgz#f4c65f2af6f38c2dd5e32153e9b358c0c80275f2" + integrity sha512-loMr02/zQ38u8aQhYLtIBg0i5n3ps2e3GUXrt3CdsJQdkRYfa62gcrE7SzvoEpMVHTk7VOI4fWGht8cWw/1k3A== + dependencies: + "@sentry-internal/feedback" "7.92.0" + "@sentry-internal/tracing" "7.92.0" + "@sentry/core" "7.92.0" + "@sentry/replay" "7.92.0" + "@sentry/types" "7.92.0" + "@sentry/utils" "7.92.0" + +"@sentry/core@7.92.0": + version "7.92.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.92.0.tgz#4e74c1959348b698226c49ead7a24e165502b55c" + integrity sha512-1Tly7YB2I1byI5xb0Cwrxs56Rhww+6mQ7m9P7rTmdC3/ijOzbEoohtYIUPwcooCEarpbEJe/tAayRx6BrH2UbQ== + dependencies: + "@sentry/types" "7.92.0" + "@sentry/utils" "7.92.0" + +"@sentry/electron@^4.14.0": + version "4.17.0" + resolved "https://registry.yarnpkg.com/@sentry/electron/-/electron-4.17.0.tgz#77ab66901b0d4607d1da66f6cebfc36f21aaaab1" + integrity sha512-1ThTHtn80E6h6mtt+V7tH03YW/vxwNfWrT8CxWSEUmtPQ/CPDpGZ8NN86lUwOPHjlSGBIYF4N33WVsGNhl+iAg== + dependencies: + "@sentry/browser" "7.92.0" + "@sentry/core" "7.92.0" + "@sentry/node" "7.92.0" + "@sentry/types" "7.92.0" + "@sentry/utils" "7.92.0" + deepmerge "4.3.0" + tslib "^2.5.0" + +"@sentry/node@7.92.0": + version "7.92.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.92.0.tgz#880d3be5cb8ef805a6856c619db3951b1678f726" + integrity sha512-LZeQL1r6kikEoOzA9K61OmMl32/lK/6PzmFNDH6z7UYwQopCZgVA6IP+CZuln8K2ys5c9hCyF7ICQMysXfpNJA== + dependencies: + "@sentry-internal/tracing" "7.92.0" + "@sentry/core" "7.92.0" + "@sentry/types" "7.92.0" + "@sentry/utils" "7.92.0" + https-proxy-agent "^5.0.0" + +"@sentry/react@^7.83.0": + version "7.92.0" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.92.0.tgz#be49d59c3ba18beab9cd03c86a5bd587fda7d1b6" + integrity sha512-lTvrLuvxtGEZbkW6NHru03K6eyixKyBliwiLwO+k37FK7Ha8Bwat2m77weyizWCdQ6DKlVazJNppkNeAlACIvQ== + dependencies: + "@sentry/browser" "7.92.0" + "@sentry/types" "7.92.0" + "@sentry/utils" "7.92.0" + hoist-non-react-statics "^3.3.2" + +"@sentry/replay@7.92.0": + version "7.92.0" + resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.92.0.tgz#d94e9f6b72e540e73378a74ca1190068edd447f2" + integrity sha512-G1t9Uvc9cR8VpNkElwvHIMGzykjIKikb10n0tfVd3e+rBPMCCjCPWOduwG6jZYxcvCjTpqmJh6NSLXxL/Mt4JA== + dependencies: + "@sentry-internal/tracing" "7.92.0" + "@sentry/core" "7.92.0" + "@sentry/types" "7.92.0" + "@sentry/utils" "7.92.0" + +"@sentry/types@7.92.0": + version "7.92.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.92.0.tgz#4c308fdb316c0272f55f0816230fe87e7b9b551a" + integrity sha512-APmSOuZuoRGpbPpPeYIbMSplPjiWNLZRQa73QiXuTflW4Tu/ItDlU8hOa2+A6JKVkJCuD2EN6yUrxDGSMyNXeg== + +"@sentry/utils@7.92.0": + version "7.92.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.92.0.tgz#20ed29742594eab007f9ff72e008b5262456a319" + integrity sha512-3nEfrQ1z28b/2zgFGANPh5yMVtgwXmrasZxTvKbrAj+KWJpjrJHrIR84r9W277J44NMeZ5RhRW2uoDmuBslPnA== + dependencies: + "@sentry/types" "7.92.0" + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -7060,6 +7154,11 @@ deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +deepmerge@4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.0.tgz#65491893ec47756d44719ae520e0e2609233b59b" + integrity sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og== + default-gateway@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" @@ -7439,6 +7538,11 @@ dotenv-expand@^5.1.0: resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== +dotenv@16.3.1: + version "16.3.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" + integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ== + dotenv@^8.1.0, dotenv@^8.2.0: version "8.6.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" @@ -16862,6 +16966,11 @@ tslib@^2.0.0, tslib@^2.0.3, tslib@^2.3.1, tslib@^2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== +tslib@^2.5.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"