From a33040fcaad64a48faa31ae0401729d44ec7a449 Mon Sep 17 00:00:00 2001 From: LautaroPetaccio Date: Fri, 21 Feb 2025 15:18:50 -0300 Subject: [PATCH] feat: Add Sentry to the auth site --- .github/workflows/build-release.yaml | 11 ++ package-lock.json | 108 ++++++++++++++++++ package.json | 1 + scripts/prebuild.cjs | 2 +- .../Pages/CallbackPage/CallbackPage.tsx | 3 + src/components/Pages/LoginPage/LoginPage.tsx | 2 + .../Pages/RequestPage/RequestPage.tsx | 6 +- src/components/Pages/SetupPage/SetupPage.tsx | 3 + src/main.tsx | 1 + src/modules/analytics/sentry.ts | 16 +++ src/modules/config/env/dev.json | 2 + src/modules/config/env/prod.json | 2 + src/modules/config/env/stg.json | 2 + 13 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 src/modules/analytics/sentry.ts diff --git a/.github/workflows/build-release.yaml b/.github/workflows/build-release.yaml index abb36a0..a2dc538 100644 --- a/.github/workflows/build-release.yaml +++ b/.github/workflows/build-release.yaml @@ -45,3 +45,14 @@ jobs: gitlab-pipeline-url: ${{ secrets.GITLAB_CDN_DEPLOYER_URL }} env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Create Sentry release + if: github.event_name == 'release' && github.event.action == 'created' + uses: getsentry/action-release@v1 + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + with: + sourcemaps: ${{ github.workspace }}/webapp/dist + version: '${{ vars.SENTRY_RELEASE_PREFIX }}@${{ github.event.release.tag_name }}' + url_prefix: '~' diff --git a/package-lock.json b/package-lock.json index c18e9a1..f4281d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@dcl/single-sign-on-client": "^0.1.0", "@dcl/ui-env": "^1.4.0", "@magic-ext/oauth2": "^9.21.0", + "@sentry/react": "^9.1.0", "@well-known-components/fetch-component": "^2.0.2", "ajv": "^8.12.0", "classnames": "^2.3.2", @@ -3298,6 +3299,98 @@ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/@sentry-internal/browser-utils": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.1.0.tgz", + "integrity": "sha512-S1uT+kkFlstWpwnaBTIJSwwAID8PS3aA0fIidOjNezeoUE5gOvpsjDATo9q+sl6FbGWynxMz6EnYSrq/5tuaBQ==", + "license": "MIT", + "dependencies": { + "@sentry/core": "9.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.1.0.tgz", + "integrity": "sha512-jTDCqkqH3QDC8m9WO4mB06hqnBRsl3p7ozoh0E774UvNB6blOEZjShhSGMMEy5jbbJajPWsOivCofUtFAwbfGw==", + "license": "MIT", + "dependencies": { + "@sentry/core": "9.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.1.0.tgz", + "integrity": "sha512-E2xrUoms90qvm0BVOuaZ8QfkMoTUEgoIW/35uOeaqNcL7uOIj8c5cSEQQKit2Dr7CL6W+Ci5c6Khdyd5C0NL5w==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "9.1.0", + "@sentry/core": "9.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.1.0.tgz", + "integrity": "sha512-gxredVe+mOgfNqDJ3dTLiRON3FK1rZ8d0LHp7TICK/umLkWFkuso0DbNeyKU+3XCEjCr9VM7ZRqTDMzmY6zyVg==", + "license": "MIT", + "dependencies": { + "@sentry-internal/replay": "9.1.0", + "@sentry/core": "9.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/browser": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.1.0.tgz", + "integrity": "sha512-G55e5j77DqRW3LkalJLAjRRfuyKrjHaKTnwIYXa6ycO+Q1+l14pEUxu+eK5Abu2rtSdViwRSb5/G6a/miSUlYA==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "9.1.0", + "@sentry-internal/feedback": "9.1.0", + "@sentry-internal/replay": "9.1.0", + "@sentry-internal/replay-canvas": "9.1.0", + "@sentry/core": "9.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/core": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.1.0.tgz", + "integrity": "sha512-djWEzSBpMgqdF3GQuxO+kXCUX+Mgq42G4Uah/HSUBvPDHKipMmyWlutGRoFyVPPOnCDgpHu3wCt83wbpEyVmDw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/react": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.1.0.tgz", + "integrity": "sha512-aP2sXHH+erbomuzU762ktg340IGDh8zD7ueuqwBwGu98fhCpTYsLXiS85I29tUvPLljwNU9puLPmxbgW4iZ2tQ==", + "license": "MIT", + "dependencies": { + "@sentry/browser": "9.1.0", + "@sentry/core": "9.1.0", + "hoist-non-react-statics": "^3.3.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^16.14.0 || 17.x || 18.x || 19.x" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -9022,6 +9115,21 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, "node_modules/html-encoding-sniffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", diff --git a/package.json b/package.json index 5bdcf89..693ca13 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@dcl/single-sign-on-client": "^0.1.0", "@dcl/ui-env": "^1.4.0", "@magic-ext/oauth2": "^9.21.0", + "@sentry/react": "^9.1.0", "@well-known-components/fetch-component": "^2.0.2", "ajv": "^8.12.0", "classnames": "^2.3.2", diff --git a/scripts/prebuild.cjs b/scripts/prebuild.cjs index 87081e9..110be4e 100644 --- a/scripts/prebuild.cjs +++ b/scripts/prebuild.cjs @@ -13,7 +13,7 @@ const packageJson = JSON.parse(fs.readFileSync('./package.json').toString()) const publicPackageJson = JSON.parse(fs.readFileSync('./public/package.json').toString()) // set version -ENV_CONTENT['REACT_APP_WEBSITE_VERSION'] = packageJson.version +ENV_CONTENT['VITE_REACT_APP_WEBSITE_VERSION'] = packageJson.version publicPackageJson.version = packageJson.version // set public url diff --git a/src/components/Pages/CallbackPage/CallbackPage.tsx b/src/components/Pages/CallbackPage/CallbackPage.tsx index 92aedd3..630b999 100644 --- a/src/components/Pages/CallbackPage/CallbackPage.tsx +++ b/src/components/Pages/CallbackPage/CallbackPage.tsx @@ -1,4 +1,5 @@ import { useCallback, useContext, useEffect, useState } from 'react' +import { captureException } from '@sentry/react' import { ProviderType } from '@dcl/schemas' import { Button } from 'decentraland-ui/dist/components/Button/Button' import { Modal } from 'decentraland-ui/dist/components/Modal/Modal' @@ -64,6 +65,7 @@ export const CallbackPage = () => { redirect() } catch (error) { console.log(error) + captureException(error) navigate(locations.login()) } }, [navigate, redirectTo, connectAndGenerateSignature, redirect, flags[FeatureFlagsKeys.DAPPS_MAGIC_AUTO_SIGN]]) @@ -91,6 +93,7 @@ export const CallbackPage = () => { } } catch (error) { console.error('Error logging in', error) + captureException(error) getAnalytics()?.track(TrackingEvents.LOGIN_ERROR, { error: isErrorWithMessage(error) ? error.message : error }) await wait(800) navigate(locations.login()) diff --git a/src/components/Pages/LoginPage/LoginPage.tsx b/src/components/Pages/LoginPage/LoginPage.tsx index 7d672c3..e9991ab 100644 --- a/src/components/Pages/LoginPage/LoginPage.tsx +++ b/src/components/Pages/LoginPage/LoginPage.tsx @@ -1,4 +1,5 @@ import { useState, useCallback, useMemo, useEffect, useContext } from 'react' +import { captureException } from '@sentry/react' import { Env } from '@dcl/ui-env' import { Loader } from 'decentraland-ui/dist/components/Loader/Loader' import Image1 from '../../../assets/images/background/image1.webp' @@ -149,6 +150,7 @@ export const LoginPage = () => { setShowConnectionModal(false) } catch (error) { console.error('Error', isErrorWithMessage(error) ? error.message : JSON.stringify(error)) + captureException(error) getAnalytics()?.track(TrackingEvents.LOGIN_ERROR, { error: isErrorWithMessage(error) ? error.message : error }) if (isErrorWithName(error) && error.name === 'ErrorUnlockingWallet') { setConnectionModalState(ConnectionModalState.ERROR_LOCKED_WALLET) diff --git a/src/components/Pages/RequestPage/RequestPage.tsx b/src/components/Pages/RequestPage/RequestPage.tsx index 186e318..8078677 100644 --- a/src/components/Pages/RequestPage/RequestPage.tsx +++ b/src/components/Pages/RequestPage/RequestPage.tsx @@ -1,12 +1,12 @@ import { ReactNode, useCallback, useContext, useEffect, useRef, useState } from 'react' import { useParams } from 'react-router-dom' +import { captureException } from '@sentry/react' import { Profile } from 'dcl-catalyst-client/dist/client/specs/catalyst.schemas' import { ethers, BrowserProvider, formatEther } from 'ethers' import Icon from 'semantic-ui-react/dist/commonjs/elements/Icon/Icon' import { io } from 'socket.io-client' import { ChainId } from '@dcl/schemas' import { Button } from 'decentraland-ui/dist/components/Button/Button' -import { CommunityBubble } from 'decentraland-ui/dist/components/CommunityBubble' import { Loader } from 'decentraland-ui/dist/components/Loader/Loader' import { Web2TransactionModal } from 'decentraland-ui/dist/components/Web2TransactionModal' import { connection } from 'decentraland-connect' @@ -170,6 +170,7 @@ export const RequestPage = () => { } } catch (e) { setError(isErrorWithMessage(e) ? e.message : 'Unknown error') + captureException(e) getAnalytics()?.track(TrackingEvents.REQUEST_LOADING_ERROR, { browserTime: Date.now(), requestType: requestRef.current?.method, @@ -292,6 +293,7 @@ export const RequestPage = () => { } } catch (e) { console.error('Wallet error', JSON.stringify(e)) + captureException(e) const signer = await providerRef.current?.getSigner() if (signer) { if (isRpcError(e)) { @@ -352,7 +354,6 @@ export const RequestPage = () => { ) : null} - ) @@ -380,7 +381,6 @@ export const RequestPage = () => {
{connectedAccountRef.current && profile !== null ? : null}
- ) diff --git a/src/components/Pages/SetupPage/SetupPage.tsx b/src/components/Pages/SetupPage/SetupPage.tsx index 12074a7..322539d 100644 --- a/src/components/Pages/SetupPage/SetupPage.tsx +++ b/src/components/Pages/SetupPage/SetupPage.tsx @@ -1,4 +1,5 @@ import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react' +import { captureException } from '@sentry/react' import classNames from 'classnames' import { AuthIdentity } from '@dcl/crypto' import { Button } from 'decentraland-ui/dist/components/Button/Button' @@ -194,6 +195,7 @@ export const SetupPage = () => { try { await subscribeToNewsletter(email) } catch (e) { + captureException(e) console.warn('There was an error subscribing to the newsletter', (e as Error).message) } } @@ -210,6 +212,7 @@ export const SetupPage = () => { // Redirect to the site defined in the search params. redirect() } catch (e) { + captureException(e) setDeploying(false) // TODO: Display a proper error on the page to show the user. diff --git a/src/main.tsx b/src/main.tsx index 6e9b96c..402cc07 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -15,6 +15,7 @@ import { FeatureFlagsProvider } from './components/FeatureFlagsProvider' import { config } from './modules/config' import { getAnalytics } from './modules/analytics/segment' import './modules/analytics/snippet' +import './modules/analytics/sentry' import 'decentraland-ui/dist/themes/alternative/dark-theme.css' import './index.css' diff --git a/src/modules/analytics/sentry.ts b/src/modules/analytics/sentry.ts new file mode 100644 index 0000000..480bc73 --- /dev/null +++ b/src/modules/analytics/sentry.ts @@ -0,0 +1,16 @@ +import { init, browserTracingIntegration, replayIntegration } from '@sentry/react' +import { Env } from '@dcl/ui-env/dist/env' +import { config } from '../config' + +init({ + environment: config.get('ENVIRONMENT'), + release: `${config.get('SENTRY_RELEASE_PREFIX', 'auth')}@${process.env.VITE_REACT_APP_WEBSITE_VERSION}`, + dsn: config.get('SENTRY_DSN'), + integrations: [browserTracingIntegration(), replayIntegration()], + // Performance Monitoring + tracesSampleRate: 0.001, + // Session Replay + replaysSessionSampleRate: 0.01, + replaysOnErrorSampleRate: 0.01, + enabled: !config.is(Env.DEVELOPMENT) +}) diff --git a/src/modules/config/env/dev.json b/src/modules/config/env/dev.json index 302e0ca..81d922f 100644 --- a/src/modules/config/env/dev.json +++ b/src/modules/config/env/dev.json @@ -1,8 +1,10 @@ { + "ENVIRONMENT": "development", "AUTH_SERVER_URL": "https://auth-api.decentraland.zone", "SEGMENT_API_KEY": "FQqbzV2KeUKe2RPOeFkedKRPkJAFsU9r", "PEER_URL": "https://peer.decentraland.zone", "FEATURE_FLAGS_URL": "https://feature-flags.decentraland.org", + "SENTRY_DSN": "https://d0ec8d688f4d9827a270acece39153b0@o4504361728212992.ingest.us.sentry.io/4508858418266112", "FEATURE_FLAGS_INTERVAL": "60000", "BUILDER_SERVER_URL": "https://builder-api.decentraland.zone", "INTERCOM_APP_ID": "z0h94kay" diff --git a/src/modules/config/env/prod.json b/src/modules/config/env/prod.json index 66a1e72..27116c8 100644 --- a/src/modules/config/env/prod.json +++ b/src/modules/config/env/prod.json @@ -1,8 +1,10 @@ { + "ENVIRONMENT": "production", "AUTH_SERVER_URL": "https://auth-api.decentraland.org", "SEGMENT_API_KEY": "FQqbzV2KeUKe2RPOeFkedKRPkJAFsU9r", "PEER_URL": "https://peer.decentraland.org", "FEATURE_FLAGS_URL": "https://feature-flags.decentraland.org", + "SENTRY_DSN": "https://d0ec8d688f4d9827a270acece39153b0@o4504361728212992.ingest.us.sentry.io/4508858418266112", "FEATURE_FLAGS_INTERVAL": "60000", "BUILDER_SERVER_URL": "https://builder-api.decentraland.org", "INTERCOM_APP_ID": "z0h94kay" diff --git a/src/modules/config/env/stg.json b/src/modules/config/env/stg.json index 24c4d05..6978574 100644 --- a/src/modules/config/env/stg.json +++ b/src/modules/config/env/stg.json @@ -1,8 +1,10 @@ { + "ENVIRONMENT": "production", "AUTH_SERVER_URL": "https://auth-api.decentraland.today", "SEGMENT_API_KEY": "FQqbzV2KeUKe2RPOeFkedKRPkJAFsU9r", "PEER_URL": "https://peer-testing.decentraland.org", "FEATURE_FLAGS_URL": "https://feature-flags.decentraland.org", + "SENTRY_DSN": "https://d0ec8d688f4d9827a270acece39153b0@o4504361728212992.ingest.us.sentry.io/4508858418266112", "FEATURE_FLAGS_INTERVAL": "60000", "BUILDER_SERVER_URL": "https://builder-api.decentraland.today", "INTERCOM_APP_ID": "z0h94kay"