From 8bf4945328f09efae4d4b28c43297ad851c1ec00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Rialland?= Date: Mon, 25 Sep 2023 16:01:42 +0200 Subject: [PATCH] Migrate sentry v6 to v7 --- .github/workflows/deploy.yaml | 1 + api/package.json | 2 +- api/source/index.ts | 6 +- api/source/sentry.ts | 52 ++++++------- site/.env.template | 1 + site/package.json | 2 +- site/source/api/sentry.ts | 38 +++++++--- site/vite.config.ts | 26 ++++++- yarn.lock | 135 +++++++++++++++++++++++++--------- 9 files changed, 178 insertions(+), 85 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 8d6c13386..7ecb9ef98 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -59,6 +59,7 @@ jobs: - name: Build app run: yarn workspace site build env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} VITE_AT_INTERNET_SITE_ID: ${{ needs.deploy-context.outputs.env-name == 'master' && 617190 || 617189 }} VITE_ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }} VITE_ALGOLIA_SEARCH_KEY: ${{secrets.ALGOLIA_SEARCH_KEY}} diff --git a/api/package.json b/api/package.json index 1349ee7cf..2b26d2a59 100644 --- a/api/package.json +++ b/api/package.json @@ -33,7 +33,7 @@ "@koa/router": "^12.0.0", "@publicodes/api": "^1.0.0-beta.74", "@sentry/node": "^7.70.0", - "@sentry/tracing": "^7.70.0", + "@sentry/utils": "^7.70.0", "got": "^13.0.0", "ioredis": "^5.3.2", "ioredis-mock": "^8.8.3", diff --git a/api/source/index.ts b/api/source/index.ts index 1a84d45a4..a3163a356 100644 --- a/api/source/index.ts +++ b/api/source/index.ts @@ -29,9 +29,9 @@ if (process.env.NODE_ENV === 'production') { app.on('error', (err, ctx: RouterContext) => { Sentry.withScope((scope) => { - scope.addEventProcessor((event) => { - return Sentry.Handlers.parseRequest(event, ctx.request) - }) + scope.addEventProcessor((event) => + Sentry.addRequestDataToEvent(event, ctx.request) + ) Sentry.captureException(err) }) }) diff --git a/api/source/sentry.ts b/api/source/sentry.ts index 3ca66c757..4dedd5796 100644 --- a/api/source/sentry.ts +++ b/api/source/sentry.ts @@ -1,9 +1,6 @@ -// eslint-disable-next-line n/no-deprecated-api -import Domains from 'domain' - import { RouterContext } from '@koa/router' -import * as Sentry from '@sentry/node' -import * as Tracing from '@sentry/tracing' +import Sentry from '@sentry/node' +import { stripUrlQueryAndFragment } from '@sentry/utils' import { Context, Next } from 'koa' const release = @@ -20,43 +17,38 @@ Sentry.init({ tracesSampleRate: 0.5, release, environment: release.includes('api-pr') ? 'test' : 'production', + + integrations: [ + // Automatically instrument Node.js libraries and frameworks + ...Sentry.autoDiscoverNodePerformanceMonitoringIntegrations(), + ], }) export default Sentry -// not mandatory, but adding domains does help a lot with breadcrumbs -export const requestHandler = (ctx: Context, next: Next) => { - return new Promise((resolve) => { - const local = Domains.create() - local.add(ctx as never) - local.on('error', (err) => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - ctx.status = (err.status as number) || 500 - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - ctx.body = err.message - ctx.app.emit('error', err, ctx) - }) - void local.run(async () => { - Sentry.getCurrentHub().configureScope((scope) => - scope.addEventProcessor((event) => - Sentry.Handlers.parseRequest(event, ctx.request, { user: false }) - ) +export const requestHandler = async (ctx: Context, next: Next) => + Sentry.runWithAsyncContext(() => { + const hub = Sentry.getCurrentHub() + hub.configureScope((scope) => + scope.addEventProcessor((event) => + Sentry.addRequestDataToEvent(event, ctx.request, { + include: { user: false }, + }) ) - await next() - resolve() - }) + ) + + return next() }) -} // this tracing middleware creates a transaction per request export const tracingMiddleWare = async (ctx: RouterContext, next: Next) => { const reqMethod = (ctx.method || '').toUpperCase() - const reqUrl = ctx.url && Tracing.stripUrlQueryAndFragment(ctx.url) + const reqUrl = ctx.url && stripUrlQueryAndFragment(ctx.url) // connect to trace of upstream app let traceparentData if (ctx.request.get('sentry-trace')) { - traceparentData = Tracing.extractTraceparentData( + traceparentData = Sentry.extractTraceparentData( ctx.request.get('sentry-trace') ) } @@ -80,9 +72,7 @@ export const tracingMiddleWare = async (ctx: RouterContext, next: Next) => { // if using koa router, a nicer way to capture transaction using the matched route if (ctx._matchedRoute) { const mountPath = (ctx.mountPath as undefined | string) || '' - transaction.setName( - `${reqMethod} ${mountPath}${ctx._matchedRoute.toString()}` - ) + transaction.setName(`${reqMethod} ${mountPath}${ctx._matchedRoute}`) } transaction.setHttpStatus(ctx.status) transaction.finish() diff --git a/site/.env.template b/site/.env.template index 0723bd272..b8c00ca8a 100644 --- a/site/.env.template +++ b/site/.env.template @@ -6,6 +6,7 @@ ATINTERNET_API_SECRET_KEY= DEEPL_API_SECRET= ZAMMAD_API_SECRET_KEY= PLAUSIBLE_API_KEY= +SENTRY_AUTH_TOKEN= # Utilisez votre propre token (voir issue en haut pour en créé un) GITHUB_API_SECRET= diff --git a/site/package.json b/site/package.json index 79c5b6176..ecc92ad49 100644 --- a/site/package.json +++ b/site/package.json @@ -60,7 +60,6 @@ "@react-pdf/renderer": "^3.1.12", "@sentry/integrations": "^7.70.0", "@sentry/react": "^7.70.0", - "@sentry/tracing": "^7.70.0", "algoliasearch": "^4.20.0", "date-fns": "^2.30.0", "exoneration-covid": "workspace:^", @@ -104,6 +103,7 @@ "@rollup/plugin-replace": "^5.0.2", "@rollup/plugin-yaml": "^4.1.1", "@rushstack/package-deps-hash": "^3.2.67", + "@sentry/vite-plugin": "^2.7.1", "@storybook/addon-a11y": "^7.4.2", "@storybook/addon-actions": "^7.4.2", "@storybook/addon-essentials": "^7.4.2", diff --git a/site/source/api/sentry.ts b/site/source/api/sentry.ts index 4b7a42c58..15c8d7eba 100644 --- a/site/source/api/sentry.ts +++ b/site/source/api/sentry.ts @@ -1,28 +1,42 @@ import { CaptureConsole } from '@sentry/integrations' -import { init } from '@sentry/react' -import { BrowserTracing } from '@sentry/tracing' +import { + BrowserTracing, + init, + reactRouterV6Instrumentation, +} from '@sentry/react' +import { useEffect } from 'react' +import { + createRoutesFromChildren, + matchRoutes, + useLocation, + useNavigationType, +} from 'react-router-dom' -const branch = BRANCH_NAME - -if (branch && IS_STAGING) { +if (BRANCH_NAME && IS_STAGING) { // eslint-disable-next-line no-console console.info( - `ℹ Vous êtes sur la branche : %c${branch}`, + `ℹ Vous êtes sur la branche : %c${BRANCH_NAME}`, 'font-weight: bold; text-decoration: underline;' ) } -const release = - branch && `${branch}-` + import.meta.env.VITE_GITHUB_SHA?.substring(0, 7) - -if (IS_PRODUCTION) { +if (!import.meta.env.SSR && (IS_PRODUCTION || IS_STAGING)) { init({ dsn: 'https://d857393f4cfb40eebc0b9b54893bab23@sentry.incubateur.net/9', integrations: [ - new BrowserTracing(), new CaptureConsole({ levels: ['error'] }), + new BrowserTracing({ + routingInstrumentation: reactRouterV6Instrumentation( + useEffect, + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes + ), + }), ], - release, + normalizeDepth: 10, + enableTracing: true, // Set tracesSampleRate to 1.0 to capture 100% // of transactions for performance monitoring. // We recommend adjusting this value in production diff --git a/site/vite.config.ts b/site/vite.config.ts index 75aefcf90..194ceee8c 100644 --- a/site/vite.config.ts +++ b/site/vite.config.ts @@ -5,6 +5,7 @@ import path from 'path' import replace from '@rollup/plugin-replace' import yaml, { ValidYamlType } from '@rollup/plugin-yaml' +import { sentryVitePlugin } from '@sentry/vite-plugin' import legacy from '@vitejs/plugin-legacy' import react from '@vitejs/plugin-react-swc' import { defineConfig, loadEnv } from 'vite' @@ -16,6 +17,13 @@ import { compileEconomieCollaborativeYaml } from './scripts/compileEconomieColll const env = (mode: string) => loadEnv(mode, process.cwd(), '') +const branch = (mode: string) => getBranch(mode) + +const sentryReleaseName = (mode: string) => + env(mode).VITE_GITHUB_SHA + ? `${branch(mode)}-` + env(mode).VITE_GITHUB_SHA?.substring(0, 7) + : undefined + export default defineConfig(({ command, mode }) => ({ resolve: { alias: [{ find: '@', replacement: path.resolve('./source') }], @@ -37,7 +45,7 @@ export default defineConfig(({ command, mode }) => ({ }, }, define: { - BRANCH_NAME: JSON.stringify(getBranch(mode)), + BRANCH_NAME: JSON.stringify(branch(mode)), IS_DEVELOPMENT: mode === 'development', IS_STAGING: mode === 'production' && !isProductionBranch(mode), IS_PRODUCTION: mode === 'production' && isProductionBranch(mode), @@ -93,6 +101,22 @@ export default defineConfig(({ command, mode }) => ({ legacy({ targets: ['defaults', 'not IE 11'], }), + + sentryVitePlugin({ + org: 'betagouv', + project: 'mon-entreprise', + url: 'https://sentry.incubateur.net/', + authToken: process.env.SENTRY_AUTH_TOKEN, + telemetry: false, + release: { + // Use same release name as the one used in the app. + name: sentryReleaseName(mode), + uploadLegacySourcemaps: { + paths: ['./dist'], + ignore: ['./node_modules'], + }, + }, + }), ], server: { diff --git a/yarn.lock b/yarn.lock index 5ed55b075..aa8640c9e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9935,6 +9935,37 @@ __metadata: languageName: node linkType: hard +"@sentry/bundler-plugin-core@npm:2.7.1": + version: 2.7.1 + resolution: "@sentry/bundler-plugin-core@npm:2.7.1" + dependencies: + "@sentry/cli": ^2.20.1 + "@sentry/node": ^7.60.0 + "@sentry/utils": ^7.60.0 + dotenv: ^16.3.1 + find-up: 5.0.0 + glob: 9.3.2 + magic-string: 0.27.0 + unplugin: 1.0.1 + checksum: 43371c0b3e0a3dfe0c43ff6f88b6c2318c339a7d0d9351b3dd4783a34ea8a71dfcbffcb45e8ce1ea7b829c14931c2f2e02562e724482d27bb085d5841750a4ab + languageName: node + linkType: hard + +"@sentry/cli@npm:^2.20.1": + version: 2.21.1 + resolution: "@sentry/cli@npm:2.21.1" + dependencies: + https-proxy-agent: ^5.0.0 + node-fetch: ^2.6.7 + progress: ^2.0.3 + proxy-from-env: ^1.1.0 + which: ^2.0.2 + bin: + sentry-cli: bin/sentry-cli + checksum: 6b9561747cfb86ceb2c9a4d53622494472391b8eb6c54c8d8df8997f430e098ed756be5f83b87fd2b85f79d9c0d771406ac6205d47cd0d1a1b31426ead72b919 + languageName: node + linkType: hard + "@sentry/core@npm:7.70.0": version: 7.70.0 resolution: "@sentry/core@npm:7.70.0" @@ -9958,7 +9989,7 @@ __metadata: languageName: node linkType: hard -"@sentry/node@npm:^7.70.0": +"@sentry/node@npm:^7.60.0, @sentry/node@npm:^7.70.0": version: 7.70.0 resolution: "@sentry/node@npm:7.70.0" dependencies: @@ -10000,15 +10031,6 @@ __metadata: languageName: node linkType: hard -"@sentry/tracing@npm:^7.70.0": - version: 7.70.0 - resolution: "@sentry/tracing@npm:7.70.0" - dependencies: - "@sentry-internal/tracing": 7.70.0 - checksum: 4efa3ccfa076971dfba85d449b069daac9e4dbe8bba30d71e0db0ca3d10e18677e68ed6cb9a1f3493572f623973bd482bff869ae72c725f06275bf46b678a9ca - languageName: node - linkType: hard - "@sentry/types@npm:7.70.0": version: 7.70.0 resolution: "@sentry/types@npm:7.70.0" @@ -10016,7 +10038,7 @@ __metadata: languageName: node linkType: hard -"@sentry/utils@npm:7.70.0": +"@sentry/utils@npm:7.70.0, @sentry/utils@npm:^7.60.0, @sentry/utils@npm:^7.70.0": version: 7.70.0 resolution: "@sentry/utils@npm:7.70.0" dependencies: @@ -10026,6 +10048,16 @@ __metadata: languageName: node linkType: hard +"@sentry/vite-plugin@npm:^2.7.1": + version: 2.7.1 + resolution: "@sentry/vite-plugin@npm:2.7.1" + dependencies: + "@sentry/bundler-plugin-core": 2.7.1 + unplugin: 1.0.1 + checksum: a676fced23f7dde4e2481d4516ab080cc557f5d12bfc19afb6989136a1eeab3ef3404d2ce58d24aa67440d352cef3dc84b7e713785654bc40bc8814906210851 + languageName: node + linkType: hard + "@sideway/address@npm:^4.1.3": version: 4.1.4 resolution: "@sideway/address@npm:4.1.4" @@ -13014,7 +13046,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.10.0, acorn@npm:^8.9.0": +"acorn@npm:^8.10.0, acorn@npm:^8.8.1, acorn@npm:^8.9.0": version: 8.10.0 resolution: "acorn@npm:8.10.0" bin: @@ -13410,7 +13442,7 @@ __metadata: "@koa/router": ^12.0.0 "@publicodes/api": ^1.0.0-beta.74 "@sentry/node": ^7.70.0 - "@sentry/tracing": ^7.70.0 + "@sentry/utils": ^7.70.0 "@types/ioredis-mock": ^8.2.2 "@types/koa": ^2.13.9 "@types/koa-static": ^4.0.2 @@ -19013,6 +19045,16 @@ __metadata: languageName: node linkType: hard +"find-up@npm:5.0.0, find-up@npm:^5.0.0": + version: 5.0.0 + resolution: "find-up@npm:5.0.0" + dependencies: + locate-path: ^6.0.0 + path-exists: ^4.0.0 + checksum: 07955e357348f34660bde7920783204ff5a26ac2cafcaa28bace494027158a97b9f56faaf2d89a6106211a8174db650dd9f503f9c0d526b1202d5554a00b9095 + languageName: node + linkType: hard + "find-up@npm:6.3.0, find-up@npm:^6.0.0, find-up@npm:^6.3.0": version: 6.3.0 resolution: "find-up@npm:6.3.0" @@ -19042,16 +19084,6 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^5.0.0": - version: 5.0.0 - resolution: "find-up@npm:5.0.0" - dependencies: - locate-path: ^6.0.0 - path-exists: ^4.0.0 - checksum: 07955e357348f34660bde7920783204ff5a26ac2cafcaa28bace494027158a97b9f56faaf2d89a6106211a8174db650dd9f503f9c0d526b1202d5554a00b9095 - languageName: node - linkType: hard - "flat-cache@npm:^3.0.4": version: 3.0.4 resolution: "flat-cache@npm:3.0.4" @@ -19814,6 +19846,18 @@ __metadata: languageName: node linkType: hard +"glob@npm:9.3.2": + version: 9.3.2 + resolution: "glob@npm:9.3.2" + dependencies: + fs.realpath: ^1.0.0 + minimatch: ^7.4.1 + minipass: ^4.2.4 + path-scurry: ^1.6.1 + checksum: f3d188e9f70e24fa729a63ca197bcdb36d838677abec1fb9bbfe4b7620063bf90dc0f8d195203d632abfdfa049fad0edf22f93c60076de67cef20c23bcbfaee8 + languageName: node + linkType: hard + "glob@npm:^10.0.0": version: 10.3.4 resolution: "glob@npm:10.3.4" @@ -23128,6 +23172,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:0.27.0, magic-string@npm:^0.27.0": + version: 0.27.0 + resolution: "magic-string@npm:0.27.0" + dependencies: + "@jridgewell/sourcemap-codec": ^1.4.13 + checksum: 273faaa50baadb7a2df6e442eac34ad611304fc08fe16e24fe2e472fd944bfcb73ffb50d2dc972dc04e92784222002af46868cb9698b1be181c81830fd95a13e + languageName: node + linkType: hard + "magic-string@npm:^0.25.0, magic-string@npm:^0.25.7": version: 0.25.9 resolution: "magic-string@npm:0.25.9" @@ -23137,15 +23190,6 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.27.0": - version: 0.27.0 - resolution: "magic-string@npm:0.27.0" - dependencies: - "@jridgewell/sourcemap-codec": ^1.4.13 - checksum: 273faaa50baadb7a2df6e442eac34ad611304fc08fe16e24fe2e472fd944bfcb73ffb50d2dc972dc04e92784222002af46868cb9698b1be181c81830fd95a13e - languageName: node - linkType: hard - "magic-string@npm:^0.30.0": version: 0.30.3 resolution: "magic-string@npm:0.30.3" @@ -23581,7 +23625,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^7.4.3": +"minimatch@npm:^7.4.1, minimatch@npm:^7.4.3": version: 7.4.6 resolution: "minimatch@npm:7.4.6" dependencies: @@ -23682,6 +23726,13 @@ __metadata: languageName: node linkType: hard +"minipass@npm:^4.2.4": + version: 4.2.8 + resolution: "minipass@npm:4.2.8" + checksum: 7f4914d5295a9a30807cae5227a37a926e6d910c03f315930fde52332cf0575dfbc20295318f91f0baf0e6bb11a6f668e30cde8027dea7a11b9d159867a3c830 + languageName: node + linkType: hard + "minipass@npm:^5.0.0 || ^6.0.2": version: 6.0.2 resolution: "minipass@npm:6.0.2" @@ -25372,7 +25423,7 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.10.1": +"path-scurry@npm:^1.10.1, path-scurry@npm:^1.6.1": version: 1.10.1 resolution: "path-scurry@npm:1.10.1" dependencies: @@ -25836,7 +25887,7 @@ __metadata: languageName: node linkType: hard -"progress@npm:^2.0.1": +"progress@npm:^2.0.1, progress@npm:^2.0.3": version: 2.0.3 resolution: "progress@npm:2.0.3" checksum: f67403fe7b34912148d9252cb7481266a354bd99ce82c835f79070643bb3c6583d10dbcfda4d41e04bbc1d8437e9af0fb1e1f2135727878f5308682a579429b7 @@ -28292,7 +28343,7 @@ __metadata: "@rushstack/package-deps-hash": ^3.2.67 "@sentry/integrations": ^7.70.0 "@sentry/react": ^7.70.0 - "@sentry/tracing": ^7.70.0 + "@sentry/vite-plugin": ^2.7.1 "@storybook/addon-a11y": ^7.4.2 "@storybook/addon-actions": ^7.4.2 "@storybook/addon-essentials": ^7.4.2 @@ -30535,6 +30586,18 @@ __metadata: languageName: node linkType: hard +"unplugin@npm:1.0.1": + version: 1.0.1 + resolution: "unplugin@npm:1.0.1" + dependencies: + acorn: ^8.8.1 + chokidar: ^3.5.3 + webpack-sources: ^3.2.3 + webpack-virtual-modules: ^0.5.0 + checksum: b6bf00dcc79e71cd55d2b4dd39ec7c8ec40b071dc10c14e29095df5dccb13ad0ca1cf14e5da38bb16b8704f8eface750b7a3be9ee7ca2574ce31096ee966b356 + languageName: node + linkType: hard + "unplugin@npm:^1.3.1": version: 1.5.0 resolution: "unplugin@npm:1.5.0"