From 0a9151fb1e3b2cad817d8656665b72900d0b1d7e Mon Sep 17 00:00:00 2001 From: Clemence Kyara Date: Sat, 22 Jun 2024 12:01:42 +0300 Subject: [PATCH 1/5] Add and instrument Sentry --- apps/roboshield/instrumentation.ts | 9 +++++++ apps/roboshield/next.config.mjs | 36 ++++++++++++++++++++++++- apps/roboshield/package.json | 1 + apps/roboshield/sentry.client.config.ts | 30 +++++++++++++++++++++ apps/roboshield/sentry.edge.config.ts | 16 +++++++++++ apps/roboshield/sentry.server.config.ts | 18 +++++++++++++ apps/roboshield/src/pages/_error.jsx | 17 ++++++++++++ 7 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 apps/roboshield/instrumentation.ts create mode 100644 apps/roboshield/sentry.client.config.ts create mode 100644 apps/roboshield/sentry.edge.config.ts create mode 100644 apps/roboshield/sentry.server.config.ts create mode 100644 apps/roboshield/src/pages/_error.jsx diff --git a/apps/roboshield/instrumentation.ts b/apps/roboshield/instrumentation.ts new file mode 100644 index 000000000..f8a929ba4 --- /dev/null +++ b/apps/roboshield/instrumentation.ts @@ -0,0 +1,9 @@ +export async function register() { + if (process.env.NEXT_RUNTIME === "nodejs") { + await import("./sentry.server.config"); + } + + if (process.env.NEXT_RUNTIME === "edge") { + await import("./sentry.edge.config"); + } +} diff --git a/apps/roboshield/next.config.mjs b/apps/roboshield/next.config.mjs index 85d7abfdf..38c5c24cd 100644 --- a/apps/roboshield/next.config.mjs +++ b/apps/roboshield/next.config.mjs @@ -1,3 +1,4 @@ +import { withSentryConfig } from "@sentry/nextjs"; import path from "path"; const PROJECT_ROOT = process.env.PROJECT_ROOT?.trim(); @@ -32,4 +33,37 @@ const nextConfig = { }, }; -export default nextConfig; +export default withSentryConfig(nextConfig, { + // For all available options, see: + // https://github.com/getsentry/sentry-webpack-plugin#options + + org: process.env.SENTRY_ORG, + project: process.env.SENTRY_PROJECT, + + // Only print logs for uploading source maps in CI + silent: !process.env.CI, + + // For all available options, see: + // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/ + + // Upload a larger set of source maps for prettier stack traces (increases build time) + widenClientFileUpload: true, + + // Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers. + // This can increase your server load as well as your hosting bill. + // Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client- + // side errors will fail. + tunnelRoute: "/monitoring", + + // Hides source maps from generated client bundles + hideSourceMaps: true, + + // Automatically tree-shake Sentry logger statements to reduce bundle size + disableLogger: true, + + // Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.) + // See the following for more information: + // https://docs.sentry.io/product/crons/ + // https://vercel.com/docs/cron-jobs + automaticVercelMonitors: true, +}); diff --git a/apps/roboshield/package.json b/apps/roboshield/package.json index 1e5bf3b9a..0f0d4b773 100644 --- a/apps/roboshield/package.json +++ b/apps/roboshield/package.json @@ -23,6 +23,7 @@ "@mui/utils": "^5.15.14", "@mui/x-date-pickers": "^7.6.2", "@next/env": "^14.2.3", + "@sentry/nextjs": "^8.10.0", "ace-builds": "^1.34.2", "crawler-user-agents": "^1.0.142", "date-fns": "^3.6.0", diff --git a/apps/roboshield/sentry.client.config.ts b/apps/roboshield/sentry.client.config.ts new file mode 100644 index 000000000..bc8c8f2e8 --- /dev/null +++ b/apps/roboshield/sentry.client.config.ts @@ -0,0 +1,30 @@ +// This file configures the initialization of Sentry on the client. +// The config you add here will be used whenever a users loads a page in their browser. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, + + // Adjust this value in production, or use tracesSampler for greater control + tracesSampleRate: 1, + + // Setting this option to true will print useful information to the console while you're setting up Sentry. + debug: false, + + replaysOnErrorSampleRate: 1.0, + + // This sets the sample rate to be 10%. You may want this to be 100% while + // in development and sample at a lower rate in production + replaysSessionSampleRate: 0.1, + + // You can remove this option if you're not planning to use the Sentry Session Replay feature: + integrations: [ + Sentry.replayIntegration({ + // Additional Replay configuration goes in here, for example: + maskAllText: true, + blockAllMedia: true, + }), + ], +}); diff --git a/apps/roboshield/sentry.edge.config.ts b/apps/roboshield/sentry.edge.config.ts new file mode 100644 index 000000000..efc59b6ad --- /dev/null +++ b/apps/roboshield/sentry.edge.config.ts @@ -0,0 +1,16 @@ +// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on). +// The config you add here will be used whenever one of the edge features is loaded. +// Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, + + // Adjust this value in production, or use tracesSampler for greater control + tracesSampleRate: 1, + + // Setting this option to true will print useful information to the console while you're setting up Sentry. + debug: false, +}); diff --git a/apps/roboshield/sentry.server.config.ts b/apps/roboshield/sentry.server.config.ts new file mode 100644 index 000000000..4ecf38688 --- /dev/null +++ b/apps/roboshield/sentry.server.config.ts @@ -0,0 +1,18 @@ +// This file configures the initialization of Sentry on the server. +// The config you add here will be used whenever the server handles a request. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, + + // Adjust this value in production, or use tracesSampler for greater control + tracesSampleRate: 1, + + // Setting this option to true will print useful information to the console while you're setting up Sentry. + debug: false, + + // Uncomment the line below to enable Spotlight (https://spotlightjs.com) + // spotlight: process.env.NODE_ENV === 'development', +}); diff --git a/apps/roboshield/src/pages/_error.jsx b/apps/roboshield/src/pages/_error.jsx new file mode 100644 index 000000000..e495b108e --- /dev/null +++ b/apps/roboshield/src/pages/_error.jsx @@ -0,0 +1,17 @@ +import * as Sentry from "@sentry/nextjs"; +import Error from "next/error"; + +const CustomError = (props) => { + return ; +}; + +CustomError.getInitialProps = async (contextData) => { + // In case this is running in a serverless function, await this in order to give Sentry + // time to send the error before the lambda exits + await Sentry.captureUnderscoreErrorException(contextData); + + // This will contain the status code of the response + return Error.getInitialProps(contextData); +}; + +export default CustomError; From ec7b20e5063096bfa995f1fb1cbb53d7c1bcadec Mon Sep 17 00:00:00 2001 From: Clemence Kyara Date: Sat, 22 Jun 2024 12:02:24 +0300 Subject: [PATCH 2/5] Add env var support for Sentry --- apps/roboshield/.env | 3 +++ apps/roboshield/.env.template | 19 +++++++++++++++++++ .../src/components/Timepicker/TimePicker.tsx | 4 ++-- 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 apps/roboshield/.env create mode 100644 apps/roboshield/.env.template diff --git a/apps/roboshield/.env b/apps/roboshield/.env new file mode 100644 index 000000000..aad2d5819 --- /dev/null +++ b/apps/roboshield/.env @@ -0,0 +1,3 @@ +SENTRY_ENV=local +SENTRY_ORG=code-for-africa +SENTRY_PROJECT=roboshield diff --git a/apps/roboshield/.env.template b/apps/roboshield/.env.template new file mode 100644 index 000000000..678dac1a0 --- /dev/null +++ b/apps/roboshield/.env.template @@ -0,0 +1,19 @@ +# Required +# -------- + +# Optional +# -------- +# Defaults to 'localhost' +NEXT_HOSTNAME +# Defaults to http://localhost:3000. +NEXT_PUBLIC_APP_URL +# Defaults to 3000. +PORT +# https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/ +NEXT_PUBLIC_SENTRY_DSN= +# Defaults to local +SENTRY_ENV=local|development|staging|production +# Defaults to code-for-africa +SENTRY_ORG= +# Defaults to roboshield +SENTRY_PROJECT= diff --git a/apps/roboshield/src/components/Timepicker/TimePicker.tsx b/apps/roboshield/src/components/Timepicker/TimePicker.tsx index a9b1dc82b..1b6f633ca 100644 --- a/apps/roboshield/src/components/Timepicker/TimePicker.tsx +++ b/apps/roboshield/src/components/Timepicker/TimePicker.tsx @@ -18,11 +18,11 @@ export default function TimePicker({ ); From a20f15ba1ebca472c4eef09d971b900af35b0283 Mon Sep 17 00:00:00 2001 From: Clemence Kyara Date: Sat, 22 Jun 2024 12:03:19 +0300 Subject: [PATCH 3/5] Update workflows to work properly with Sentry --- .github/workflows/codeforafrica-deploy-dev-app.yml | 9 +++++++-- .github/workflows/codeforafrica-deploy-prod.yml | 9 +++++++-- .github/workflows/pesayetu-deploy-dev.yml | 9 +++++++-- .github/workflows/roboshield-deploy-dev.yml | 14 ++++++++++++-- .gitignore | 1 + 5 files changed, 34 insertions(+), 8 deletions(-) diff --git a/.github/workflows/codeforafrica-deploy-dev-app.yml b/.github/workflows/codeforafrica-deploy-dev-app.yml index df9a387b3..bca8123d7 100644 --- a/.github/workflows/codeforafrica-deploy-dev-app.yml +++ b/.github/workflows/codeforafrica-deploy-dev-app.yml @@ -13,12 +13,13 @@ concurrency: cancel-in-progress: true env: + APP_NAME: codeforafrica-ui DOKKU_REMOTE_BRANCH: "master" DOKKU_REMOTE_URL: "ssh://azureuser@ui-1.dev.codeforafrica.org" + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} IMAGE_NAME: "codeforafrica/codeforafrica-ui" NEXT_PUBLIC_APP_URL: "https://codeforafrica-ui.dev.codeforafrica.org" - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - APP_NAME: codeforafrica-ui + SENTRY_ENV: "development" jobs: deploy: @@ -59,6 +60,10 @@ jobs: PAYLOAD_SECRET=${{ secrets.CODEFORAFRICA_PAYLOAD_SECRET }} NEXT_PUBLIC_APP_LOGO_URL=${{ secrets.NEXT_PUBLIC_CODEFORAFRICA_APP_LOGO_URL }} NEXT_PUBLIC_APP_NAME=${{ secrets.NEXT_PUBLIC_CODEFORAFRICA_APP_NAME }} + SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ENV=${{ env.SENTRY_ENV }} + SENTRY_ORG=${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT=${{ secrets.CODEFORAFRICA_SENTRY_PROJECT }} cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new context: . diff --git a/.github/workflows/codeforafrica-deploy-prod.yml b/.github/workflows/codeforafrica-deploy-prod.yml index 6f6659d77..af5cabb84 100644 --- a/.github/workflows/codeforafrica-deploy-prod.yml +++ b/.github/workflows/codeforafrica-deploy-prod.yml @@ -10,13 +10,14 @@ concurrency: cancel-in-progress: true env: + APP: "codeforafrica" DOKKU_REMOTE_BRANCH: "master" DOKKU_REMOTE_URL: "ssh://dokku@ui-1.prod.codeforafrica.org/codeforafrica-ui" + GIT_PUSH_FLAGS: "--force" IMAGE_NAME: "codeforafrica/codeforafrica-ui" - APP: "codeforafrica" VERSION_FILE_NAME: "./apps/codeforafrica/package.json" - GIT_PUSH_FLAGS: "--force" NEXT_PUBLIC_APP_URL: "https://cfa.dev.codeforafrica.org" + SENTRY_ENV: "production" jobs: deploy: @@ -80,6 +81,10 @@ jobs: NEXT_PUBLIC_APP_NAME=${{ secrets.NEXT_PUBLIC_CODEFORAFRICA_APP_NAME }} NEXT_PUBLIC_APP_URL=${{ env.NEXT_PUBLIC_APP_URL }} PAYLOAD_SECRET=${{ secrets.CODEFORAFRICA_PAYLOAD_SECRET }} + SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ENV=${{ env.SENTRY_ENV }} + SENTRY_ORG=${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT=${{ secrets.CODEFORAFRICA_SENTRY_PROJECT }} cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new context: . diff --git a/.github/workflows/pesayetu-deploy-dev.yml b/.github/workflows/pesayetu-deploy-dev.yml index 84a8309fc..6d16ef6b0 100644 --- a/.github/workflows/pesayetu-deploy-dev.yml +++ b/.github/workflows/pesayetu-deploy-dev.yml @@ -13,12 +13,13 @@ concurrency: cancel-in-progress: true env: + APP_NAME: pesayetu-ui DOKKU_REMOTE_BRANCH: "master" DOKKU_REMOTE_URL: "ssh://azureuser@ui-1.dev.codeforafrica.org" IMAGE_NAME: "codeforafrica/pesayetu-ui" - NEXT_PUBLIC_APP_URL: "https://pesayetu-ui.dev.codeforafrica.org" GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - APP_NAME: pesayetu-ui + NEXT_PUBLIC_APP_URL: "https://pesayetu-ui.dev.codeforafrica.org" + SENTRY_ENV: "development" jobs: deploy: @@ -61,6 +62,10 @@ jobs: WORDPRESS_APPLICATION_PASSWORD=${{ secrets.PESAYETU_WORDPRESS_APPLICATION_PASSWORD }} JWT_SECRET_KEY=${{ secrets.PESAYETU_JWT_SECRET_KEY }} HURUMAP_API_URL=${{ secrets.PESAYETU_HURUMAP_API_URL }} + SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ENV=${{ env.SENTRY_ENV }} + SENTRY_ORG=${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT=${{ secrets.PESAYETU_SENTRY_PROJECT }} cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new context: . diff --git a/.github/workflows/roboshield-deploy-dev.yml b/.github/workflows/roboshield-deploy-dev.yml index 9f5b4f960..905282f45 100644 --- a/.github/workflows/roboshield-deploy-dev.yml +++ b/.github/workflows/roboshield-deploy-dev.yml @@ -13,12 +13,13 @@ concurrency: cancel-in-progress: true env: + APP_NAME: roboshield-ui DOKKU_REMOTE_BRANCH: "master" DOKKU_REMOTE_URL: "ssh://azureuser@ui-1.dev.codeforafrica.org" + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} IMAGE_NAME: "codeforafrica/roboshield" NEXT_PUBLIC_APP_URL: "https://roboshield-ui.dev.codeforafrica.org" - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - APP_NAME: roboshield-ui + SENTRY_ENV: "development" jobs: deploy: @@ -53,6 +54,15 @@ jobs: - name: Build Docker image uses: docker/build-push-action@v3 with: + build-args: | + MONGO_URL=${{ secrets.CHARTERAFRICA_MONGO_URL }} + NEXT_PUBLIC_APP_URL=${{ env.NEXT_PUBLIC_APP_URL }} + NEXT_PUBLIC_SENTRY_DSN=${{ secrets.CHARTERAFRICA_SENTRY_DSN }} + PAYLOAD_SECRET_KEY=${{ secrets.CHARTERAFRICA_PAYLOAD_SECRET_KEY }} + SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ENV=${{ env.SENTRY_ENV }} + SENTRY_ORG=${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT=${{ secrets.ROBOSHIELD_SENTRY_PROJECT }} cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new context: . diff --git a/.gitignore b/.gitignore index 898fcc87c..9d9580e86 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ credentials.json # Sentry Config File .sentryclirc +.env.sentry-build-plugin # SQLite files **.db From 8c5d5874e055b153ec1e0aa6d213c3481891a74e Mon Sep 17 00:00:00 2001 From: Clemence Kyara Date: Sat, 22 Jun 2024 12:04:07 +0300 Subject: [PATCH 4/5] Add Sentry support to Dockerfile --- roboshield.Dockerfile | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/roboshield.Dockerfile b/roboshield.Dockerfile index e98cc72ba..77838339b 100644 --- a/roboshield.Dockerfile +++ b/roboshield.Dockerfile @@ -53,9 +53,15 @@ ARG NEXT_TELEMETRY_DISABLED=1 \ # Needed by Next.js at build time NEXT_PUBLIC_APP_NAME=RoboShield \ NEXT_PUBLIC_APP_URL=http://localhost:3000 \ + NEXT_PUBLIC_SENTRY_DSN="" \ NEXT_PUBLIC_SEO_DISABLED="true" \ # Needed by Next.js and server.ts at build time - PORT=3000 + PORT=3000 \ + # Sentry config for source maps upload (needed at build time only) + SENTRY_AUTH_TOKEN="" \ + SENTRY_ENV="" \ + SENTRY_ORG="" \ + SENTRY_PROJECT="" COPY --from=deps /workspace/node_modules ./node_modules COPY --from=deps /workspace/packages/commons-ui-core/node_modules ./packages/commons-ui-core/node_modules @@ -77,12 +83,16 @@ FROM base as runner ARG NEXT_TELEMETRY_DISABLED \ NEXT_PUBLIC_APP_NAME \ NEXT_PUBLIC_APP_URL \ - PORT + NEXT_PUBLIC_SENTRY_DSN \ + PORT \ + SENTRY_ENV ENV NODE_ENV=production \ NEXT_PUBLIC_APP_NAME=${NEXT_PUBLIC_APP_NAME} \ NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL} \ - PORT=${PORT} + NEXT_PUBLIC_SENTRY_DSN=${NEXT_PUBLIC_SENTRY_DSN} \ + PORT=${PORT} \ + SENTRY_ENV=${SENTRY_ENV} RUN set -ex \ # Create a non-root user From 9231183a01b72e7a83561d4024380723a8d6fed7 Mon Sep 17 00:00:00 2001 From: Clemence Kyara Date: Sat, 22 Jun 2024 12:04:40 +0300 Subject: [PATCH 5/5] Update lockfile --- pnpm-lock.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 771b10735..ea80cc2c2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1012,6 +1012,9 @@ importers: '@next/env': specifier: ^14.2.3 version: 14.2.4 + '@sentry/nextjs': + specifier: ^8.10.0 + version: 8.11.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.25.1)(encoding@0.1.13)(next@14.2.4(@babel/core@7.24.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.44.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.69.4))(react@18.3.1)(webpack@5.92.1) ace-builds: specifier: ^1.34.2 version: 1.35.0