diff --git a/.do/app.yaml b/.do/app.yaml deleted file mode 100644 index efa0ecca43..0000000000 --- a/.do/app.yaml +++ /dev/null @@ -1,233 +0,0 @@ -alerts: - - rule: DEPLOYMENT_FAILED - - rule: DOMAIN_FAILED -databases: - - cluster_name: hi-events-redis - engine: REDIS - name: hi-events-redis - production: true - version: "7" - - cluster_name: hi-events-postgres - db_name: hi-events-db - db_user: hi-events-db - engine: PG - name: hi-events-postgres - production: true - version: "12" -domains: - - domain: demo.hi.events - type: PRIMARY - - domain: app.hi.events - type: ALIAS -envs: - - key: APP_KEY - scope: RUN_AND_BUILD_TIME - type: SECRET - value: EV[1:XXX:XXX] - - key: APP_SAAS_MODE_ENABLED - scope: RUN_AND_BUILD_TIME - value: "true" - - key: APP_SAAS_STRIPE_APPLICATION_FEE_PERCENT - scope: RUN_AND_BUILD_TIME - value: "1.5" - - key: APP_FRONTEND_URL - scope: RUN_AND_BUILD_TIME - value: ${APP_URL} - - key: APP_CDN_URL - scope: RUN_AND_BUILD_TIME - value: https://d31hxulcw8spzw.cloudfront.net - - key: FILESYSTEM_DISK - scope: RUN_AND_BUILD_TIME - value: s3-public - - key: JWT_SECRET - scope: RUN_AND_BUILD_TIME - type: SECRET - value: EV[1:XXX:XXX] - - key: LOG_CHANNEL - scope: RUN_AND_BUILD_TIME - value: stderr - - key: AWS_ACCESS_KEY_ID - scope: RUN_AND_BUILD_TIME - type: SECRET - value: EV[1:XXX:XXX] - - key: AWS_SECRET_ACCESS_KEY - scope: RUN_AND_BUILD_TIME - type: SECRET - value: EV[1:XXX:XXX] - - key: AWS_DEFAULT_REGION - scope: RUN_AND_BUILD_TIME - value: us-west-1 - - key: AWS_PUBLIC_BUCKET - scope: RUN_AND_BUILD_TIME - value: hievents-public - - key: AWS_PRIVATE_BUCKET - scope: RUN_AND_BUILD_TIME - value: hievents-private - - key: STRIPE_PUBLIC_KEY - scope: RUN_AND_BUILD_TIME - type: SECRET - value: EV[1:XXX:XXX] - - key: STRIPE_SECRET_KEY - scope: RUN_AND_BUILD_TIME - type: SECRET - value: EV[1:XXX:XXX] - - key: MAIL_MAILER - scope: RUN_AND_BUILD_TIME - value: smtp - - key: MAIL_HOST - scope: RUN_AND_BUILD_TIME - value: smtp-relay.brevo.com - - key: MAIL_PORT - scope: RUN_AND_BUILD_TIME - value: "587" - - key: DB_CONNECTION - scope: RUN_AND_BUILD_TIME - value: pgsql - - key: DB_HOST - scope: RUN_AND_BUILD_TIME - value: ${hi-events-postgres.HOSTNAME} - - key: DB_PORT - scope: RUN_AND_BUILD_TIME - value: ${hi-events-postgres.PORT} - - key: DB_DATABASE - scope: RUN_AND_BUILD_TIME - value: ${hi-events-postgres.DATABASE} - - key: DB_USERNAME - scope: RUN_AND_BUILD_TIME - value: ${hi-events-postgres.USERNAME} - - key: DB_PASSWORD - scope: RUN_AND_BUILD_TIME - value: ${hi-events-postgres.PASSWORD} - - key: REDIS_HOST - scope: RUN_AND_BUILD_TIME - value: ${hi-events-redis.HOSTNAME} - - key: REDIS_PASSWORD - scope: RUN_AND_BUILD_TIME - value: ${hi-events-redis.PASSWORD} - - key: REDIS_USER - scope: RUN_AND_BUILD_TIME - value: ${hi-events-redis.USERNAME} - - key: REDIS_PORT - scope: RUN_AND_BUILD_TIME - value: ${hi-events-redis.PORT} - - key: REDIS_URL - scope: RUN_AND_BUILD_TIME - value: ${hi-events-redis.REDIS_URL} - - key: QUEUE_CONNECTION - scope: RUN_AND_BUILD_TIME - value: redis - - key: DATABASE_URL - scope: RUN_AND_BUILD_TIME - value: ${hi-events-postgres.DATABASE_URL} - - key: STRIPE_WEBHOOK_SECRET - scope: RUN_AND_BUILD_TIME - type: SECRET - value: EV[1:XXX:XXX] - - key: MAIL_USERNAME - scope: RUN_AND_BUILD_TIME - value: 758230001@smtp-brevo.com - - key: MAIL_PASSWORD - scope: RUN_AND_BUILD_TIME - value: XXX - - key: MAIL_FROM_ADDRESS - scope: RUN_AND_BUILD_TIME - value: hello@hi.events - - key: MAIL_FROM_NAME - scope: RUN_AND_BUILD_TIME - value: Hi.Events -features: - - buildpack-stack=ubuntu-22 -ingress: - rules: - - component: - name: hi-events-backend - match: - path: - prefix: /api - - component: - name: hi-events-frontend - match: - path: - prefix: / -jobs: - - dockerfile_path: /backend/Dockerfile - github: - branch: main - deploy_on_push: true - repo: HiEventsDev/Hi.Events - instance_count: 2 - instance_size_slug: professional-xs - kind: PRE_DEPLOY - log_destinations: - - logtail: - token: XXX - name: LogTail - name: hi-events-migration - run_command: php artisan migrate --force - source_dir: backend -name: hi-events-backend-app -region: sfo -services: - - alerts: - - operator: GREATER_THAN - rule: CPU_UTILIZATION - value: 50 - window: FIVE_MINUTES - - operator: GREATER_THAN - rule: MEM_UTILIZATION - value: 50 - window: FIVE_MINUTES - dockerfile_path: /backend/Dockerfile - github: - branch: main - deploy_on_push: true - repo: HiEventsDev/Hi.Events - http_port: 8080 - instance_count: 1 - instance_size_slug: professional-xs - log_destinations: - - logtail: - token: XXX - name: LogTail - name: hi-events-backend - source_dir: backend - - build_command: yarn build - environment_slug: node-js - envs: - - key: VITE_STRIPE_PUBLISHABLE_KEY - scope: RUN_AND_BUILD_TIME - value: pk_test_XXX - - key: VITE_API_URL_SERVER - scope: RUN_AND_BUILD_TIME - value: ${APP_URL}/api - - key: VITE_API_URL_CLIENT - scope: RUN_AND_BUILD_TIME - value: ${APP_URL}/api - - key: VITE_FRONTEND_URL - scope: RUN_AND_BUILD_TIME - value: ${APP_URL} - github: - branch: main - deploy_on_push: true - repo: HiEventsDev/Hi.Events - http_port: 5678 - instance_count: 1 - instance_size_slug: professional-xs - name: hi-events-frontend - run_command: yarn start - source_dir: frontend -workers: - - dockerfile_path: /backend/Dockerfile - github: - branch: main - deploy_on_push: true - repo: HiEventsDev/Hi.Events - instance_count: 1 - instance_size_slug: professional-xs - log_destinations: - - logtail: - token: XXX - name: LogTail - name: hi-events-worker - run_command: php artisan queue:work - source_dir: backend diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 1fd5f71ab3..82c1d25fa8 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -116,6 +116,7 @@ jobs: run: vapor deploy ${{ env.VAPOR_ENV }} env: VAPOR_API_TOKEN: ${{ secrets.VAPOR_API_TOKEN }} + SENTRY_RELEASE: ${{ github.sha }} frontend: name: Deploy Frontend diff --git a/backend/.env.example b/backend/.env.example index 81e46d1d1d..a68aa669e5 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -24,6 +24,14 @@ CORS_ALLOWED_ORIGINS=* LOG_CHANNEL=stderr LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug +LOG_STACK=single + +SENTRY_DSN= +SENTRY_ENVIRONMENT= +SENTRY_ENABLE_LOGS=false +SENTRY_LOG_LEVEL=info +SENTRY_RELEASE= +SENTRY_TRACES_SAMPLE_RATE=0 DB_CONNECTION=pgsql DB_HOST=pgsql diff --git a/backend/config/logging.php b/backend/config/logging.php index c44d27639a..52f7b43936 100644 --- a/backend/config/logging.php +++ b/backend/config/logging.php @@ -54,7 +54,7 @@ 'channels' => [ 'stack' => [ 'driver' => 'stack', - 'channels' => ['single'], + 'channels' => array_values(array_filter(array_map('trim', explode(',', (string) env('LOG_STACK', 'single'))))) ?: ['single'], 'ignore_exceptions' => false, ], @@ -118,6 +118,11 @@ 'replace_placeholders' => true, ], + 'sentry_logs' => [ + 'driver' => 'sentry_logs', + 'level' => env('SENTRY_LOG_LEVEL', 'info'), + ], + 'null' => [ 'driver' => 'monolog', 'handler' => NullHandler::class, diff --git a/backend/config/sentry.php b/backend/config/sentry.php index b159b0aae8..7a9c96c25e 100644 --- a/backend/config/sentry.php +++ b/backend/config/sentry.php @@ -35,6 +35,9 @@ // @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#send-default-pii 'send_default_pii' => env('SENTRY_SEND_DEFAULT_PII', false), + // @see: https://docs.sentry.io/platforms/php/guides/laravel/logs/ + 'enable_logs' => filter_var(env('SENTRY_ENABLE_LOGS', false), FILTER_VALIDATE_BOOLEAN), + // @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#ignore-exceptions // 'ignore_exceptions' => [], diff --git a/frontend/.env.example b/frontend/.env.example index 7962f4ade8..7b2d17d2b0 100644 --- a/frontend/.env.example +++ b/frontend/.env.example @@ -3,4 +3,11 @@ VITE_API_URL_CLIENT=https://localhost:8443/api VITE_API_URL_SERVER=http://backend:80/api VITE_FRONTEND_URL=https://localhost:8443 -VITE_STRIPE_PUBLISHABLE_KEY=pk_test_51Ofu1CJKnXOyGeQuDPUHiZcJxZozRuERiv4vQRBtCscwTbxOL574cxUjAoNRL2YLCumgC5160pl6kvTIiAc9mOeM0058KAWQ55 \ No newline at end of file +VITE_STRIPE_PUBLISHABLE_KEY=pk_test_51Ofu1CJKnXOyGeQuDPUHiZcJxZozRuERiv4vQRBtCscwTbxOL574cxUjAoNRL2YLCumgC5160pl6kvTIiAc9mOeM0058KAWQ55 + +SENTRY_SSR_DSN= +SENTRY_ENVIRONMENT= +SENTRY_ENABLE_LOGS=false +SENTRY_LOG_LEVEL=info +SENTRY_RELEASE= +SENTRY_TRACES_SAMPLE_RATE=0 diff --git a/frontend/Dockerfile.ssr b/frontend/Dockerfile.ssr index 425c0c0668..543c9d8afe 100644 --- a/frontend/Dockerfile.ssr +++ b/frontend/Dockerfile.ssr @@ -38,7 +38,7 @@ WORKDIR /app COPY --from=prod-deps /app/node_modules ./node_modules COPY --from=build /app/dist ./dist -COPY package.json yarn.lock server.js ./ +COPY package.json yarn.lock server.js instrument.mjs ./ COPY src ./src COPY public ./public diff --git a/frontend/instrument.mjs b/frontend/instrument.mjs new file mode 100644 index 0000000000..5f4b9f5adc --- /dev/null +++ b/frontend/instrument.mjs @@ -0,0 +1,54 @@ +import "dotenv/config"; +import * as Sentry from "@sentry/node"; + +const LOG_SEVERITY_ORDER = ["trace", "debug", "info", "warn", "error", "fatal"]; + +const LOG_LEVEL_ALIASES = { + warning: "warn", + notice: "info", + critical: "fatal", + alert: "fatal", + emergency: "fatal", +}; + +const isTruthy = (value) => /^(1|true|yes|on)$/i.test(value ?? ""); + +const resolveMinimumSeverity = (value) => { + const normalised = LOG_LEVEL_ALIASES[String(value).toLowerCase()] ?? String(value).toLowerCase(); + const index = LOG_SEVERITY_ORDER.indexOf(normalised); + + return index === -1 ? LOG_SEVERITY_ORDER.indexOf("info") : index; +}; + +const dsn = process.env.SENTRY_SSR_DSN; + +if (dsn) { + const environment = process.env.SENTRY_ENVIRONMENT; + + if (!environment) { + console.warn( + `[sentry] SENTRY_ENVIRONMENT is not set, so events will be reported as "${process.env.NODE_ENV || "production"}". ` + + "Set it per deployment so staging and production stay separate." + ); + } + + const enableLogs = isTruthy(process.env.SENTRY_ENABLE_LOGS); + const minimumSeverity = resolveMinimumSeverity(process.env.SENTRY_LOG_LEVEL ?? "info"); + + Sentry.init({ + dsn, + environment: environment || process.env.NODE_ENV || "production", + release: process.env.SENTRY_RELEASE, + enableLogs, + integrations: enableLogs ? [Sentry.consoleLoggingIntegration()] : [], + beforeSendLog: (log) => (LOG_SEVERITY_ORDER.indexOf(log.level) >= minimumSeverity ? log : null), + tracesSampleRate: Number(process.env.SENTRY_TRACES_SAMPLE_RATE) || 0, + dataCollection: { + userInfo: false, + cookies: false, + httpHeaders: { request: false, response: false }, + httpBodies: [], + urlQueryParams: false, + }, + }); +} diff --git a/frontend/package.json b/frontend/package.json index e2592b9048..91faea9b57 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -8,10 +8,10 @@ "build:csr": "vite build", "build-strict:csr": "tsc && npm run build:csr", "preview:csr": "vite preview", - "dev:ssr": "cross-env NODE_ENV=development node server.js --port 5678", + "dev:ssr": "cross-env NODE_ENV=development node --import ./instrument.mjs server.js --port 5678", "build:ssr:client": "vite build --ssrManifest --outDir dist/client", "build:ssr:server": "vite build --ssr src/entry.server.tsx --outDir dist/server", - "start": "cross-env NODE_ENV=production node server.js", + "start": "cross-env NODE_ENV=production node --import ./instrument.mjs server.js", "build": "npm run messages:extract && npm run messages:compile && npm run build:ssr:client && npm run build:ssr:server", "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "messages:extract": "lingui extract", @@ -39,6 +39,7 @@ "@react-pdf/renderer": "^4.5.1", "@react-router/node": "^7.1.5", "@remix-run/node": "^2.16.8", + "@sentry/node": "^10.73.0", "@stripe/react-stripe-js": "^2.1.1", "@stripe/stripe-js": "^1.54.1", "@tabler/icons-react": "^3.35.0", diff --git a/frontend/server.js b/frontend/server.js index 1cbdb4c1ca..74af242799 100644 --- a/frontend/server.js +++ b/frontend/server.js @@ -10,6 +10,7 @@ import {fileURLToPath} from "node:url"; import * as nodePath from "node:path"; import * as nodeUrl from "node:url"; import "dotenv/config"; +import * as Sentry from "@sentry/node"; import {sitemapIndexHandler, sitemapEventsHandler, sitemapOrganizersHandler} from "./src/sitemap/proxy.js"; import {htmlSafeJsonStringify} from "./src/utilites/safeScriptJson.js"; @@ -110,6 +111,16 @@ Sitemap: ${frontendUrl}/sitemap.xml app.get('/sitemap-events-:page.xml', sitemapEventsHandler); app.get('/sitemap-organizers-:page.xml', sitemapOrganizersHandler); + const nonRenderablePathPattern = /(^|\/)\.[^/]|\.(php|asp|aspx|jsp|cgi|sql|bak|old|zip|tar|gz|rar|7z|env|ini|yml|yaml|conf|log|sh|exe|dll)$/i; + + app.use("*", async (req, res, next) => { + if (nonRenderablePathPattern.test(req.originalUrl.split("?")[0])) { + return res.status(404).type("text/plain").send("Not Found"); + } + + return next(); + }); + app.use("*", async (req, res) => { const url = req.originalUrl.replace(base, ""); @@ -126,10 +137,19 @@ Sitemap: ${frontendUrl}/sitemap.xml render = (await dynamicImport(path.join(__dirname, "./dist/server/entry.server.js"))).render; } - const { appHtml, dehydratedState, helmetContext, themeColors } = await render( + const { appHtml, dehydratedState, helmetContext, themeColors, statusCode, renderErrors } = await render( { req, res }, ssrManifest ); + + if (statusCode >= 500) { + renderErrors.forEach((renderError) => { + Sentry.captureException(renderError, { + tags: { source: "ssr-loader" }, + extra: { url: req.originalUrl }, + }); + }); + } const stringifiedState = htmlSafeJsonStringify(dehydratedState); const stringifiedThemeColors = htmlSafeJsonStringify(themeColors); @@ -154,7 +174,7 @@ Sitemap: ${frontendUrl}/sitemap.xml .replace(/.*?/s, () => helmetHtml); res.setHeader("Content-Type", "text/html"); - return res.status(200).end(html); + return res.status(statusCode || 200).end(html); } catch (error) { if (error instanceof Response) { if (error.status >= 300 && error.status < 400) { @@ -164,11 +184,27 @@ Sitemap: ${frontendUrl}/sitemap.xml } } + Sentry.captureException(error, { + tags: { source: "ssr-render" }, + extra: { url: req.originalUrl }, + }); console.error(error); res.status(500).send("Internal Server Error"); } }); + Sentry.setupExpressErrorHandler(app); + + app.use((error, req, res, _next) => { + console.error(error); + + if (res.headersSent) { + return res.end(); + } + + return res.status(500).type("text/plain").send("Internal Server Error"); + }); + app.listen(port, () => { console.info(`SSR Serving at http://localhost:${port}`); }); diff --git a/frontend/src/components/common/ErrorDisplay/index.tsx b/frontend/src/components/common/ErrorDisplay/index.tsx index f95b4be93d..f378cfdc85 100644 --- a/frontend/src/components/common/ErrorDisplay/index.tsx +++ b/frontend/src/components/common/ErrorDisplay/index.tsx @@ -18,8 +18,6 @@ export const ErrorDisplay = () => { ? t`The page you are looking for does not exist` : t`An error occurred while loading the page`; - console.log('ErrorDisplay error:', error); - return ( <> { const backendUrl = process.env.VITE_API_URL_SERVER; @@ -26,6 +27,10 @@ const fetchSitemap = async (path, res, errorContext) => { res.status(404).send('Sitemap not found'); return; } + Sentry.captureException(error, { + tags: { source: 'sitemap-proxy' }, + extra: { errorContext, path }, + }); console.error(`Error fetching ${errorContext}:`, error); res.status(500).send('Internal server error'); } diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 2799e52088..fdbd45802e 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -794,6 +794,66 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@opentelemetry/api-logs@0.220.0": + version "0.220.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.220.0.tgz#b2ed235de4b5f3c1769adfa5f3bc247d82cdfbc9" + integrity sha512-CmVa4ImJ+ynfrPMNaAXHET6Bhb44SwzmfyVJFq9ni2jgXJR/l7C6gfVFddNmHP+ZOkP9cf4f9DBe68qVLTHc9w== + dependencies: + "@opentelemetry/api" "^1.3.0" + +"@opentelemetry/api@^1.3.0", "@opentelemetry/api@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.1.tgz#c1b0346de336ba55af2d5a7970882037baedec05" + integrity sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q== + +"@opentelemetry/core@2.11.0": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-2.11.0.tgz#97849d3808bba652568b7d53e20c9fc38bcb7c49" + integrity sha512-7YP44XH0tV6+Mb54x2YGf84i7yi+31MBZlE8JwvozkxyTvXbSp10X7cI7YE49ChJ3shMJoBmCJF3+1QFBJctGA== + dependencies: + "@opentelemetry/semantic-conventions" "^1.29.0" + +"@opentelemetry/instrumentation@^0.220.0": + version "0.220.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.220.0.tgz#542b36bf4871dd83dc84e1373ac4bbcd35a8bfb8" + integrity sha512-xQx3E2WxP1mDvKzxLxX+CTCtNLa560YJZ3087qYHerl2YmiKpv7AH+dAy7vmx+eVrZ5BwhfWUAVoKOoxCNHcpw== + dependencies: + "@opentelemetry/api-logs" "0.220.0" + import-in-the-middle "^3.0.0" + require-in-the-middle "^8.0.0" + +"@opentelemetry/resources@2.11.0": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-2.11.0.tgz#b4e60ba92a4f122dc979f3402aea9713a98eac5b" + integrity sha512-Ie7+8q8MDF4FAEQCKVMTx3ReUvxiIAgIiiW3c9JdmP8+HMcDy20puT+AHjexnExgnbvBxjQ9fjkFDWrikJ2jQA== + dependencies: + "@opentelemetry/core" "2.11.0" + "@opentelemetry/semantic-conventions" "^1.29.0" + +"@opentelemetry/sdk-trace-base@^2.9.0": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.11.0.tgz#3f725401fcfb16e5b2335c103cdc9488829632d1" + integrity sha512-H19x/TX/LZdqiYOjM7fqtSxwlplC5pgelavqbQdHbhdq0q/AI/TGkM2dfGuuynTXmJPeF2HoZVoPDu+TGoW78A== + dependencies: + "@opentelemetry/core" "2.11.0" + "@opentelemetry/resources" "2.11.0" + "@opentelemetry/sdk-trace" "2.11.0" + "@opentelemetry/semantic-conventions" "^1.29.0" + +"@opentelemetry/sdk-trace@2.11.0": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace/-/sdk-trace-2.11.0.tgz#46bbba9d366755df7d6faded0f7cd25af7f265c2" + integrity sha512-fFnTqGm8/G73GQVnxYi7LXa1ZVYEUvgL6XI1LpvV0bPC7WQ/ZGgKxCSl8FnlZBKto9JHHEFTO6s6CUpvvtwFrA== + dependencies: + "@opentelemetry/core" "2.11.0" + "@opentelemetry/resources" "2.11.0" + "@opentelemetry/semantic-conventions" "^1.29.0" + +"@opentelemetry/semantic-conventions@^1.29.0": + version "1.43.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz#f3f467e36c27332f0e735ec86cdcd78dd6f27865" + integrity sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg== + "@parcel/watcher-android-arm64@2.5.1": version "2.5.1" resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz#507f836d7e2042f798c7d07ad19c3546f9848ac1" @@ -1237,6 +1297,59 @@ resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.4.tgz" integrity sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w== +"@sentry/conventions@^0.16.0": + version "0.16.0" + resolved "https://registry.yarnpkg.com/@sentry/conventions/-/conventions-0.16.0.tgz#3b58d15714cf44dca1518496c00749eec5525009" + integrity sha512-fO9PLmHdVURcSPUpWCItWAtgKiMwGdJHbovoSEyLplX5sxs2ugvI4CBPTrkkgqhObnZOD0CnWBKDzSVQYBKEyQ== + +"@sentry/core@10.73.0": + version "10.73.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-10.73.0.tgz#464593d1a2cec6655da681911a2d60d26033e4ab" + integrity sha512-FLO1UgH19RyasVpofu612WCOgb2nEH0dZy+R72d7p65XU9i0wxlMKm3+sgfwKmiSJp1Qhilaaxs4Jg6BbiM5HA== + dependencies: + "@sentry/conventions" "^0.16.0" + +"@sentry/node-core@10.73.0": + version "10.73.0" + resolved "https://registry.yarnpkg.com/@sentry/node-core/-/node-core-10.73.0.tgz#bcc34284d134457f7497d545016879fe6f230bbe" + integrity sha512-GHAGUmZPmm6FKfxfv2maVVJ/A99YAmd7oFOuKMDmITI6O/Msl6JB3vPTEpopVAHLW0LYJQBOjddL9C7o+Jt44g== + dependencies: + "@sentry/conventions" "^0.16.0" + "@sentry/core" "10.73.0" + "@sentry/opentelemetry" "10.73.0" + import-in-the-middle "^3.0.0" + +"@sentry/node@^10.73.0": + version "10.73.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-10.73.0.tgz#a6e98e41b4510c1eaaf9407238b3714521486de1" + integrity sha512-jiMJ6GgXDw6UMGzJY+o0c8OoeA9OfHqZ/xEpHfDqy75hn+9CEkRkbNGCIdMvsc7wW/Se1Os394hHfTpU+YEskg== + dependencies: + "@opentelemetry/api" "^1.9.1" + "@opentelemetry/instrumentation" "^0.220.0" + "@opentelemetry/sdk-trace-base" "^2.9.0" + "@sentry/conventions" "^0.16.0" + "@sentry/core" "10.73.0" + "@sentry/node-core" "10.73.0" + "@sentry/opentelemetry" "10.73.0" + "@sentry/server-utils" "10.73.0" + import-in-the-middle "^3.0.0" + +"@sentry/opentelemetry@10.73.0": + version "10.73.0" + resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-10.73.0.tgz#33af62e2693f0ca0d3963ddba5b67089b82fccdf" + integrity sha512-fQouPQKsH0CQrw6oAn1k0Z2I+tgyochCovifr5qNS69i0OzjknLa03WJyiZ/IuzXc4AVa5jAKfOeE9slABz8Qw== + dependencies: + "@sentry/conventions" "^0.16.0" + "@sentry/core" "10.73.0" + +"@sentry/server-utils@10.73.0": + version "10.73.0" + resolved "https://registry.yarnpkg.com/@sentry/server-utils/-/server-utils-10.73.0.tgz#041aa26349845deeca37f574f04d4298e3ffe157" + integrity sha512-QskripdKFbM/+gipC6mpa2crLwL7+VbkX84IpHg2z9UlYQ1kNKd3aMT+Qk9NLRSw/zu1rSIAvlbWfx4D3rgNAA== + dependencies: + "@sentry/conventions" "^0.16.0" + "@sentry/core" "10.73.0" + "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz" @@ -2363,6 +2476,11 @@ chroma-js@^3.1.2: resolved "https://registry.npmjs.org/chroma-js/-/chroma-js-3.1.2.tgz" integrity sha512-IJnETTalXbsLx1eKEgx19d5L6SRM7cH4vINw/99p/M11HCuXGRWL+6YmCm7FWFGIo6dtWuQoQi1dc5yQ7ESIHg== +cjs-module-lexer@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-2.2.1.tgz#ab35b03c56ade05fe170c70e67ae89f60666847c" + integrity sha512-Ca8swihM+/4yKecYHY52kgJd300hi2lADU/a1RxNTRe+RJ9jvqQlESpbz9DnG9mowez8qwXHB8qYdIUw9e+F5Q== + classnames@^2.3.2: version "2.5.1" resolved "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz" @@ -2682,7 +2800,7 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: +debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5: version "4.4.3" resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz" integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== @@ -2838,6 +2956,11 @@ es-errors@^1.3.0: resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== +es-module-lexer@^2.2.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-2.3.2.tgz#311fa4f40168c1975c505477c51b23234d41ad55" + integrity sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw== + es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz" @@ -3515,6 +3638,15 @@ import-from-esm@^1.3.3: debug "^4.3.4" import-meta-resolve "^4.0.0" +import-in-the-middle@^3.0.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-3.4.0.tgz#74d868189dddbc300c3a558743504884277038de" + integrity sha512-Xfjwfarhe+LGmoaof+sexeNo3sGRysb5x56WrZLwHtmqT0OilSKtVWkv0lrCcMgSKyKP9oBogBAisHZvtJH0aw== + dependencies: + cjs-module-lexer "^2.2.0" + es-module-lexer "^2.2.0" + module-details-from-path "^1.0.4" + import-meta-resolve@^4.0.0: version "4.2.0" resolved "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz" @@ -3946,6 +4078,11 @@ minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" +module-details-from-path@^1.0.3, module-details-from-path@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.4.tgz#b662fdcd93f6c83d3f25289da0ce81c8d9685b94" + integrity sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w== + moo@^0.5.1: version "0.5.2" resolved "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz" @@ -4707,6 +4844,14 @@ require-from-string@^2.0.2: resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +require-in-the-middle@^8.0.0: + version "8.0.1" + resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-8.0.1.tgz#dbde2587f669398626d56b20c868ab87bf01cce4" + integrity sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ== + dependencies: + debug "^4.3.5" + module-details-from-path "^1.0.3" + reselect@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/reselect/-/reselect-5.1.1.tgz#c766b1eb5d558291e5e550298adb0becc24bb72e"