diff --git a/app/soapbox/build_config.js b/app/soapbox/build_config.js index 7e0419619..bb9209d6c 100644 --- a/app/soapbox/build_config.js +++ b/app/soapbox/build_config.js @@ -11,6 +11,7 @@ const { BACKEND_URL, FE_SUBDIRECTORY, FE_BUILD_DIR, + SENTRY_DSN, } = process.env; const sanitizeURL = url => { @@ -38,4 +39,5 @@ module.exports = sanitize({ BACKEND_URL: sanitizeURL(BACKEND_URL), FE_SUBDIRECTORY: sanitizeBasename(FE_SUBDIRECTORY), FE_BUILD_DIR: sanitizePath(FE_BUILD_DIR) || 'static', + SENTRY_DSN, }); diff --git a/app/soapbox/components/error_boundary.js b/app/soapbox/components/error_boundary.js index 731e7ecf2..b2b077a5f 100644 --- a/app/soapbox/components/error_boundary.js +++ b/app/soapbox/components/error_boundary.js @@ -2,6 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage } from 'react-intl'; import Bowser from 'bowser'; +import * as Sentry from '@sentry/browser'; export default class ErrorBoundary extends React.PureComponent { @@ -15,6 +16,8 @@ export default class ErrorBoundary extends React.PureComponent { } componentDidCatch(error, info) { + Sentry.captureException(error); + this.setState({ hasError: true, error, diff --git a/app/soapbox/main.js b/app/soapbox/main.js index 599831e08..3802874df 100644 --- a/app/soapbox/main.js +++ b/app/soapbox/main.js @@ -10,12 +10,16 @@ import React from 'react'; import ReactDOM from 'react-dom'; import * as OfflinePluginRuntime from '@lcdp/offline-plugin/runtime'; import * as perf from './performance'; +import * as monitoring from './monitoring'; import ready from './ready'; import { NODE_ENV } from 'soapbox/build_config'; function main() { perf.start('main()'); + // Sentry + monitoring.start(); + ready(() => { const mountNode = document.getElementById('soapbox'); diff --git a/app/soapbox/monitoring.js b/app/soapbox/monitoring.js new file mode 100644 index 000000000..c99edaa70 --- /dev/null +++ b/app/soapbox/monitoring.js @@ -0,0 +1,16 @@ +import * as Sentry from '@sentry/react'; +import { Integrations } from '@sentry/tracing'; +import { NODE_ENV, SENTRY_DSN } from 'soapbox/build_config'; + +export function start() { + Sentry.init({ + dsn: SENTRY_DSN, + environment: NODE_ENV, + debug: NODE_ENV === 'development', + integrations: [new Integrations.BrowserTracing()], + + // We recommend adjusting this value in production, or using tracesSampler + // for finer control + tracesSampleRate: 1.0, + }); +} diff --git a/package.json b/package.json index 419294299..7a1ee4e28 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,9 @@ "@fontsource/roboto": "^4.5.0", "@lcdp/offline-plugin": "^5.1.0", "@popperjs/core": "^2.4.4", + "@sentry/browser": "^6.12.0", + "@sentry/react": "^6.12.0", + "@sentry/tracing": "^6.12.0", "@welldone-software/why-did-you-render": "^6.2.0", "array-includes": "^3.0.3", "autoprefixer": "^10.0.0", diff --git a/yarn.lock b/yarn.lock index 9e75304e7..958fca38f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2039,6 +2039,81 @@ resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353" integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q== +"@sentry/browser@6.12.0", "@sentry/browser@^6.12.0": + version "6.12.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.12.0.tgz#970cd68fa117a1e1336fdb373e3b1fa76cd63e2d" + integrity sha512-wsJi1NLOmfwtPNYxEC50dpDcVY7sdYckzwfqz1/zHrede1mtxpqSw+7iP4bHADOJXuF+ObYYTHND0v38GSXznQ== + dependencies: + "@sentry/core" "6.12.0" + "@sentry/types" "6.12.0" + "@sentry/utils" "6.12.0" + tslib "^1.9.3" + +"@sentry/core@6.12.0": + version "6.12.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.12.0.tgz#bc7c5f0785b6a392d9ad47bd9b1fae3f5389996c" + integrity sha512-mU/zdjlzFHzdXDZCPZm8OeCw7c9xsbL49Mq0TrY0KJjLt4CJBkiq5SDTGfRsenBLgTedYhe5Z/J8Z+xVVq+MfQ== + dependencies: + "@sentry/hub" "6.12.0" + "@sentry/minimal" "6.12.0" + "@sentry/types" "6.12.0" + "@sentry/utils" "6.12.0" + tslib "^1.9.3" + +"@sentry/hub@6.12.0": + version "6.12.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.12.0.tgz#29e323ab6a95e178fb14fffb684aa0e09707197f" + integrity sha512-yR/UQVU+ukr42bSYpeqvb989SowIXlKBanU0cqLFDmv5LPCnaQB8PGeXwJAwWhQgx44PARhmB82S6Xor8gYNxg== + dependencies: + "@sentry/types" "6.12.0" + "@sentry/utils" "6.12.0" + tslib "^1.9.3" + +"@sentry/minimal@6.12.0": + version "6.12.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.12.0.tgz#cbe20e95056cedb9709d7d5b2119ef95206a9f8c" + integrity sha512-r3C54Q1KN+xIqUvcgX9DlcoWE7ezWvFk2pSu1Ojx9De81hVqR9u5T3sdSAP2Xma+um0zr6coOtDJG4WtYlOtsw== + dependencies: + "@sentry/hub" "6.12.0" + "@sentry/types" "6.12.0" + tslib "^1.9.3" + +"@sentry/react@^6.12.0": + version "6.12.0" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-6.12.0.tgz#8ae2680d226fafb0da0f3d8366bb285004ba6c2e" + integrity sha512-E8Nw9PPzP/EyMy64ksr9xcyYYlBmUA5ROnkPQp7o5wF0xf5/J+nMS1tQdyPnLQe2KUgHlN4kVs2HHft1m7mSYQ== + dependencies: + "@sentry/browser" "6.12.0" + "@sentry/minimal" "6.12.0" + "@sentry/types" "6.12.0" + "@sentry/utils" "6.12.0" + hoist-non-react-statics "^3.3.2" + tslib "^1.9.3" + +"@sentry/tracing@^6.12.0": + version "6.12.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.12.0.tgz#a05c8985ee7fed7310b029b147d8f9f14f2a2e67" + integrity sha512-u10QHNknPBzbWSUUNMkvuH53sQd5NaBo6YdNPj4p5b7sE7445Sh0PwBpRbY3ZiUUiwyxV59fx9UQ4yVnPGxZQA== + dependencies: + "@sentry/hub" "6.12.0" + "@sentry/minimal" "6.12.0" + "@sentry/types" "6.12.0" + "@sentry/utils" "6.12.0" + tslib "^1.9.3" + +"@sentry/types@6.12.0": + version "6.12.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.12.0.tgz#b7395688a79403c6df8d8bb8d81deb8222519853" + integrity sha512-urtgLzE4EDMAYQHYdkgC0Ei9QvLajodK1ntg71bGn0Pm84QUpaqpPDfHRU+i6jLeteyC7kWwa5O5W1m/jrjGXA== + +"@sentry/utils@6.12.0": + version "6.12.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.12.0.tgz#3de261e8d11bdfdc7add64a3065d43517802e975" + integrity sha512-oRHQ7TH5TSsJqoP9Gqq25Jvn9LKexXfAh/OoKwjMhYCGKGhqpDNUIZVgl9DWsGw5A5N5xnQyLOxDfyRV5RshdA== + dependencies: + "@sentry/types" "6.12.0" + tslib "^1.9.3" + "@sinonjs/commons@^1.7.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.0.tgz#c8d68821a854c555bba172f3b06959a0039b236d" @@ -11670,6 +11745,11 @@ tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== +tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + tslib@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.2.tgz#462295631185db44b21b1ea3615b63cd1c038242"