From 45adf5d5827f65b95d9a3e215e031c0ebb87f961 Mon Sep 17 00:00:00 2001 From: samshara Date: Mon, 27 Nov 2023 14:35:37 +0545 Subject: [PATCH 1/2] feat: setup sentry --- env.ts | 8 +++--- package.json | 1 + src/App/index.tsx | 8 +++--- src/config.ts | 12 +++++---- src/index.tsx | 56 +++++++++++++++++++++++++++++++++++++- yarn.lock | 69 ++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 141 insertions(+), 13 deletions(-) diff --git a/env.ts b/env.ts index 1d6356b4e..e6308547e 100644 --- a/env.ts +++ b/env.ts @@ -6,10 +6,12 @@ export default defineConfig({ APP_ENVIRONMENT: Schema.enum(['development', 'testing', 'staging', 'production'] as const), APP_MAPBOX_ACCESS_TOKEN: Schema.string(), APP_RISK_API_ENDPOINT: Schema.string({ format: 'url', protocol: true }), - APP_SENTRY_DSN: Schema.string.optional(), - APP_SENTRY_NORMALIZE_DEPTH: Schema.number.optional(), - APP_SENTRY_TRACES_SAMPLE_RATE: Schema.number.optional(), + APP_RISK_ADMIN_URL: Schema.string({ format: 'url', protocol: true }), APP_SHOW_ENV_BANNER: Schema.boolean.optional(), APP_TINY_API_KEY: Schema.string(), APP_TITLE: Schema.string(), + APP_SENTRY_DSN: Schema.string.optional(), + APP_SENTRY_TRACES_SAMPLE_RATE: Schema.number.optional(), + APP_SENTRY_REPLAYS_SESSION_SAMPLE_RATE: Schema.number.optional(), + APP_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE: Schema.number.optional(), }) diff --git a/package.json b/package.json index b395422f6..5cc28e80b 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "dependencies": { "@ifrc-go/icons": "^1.2.0", "@mapbox/mapbox-gl-draw": "^1.2.0", + "@sentry/react": "^7.81.1", "@tinymce/tinymce-react": "^4.3.0", "@togglecorp/fujs": "^2.0.0", "@togglecorp/re-map": "^0.2.0-beta-6", diff --git a/src/App/index.tsx b/src/App/index.tsx index 47023617f..f8d35058e 100644 --- a/src/App/index.tsx +++ b/src/App/index.tsx @@ -10,6 +10,7 @@ import { } from 'react-router-dom'; import mapboxgl from 'mapbox-gl'; import { isDefined, unique } from '@togglecorp/fujs'; +import * as Sentry from '@sentry/react'; import UserContext, { UserAuth, UserContextProps } from '#contexts/user'; import AlertContext, { AlertParams, AlertContextProps } from '#contexts/alert'; @@ -44,11 +45,11 @@ const requestContextValue = { transformResponse: processGoResponse, transformError: processGoError, }; - -const router = createBrowserRouter(unwrappedRoutes); +const sentryCreateBrowserRouter = Sentry.wrapCreateBrowserRouter(createBrowserRouter); +const router = sentryCreateBrowserRouter(unwrappedRoutes); mapboxgl.accessToken = mbtoken; -function App() { +function Application() { // ALERTS const [alerts, setAlerts] = useState([]); @@ -242,4 +243,5 @@ function App() { ); } +const App = Sentry.withProfiler(Application); export default App; diff --git a/src/config.ts b/src/config.ts index 408f3c3dd..5768010c2 100644 --- a/src/config.ts +++ b/src/config.ts @@ -6,12 +6,13 @@ const { APP_RISK_API_ENDPOINT, APP_TINY_API_KEY, APP_SHOW_ENV_BANNER, - APP_SENTRY_DSN, - APP_SENTRY_TRACES_SAMPLE_RATE, - APP_SENTRY_NORMALIZE_DEPTH, APP_TITLE, APP_COMMIT_HASH, APP_VERSION, + APP_SENTRY_DSN, + APP_SENTRY_TRACES_SAMPLE_RATE, + APP_SENTRY_REPLAYS_SESSION_SAMPLE_RATE, + APP_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE, } = import.meta.env; export const environment = APP_ENVIRONMENT; @@ -27,5 +28,6 @@ export const showEnvBanner = APP_SHOW_ENV_BANNER; export const riskApi = APP_RISK_API_ENDPOINT; export const tinyApiKey = APP_TINY_API_KEY; export const sentryAppDsn = APP_SENTRY_DSN; -export const sentryTraceSampleRate = APP_SENTRY_TRACES_SAMPLE_RATE; -export const sentryNormalizeDepth = APP_SENTRY_NORMALIZE_DEPTH; +export const sentryTracesSampleRate = APP_SENTRY_TRACES_SAMPLE_RATE; +export const sentryReplaysSessionSampleRate = APP_SENTRY_REPLAYS_SESSION_SAMPLE_RATE; +export const sentryReplaysOnErrorSampleRate = APP_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE; diff --git a/src/index.tsx b/src/index.tsx index 40efe4fb2..eabbb426d 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,12 +1,66 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; -import { isNotDefined } from '@togglecorp/fujs'; +import { isNotDefined, isDefined } from '@togglecorp/fujs'; +import * as Sentry from '@sentry/react'; +import { + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes, +} from 'react-router-dom'; +import { + appTitle, + appVersion, + appCommitHash, + api, + environment, + sentryAppDsn, + sentryReplaysOnErrorSampleRate, + sentryReplaysSessionSampleRate, + sentryTracesSampleRate, +} from '#config'; import 'mapbox-gl/dist/mapbox-gl.css'; import './index.css'; import App from './App/index.tsx'; +if (isDefined(sentryAppDsn)) { + Sentry.init({ + dsn: sentryAppDsn, + release: `${appTitle}@${appVersion}+${appCommitHash}`, + environment, + integrations: [ + new Sentry.BrowserTracing({ + routingInstrumentation: Sentry.reactRouterV6Instrumentation( + React.useEffect, + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes, + ), + }), + new Sentry.Replay(), + ], + + // Set tracesSampleRate to 1.0 to capture 100% + // of transactions for performance monitoring. + tracesSampleRate: Number(sentryTracesSampleRate), + + // Set `tracePropagationTargets` to control for which URLs distributed + // tracing should be enabled + tracePropagationTargets: [ + api, + // riskApi, TODO: let's add this once sentry is configured for risk server + ], + + // Capture Replay for (sentryReplaysSessionSampleRate)% of all sessions, + // plus for (sentryReplaysOnErrorSampleRate)% of sessions with an error + replaysSessionSampleRate: Number(sentryReplaysSessionSampleRate), + replaysOnErrorSampleRate: Number(sentryReplaysOnErrorSampleRate), + }); +} + const webappRootId = 'webapp-root'; const webappRootElement = document.getElementById(webappRootId); diff --git a/yarn.lock b/yarn.lock index 57d598fd8..8798f89ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -877,6 +877,66 @@ estree-walker "^2.0.2" picomatch "^2.3.1" +"@sentry-internal/tracing@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.81.1.tgz#1180365cd8a9e18cb0f92e1ea970161840ec0e2e" + integrity sha512-E5xm27xrLXL10knH2EWDQsQYh5nb4SxxZzJ3sJwDGG9XGKzBdlp20UUhKqx00wixooVX9uCj3e4Jg8SvNB1hKg== + dependencies: + "@sentry/core" "7.81.1" + "@sentry/types" "7.81.1" + "@sentry/utils" "7.81.1" + +"@sentry/browser@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.81.1.tgz#5ee6ae3679ee80f444d2e8c5662430e7a734ae50" + integrity sha512-DNtS7bZEnFPKVoGazKs5wHoWC0FwsOFOOMNeDvEfouUqKKbjO7+RDHbr7H6Bo83zX4qmZWRBf8V+3n3YPIiJFw== + dependencies: + "@sentry-internal/tracing" "7.81.1" + "@sentry/core" "7.81.1" + "@sentry/replay" "7.81.1" + "@sentry/types" "7.81.1" + "@sentry/utils" "7.81.1" + +"@sentry/core@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.81.1.tgz#082fd9122bf9a488c8e05b1754724ddbc2d5cf30" + integrity sha512-tU37yAmckOGCw/moWKSwekSCWWJP15O6luIq+u7wal22hE88F3Vc5Avo8SeF3upnPR+4ejaOFH+BJTr6bgrs6Q== + dependencies: + "@sentry/types" "7.81.1" + "@sentry/utils" "7.81.1" + +"@sentry/react@^7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.81.1.tgz#6a94e8e373a5bf27330cea2eb1a603ae0eb0b8ba" + integrity sha512-kk0plP/mf8KgVLOiImIpp1liYysmh3Un8uXcVAToomSuHZPGanelFAdP0XhY+0HlWU9KIfxTjhMte1iSwQ8pYw== + dependencies: + "@sentry/browser" "7.81.1" + "@sentry/types" "7.81.1" + "@sentry/utils" "7.81.1" + hoist-non-react-statics "^3.3.2" + +"@sentry/replay@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.81.1.tgz#a656d55e2a00b34e42be6eeb79018d21efc223af" + integrity sha512-4ueT0C4bYjngN/9p0fEYH10dTMLovHyk9HxJ6zSTgePvGVexhg+cSEHXisoBDwHeRZVnbIvsVM0NA7rmEDXJJw== + dependencies: + "@sentry-internal/tracing" "7.81.1" + "@sentry/core" "7.81.1" + "@sentry/types" "7.81.1" + "@sentry/utils" "7.81.1" + +"@sentry/types@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.81.1.tgz#2b2551fc291e1089651fd574a68f7c4175878bd5" + integrity sha512-dvJvGyctiaPMIQqa46k56Re5IODWMDxiHJ1UjBs/WYDLrmWFPGrEbyJ8w8CYLhYA+7qqrCyIZmHbWSTRIxstHw== + +"@sentry/utils@7.81.1": + version "7.81.1" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.81.1.tgz#42f3e77baf90205cec1f8599eb8445a6918030bd" + integrity sha512-gq+MDXIirHKxNZ+c9/lVvCXd6y2zaZANujwlFggRH2u9SRiPaIXVilLpvMm4uJqmqBMEcY81ArujExtHvkbCqg== + dependencies: + "@sentry/types" "7.81.1" + "@svgr/babel-plugin-add-jsx-attribute@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-7.0.0.tgz#80856c1b7a3b7422d232f6e079f0beb90c4a13e9" @@ -4268,6 +4328,13 @@ hat@0.0.3: resolved "https://registry.yarnpkg.com/hat/-/hat-0.0.3.tgz#bb014a9e64b3788aed8005917413d4ff3d502d8a" integrity sha512-zpImx2GoKXy42fVDSEad2BPKuSQdLcqsCYa48K3zHSzM/ugWuYjLDr8IXxpVuL7uCLHw56eaiLxCRthhOzf5ug== +hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + home-or-tmp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" @@ -6209,7 +6276,7 @@ react-focus-on@^3.8.1: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" -react-is@^16.13.1: +react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== From 9e0d7c6d816e88b6943dec224f5f27ff904475a5 Mon Sep 17 00:00:00 2001 From: samshara Date: Tue, 28 Nov 2023 17:18:59 +0545 Subject: [PATCH 2/2] feat: add google analytics integration --- env.ts | 1 + package.json | 1 + vite.config.ts | 14 +++++++++++--- yarn.lock | 5 +++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/env.ts b/env.ts index e6308547e..38e100277 100644 --- a/env.ts +++ b/env.ts @@ -14,4 +14,5 @@ export default defineConfig({ APP_SENTRY_TRACES_SAMPLE_RATE: Schema.number.optional(), APP_SENTRY_REPLAYS_SESSION_SAMPLE_RATE: Schema.number.optional(), APP_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE: Schema.number.optional(), + APP_GOOGLE_ANALYTICS_ID: Schema.string.optional(), }) diff --git a/package.json b/package.json index 5cc28e80b..ebba7ff6b 100644 --- a/package.json +++ b/package.json @@ -96,6 +96,7 @@ "vite": "^4.3.2", "vite-plugin-checker": "^0.6.0", "vite-plugin-compression2": "^0.9.1", + "vite-plugin-radar": "^0.9.1", "vite-plugin-svgr": "^3.2.0", "vite-plugin-webfont-dl": "^3.7.4", "vite-tsconfig-paths": "^4.2.0", diff --git a/vite.config.ts b/vite.config.ts index 4a85396cf..b44219ac0 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,4 +1,4 @@ -import { defineConfig } from 'vite'; +import { defineConfig, loadEnv } from 'vite'; import tsconfigPaths from 'vite-tsconfig-paths'; import webfontDownload from 'vite-plugin-webfont-dl'; import reactSwc from '@vitejs/plugin-react-swc'; @@ -7,7 +7,8 @@ import { compression } from 'vite-plugin-compression2'; import checker from 'vite-plugin-checker'; import { visualizer } from 'rollup-plugin-visualizer'; import { ValidateEnv as validateEnv } from '@julr/vite-plugin-validate-env'; -import svgr from "vite-plugin-svgr"; +import { VitePluginRadar } from 'vite-plugin-radar' +import svgr from 'vite-plugin-svgr'; import envConfig from './env'; @@ -16,10 +17,12 @@ const commitHash = execSync('git rev-parse --short HEAD').toString(); export default defineConfig(({ mode }) => { const isProd = mode === 'production'; + const env = loadEnv(mode, process.cwd(), '') + return { define: { 'import.meta.env.APP_COMMIT_HASH': JSON.stringify(commitHash), - 'import.meta.env.APP_VERSION': JSON.stringify(process.env.npm_package_version), + 'import.meta.env.APP_VERSION': JSON.stringify(env.npm_package_version), }, plugins: [ isProd ? checker({ @@ -38,6 +41,11 @@ export default defineConfig(({ mode }) => { validateEnv(envConfig), isProd ? compression() : undefined, isProd ? visualizer({ sourcemap: true }) : undefined, + VitePluginRadar({ + analytics: { + id: env.APP_GOOGLE_ANALYTICS_ID, + }, + }) ], css: { devSourcemap: isProd, diff --git a/yarn.lock b/yarn.lock index 8798f89ef..9f4123b26 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7759,6 +7759,11 @@ vite-plugin-compression2@^0.9.1: dependencies: "@rollup/pluginutils" "^5.0.2" +vite-plugin-radar@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/vite-plugin-radar/-/vite-plugin-radar-0.9.1.tgz#1ee8866cb2f2275f3eb56bfe49fea82bbdd673d2" + integrity sha512-stnb+LxeEKobcesXW2JA0OdCaBRgR/zZwN6ACXZf1gF9MNR689aiK5UlgTVmrpUnEcPucO9U0M0WHnuM6NXPsA== + vite-plugin-svgr@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/vite-plugin-svgr/-/vite-plugin-svgr-3.2.0.tgz#920375aaf6635091c9ac8e467825f92d32544476"