From 8cb7ae29ab9b928c58b68faac37134211ad04644 Mon Sep 17 00:00:00 2001 From: tom Date: Fri, 15 Nov 2024 15:14:05 +0100 Subject: [PATCH 1/8] basic Rollbar setup --- .env.example | 1 + configs/app/features/index.ts | 1 + configs/app/features/rollbar.ts | 43 +++++++++++ deploy/tools/envs-validator/schema.ts | 16 ++++- deploy/tools/envs-validator/test/.env.base | 2 + docs/ENVS.md | 9 +++ lib/rollbar/index.tsx | 18 +++++ nextjs/csp/generateCspPolicy.ts | 1 + nextjs/csp/policies/index.ts | 1 + nextjs/csp/policies/rollbar.ts | 15 ++++ package.json | 2 + pages/_app.tsx | 63 ++++++++-------- ui/pages/Login.tsx | 14 ++-- ui/shared/AppError/AppErrorBoundary.tsx | 12 +++- yarn.lock | 83 ++++++++++++++++++++++ 15 files changed, 237 insertions(+), 44 deletions(-) create mode 100644 configs/app/features/rollbar.ts create mode 100644 lib/rollbar/index.tsx create mode 100644 nextjs/csp/policies/rollbar.ts diff --git a/.env.example b/.env.example index 55112332c2..1b3276a9f6 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,6 @@ NEXT_PUBLIC_SENTRY_DSN=https://sentry.io SENTRY_CSP_REPORT_URI=https://sentry.io +NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN=xxx NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=xxx NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY=xxx NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID=UA-XXXXXX-X diff --git a/configs/app/features/index.ts b/configs/app/features/index.ts index 8fb703f600..009b5cb4e2 100644 --- a/configs/app/features/index.ts +++ b/configs/app/features/index.ts @@ -24,6 +24,7 @@ export { default as nameService } from './nameService'; export { default as publicTagsSubmission } from './publicTagsSubmission'; export { default as restApiDocs } from './restApiDocs'; export { default as rewards } from './rewards'; +export { default as rollbar } from './rollbar'; export { default as rollup } from './rollup'; export { default as safe } from './safe'; export { default as saveOnGas } from './saveOnGas'; diff --git a/configs/app/features/rollbar.ts b/configs/app/features/rollbar.ts new file mode 100644 index 0000000000..56561e8f4e --- /dev/null +++ b/configs/app/features/rollbar.ts @@ -0,0 +1,43 @@ +import type { Feature } from './types'; + +import app from '../app'; +import { getEnvValue } from '../utils'; + +const clientToken = getEnvValue('NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN'); +const instance = (() => { + // const envValue = getEnvValue('NEXT_PUBLIC_APP_INSTANCE'); + // if (envValue) { + // return envValue; + // } + + return app.host?.replace('.blockscout.com', '').replaceAll('-', '_'); +})(); +const environment = getEnvValue('NEXT_PUBLIC_ROLLBAR_ENVIRONMENT') || 'development'; +const codeVersion = getEnvValue('NEXT_PUBLIC_GIT_TAG') || getEnvValue('NEXT_PUBLIC_GIT_COMMIT_SHA'); + +const title = 'Rollbar error monitoring'; + +const config: Feature<{ + clientToken: string; + environment: string; + instance: string | undefined; + codeVersion: string | undefined; +}> = (() => { + if (clientToken) { + return Object.freeze({ + title, + isEnabled: true, + clientToken, + environment, + instance, + codeVersion, + }); + } + + return Object.freeze({ + title, + isEnabled: false, + }); +})(); + +export default config; diff --git a/deploy/tools/envs-validator/schema.ts b/deploy/tools/envs-validator/schema.ts index 42072be04b..bf86708bc7 100644 --- a/deploy/tools/envs-validator/schema.ts +++ b/deploy/tools/envs-validator/schema.ts @@ -367,6 +367,19 @@ const sentrySchema = yup }), }); +const rollbarSchema = yup + .object() + .shape({ + NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN: yup.string().required(), + NEXT_PUBLIC_ROLLBAR_ENVIRONMENT: yup + .string() + .when('NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN', { + is: (value: string) => Boolean(value), + then: (schema) => schema, + otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_ROLLBAR_ENVIRONMENT cannot not be used without NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN'), + }), + }); + const accountSchema = yup .object() .shape({ @@ -869,6 +882,7 @@ const schema = yup .concat(rollupSchema) .concat(beaconChainSchema) .concat(bridgedTokensSchema) - .concat(sentrySchema); + .concat(sentrySchema) + .concat(rollbarSchema); export default schema; diff --git a/deploy/tools/envs-validator/test/.env.base b/deploy/tools/envs-validator/test/.env.base index 3851db8f69..9f46e47e42 100644 --- a/deploy/tools/envs-validator/test/.env.base +++ b/deploy/tools/envs-validator/test/.env.base @@ -1,4 +1,6 @@ NEXT_PUBLIC_SENTRY_DSN=https://sentry.io +NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN=https://rollbar.com +NEXT_PUBLIC_ROLLBAR_ENVIRONMENT=development NEXT_PUBLIC_AUTH_URL=https://example.com NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true NEXT_PUBLIC_LOGOUT_URL=https://example.com diff --git a/docs/ENVS.md b/docs/ENVS.md index 4e7c0c8514..37af2d2927 100644 --- a/docs/ENVS.md +++ b/docs/ENVS.md @@ -735,6 +735,15 @@ The feature enables the Validators page which provides detailed information abou   +### Rollbar error monitoring + +| Variable | Type| Description | Compulsoriness | Default value | Example value | Version | +| --- | --- | --- | --- | --- | --- | --- | +| NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN | `string` | Client token for your Rollbar project | Required | - | `` | v1.37.x+ | +| NEXT_PUBLIC_ROLLBAR_ENVIRONMENT | `string` | App env (e.g development, staging, e2e or production). Passed as `environment` property to Rollbar config | - | `development` | `production` | v1.37.x+ | + +  + ### OpenTelemetry OpenTelemetry SDK for Node.js app could be enabled by passing `OTEL_SDK_ENABLED=true` variable. Configure the OpenTelemetry Protocol Exporter by using the generic environment variables described in the [OT docs](https://opentelemetry.io/docs/specs/otel/protocol/exporter/#configuration-options). Note that this Next.js feature is currently experimental. The Docker image should be built with the `NEXT_OPEN_TELEMETRY_ENABLED=true` argument to enable it. diff --git a/lib/rollbar/index.tsx b/lib/rollbar/index.tsx new file mode 100644 index 0000000000..233c06c9a6 --- /dev/null +++ b/lib/rollbar/index.tsx @@ -0,0 +1,18 @@ +import { Provider as DefaultProvider, useRollbar as useRollbarDefault } from '@rollbar/react'; +import type React from 'react'; + +import config from 'configs/app'; + +const feature = config.features.rollbar; + +const FallbackProvider = ({ children }: { children: React.ReactNode }) => children; + +const useRollbarFallback = (): undefined => {}; + +export const Provider = feature.isEnabled ? DefaultProvider : FallbackProvider; +export const useRollbar = feature.isEnabled ? useRollbarDefault : useRollbarFallback; + +export const clientConfig = feature.isEnabled ? { + accessToken: feature.clientToken, + environment: feature.environment, +} : undefined; diff --git a/nextjs/csp/generateCspPolicy.ts b/nextjs/csp/generateCspPolicy.ts index 149ab93c68..2f178768df 100644 --- a/nextjs/csp/generateCspPolicy.ts +++ b/nextjs/csp/generateCspPolicy.ts @@ -14,6 +14,7 @@ function generateCspPolicy() { descriptors.marketplace(), descriptors.mixpanel(), descriptors.monaco(), + descriptors.rollbar(), descriptors.safe(), descriptors.sentry(), descriptors.usernameApi(), diff --git a/nextjs/csp/policies/index.ts b/nextjs/csp/policies/index.ts index b483f63490..456dad54a7 100644 --- a/nextjs/csp/policies/index.ts +++ b/nextjs/csp/policies/index.ts @@ -9,6 +9,7 @@ export { growthBook } from './growthBook'; export { marketplace } from './marketplace'; export { mixpanel } from './mixpanel'; export { monaco } from './monaco'; +export { rollbar } from './rollbar'; export { safe } from './safe'; export { sentry } from './sentry'; export { usernameApi } from './usernameApi'; diff --git a/nextjs/csp/policies/rollbar.ts b/nextjs/csp/policies/rollbar.ts new file mode 100644 index 0000000000..87470735f7 --- /dev/null +++ b/nextjs/csp/policies/rollbar.ts @@ -0,0 +1,15 @@ +import type CspDev from 'csp-dev'; + +import config from 'configs/app'; + +export function rollbar(): CspDev.DirectiveDescriptor { + if (!config.features.rollbar.isEnabled) { + return {}; + } + + return { + 'connect-src': [ + 'api.rollbar.com', + ], + }; +} diff --git a/package.json b/package.json index 1fa04a3d02..67eb984de3 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "@opentelemetry/sdk-node": "0.49.1", "@opentelemetry/sdk-trace-node": "1.22.0", "@opentelemetry/semantic-conventions": "1.22.0", + "@rollbar/react": "0.12.0-beta", "@scure/base": "1.1.9", "@sentry/cli": "^2.21.2", "@sentry/react": "7.24.0", @@ -109,6 +110,7 @@ "react-jazzicon": "^1.0.4", "react-number-format": "^5.3.1", "react-scroll": "^1.8.7", + "rollbar": "2.26.4", "swagger-ui-react": "^5.9.0", "use-font-face-observer": "^1.2.1", "valibot": "0.38.0", diff --git a/pages/_app.tsx b/pages/_app.tsx index 3c412226f3..bc583e44e8 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -1,6 +1,5 @@ import { type ChakraProps } from '@chakra-ui/react'; import { GrowthBookProvider } from '@growthbook/growthbook-react'; -import * as Sentry from '@sentry/react'; import { QueryClientProvider } from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import type { AppProps } from 'next/app'; @@ -19,6 +18,7 @@ import { SettingsContextProvider } from 'lib/contexts/settings'; import { growthBook } from 'lib/growthbook/init'; import useLoadFeatures from 'lib/growthbook/useLoadFeatures'; import useNotifyOnNavigation from 'lib/hooks/useNotifyOnNavigation'; +import { clientConfig as rollbarConfig, Provider as RollbarProvider } from 'lib/rollbar'; import { SocketProvider } from 'lib/socket/context'; import RewardsLoginModal from 'ui/rewards/login/RewardsLoginModal'; import AppErrorBoundary from 'ui/shared/AppError/AppErrorBoundary'; @@ -53,42 +53,39 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) { const queryClient = useQueryClientConfig(); - const handleError = React.useCallback((error: Error) => { - Sentry.captureException(error); - }, []); - const getLayout = Component.getLayout ?? ((page) => { page }); return ( - - - - - - - - - - - { getLayout() } - { config.features.rewards.isEnabled && } - - - - - - - - - - - - + + + + + + + + + + + + { getLayout() } + { config.features.rewards.isEnabled && } + + + + + + + + + + + + + ); } diff --git a/ui/pages/Login.tsx b/ui/pages/Login.tsx index 438f13fd4b..7bc96b70a6 100644 --- a/ui/pages/Login.tsx +++ b/ui/pages/Login.tsx @@ -1,5 +1,4 @@ import { VStack, Textarea, Button, Alert, AlertTitle, AlertDescription, Code, Flex, Box } from '@chakra-ui/react'; -import * as Sentry from '@sentry/react'; import mixpanel from 'mixpanel-browser'; import type { ChangeEvent } from 'react'; import React from 'react'; @@ -9,12 +8,13 @@ import * as cookies from 'lib/cookies'; import useFeatureValue from 'lib/growthbook/useFeatureValue'; import useGradualIncrement from 'lib/hooks/useGradualIncrement'; import useToast from 'lib/hooks/useToast'; +import { useRollbar } from 'lib/rollbar'; import PageTitle from 'ui/shared/Page/PageTitle'; const Login = () => { + const rollbar = useRollbar(); const toast = useToast(); const [ num, setNum ] = useGradualIncrement(0); - const testFeature = useFeatureValue('test_value', 'fallback'); const [ isFormVisible, setFormVisibility ] = React.useState(false); @@ -23,12 +23,12 @@ const Login = () => { React.useEffect(() => { const token = cookies.get(cookies.NAMES.API_TOKEN); setFormVisibility(Boolean(!token && config.features.account.isEnabled)); - // throw new Error('Test error'); + // throw new Error('Render error'); }, []); - const checkSentry = React.useCallback(() => { - Sentry.captureException(new Error('Test error'), { tags: { source: 'test' } }); - }, []); + const checkRollbar = React.useCallback(() => { + rollbar?.error('Test error', { payload: 'foo' }); + }, [ rollbar ]); const checkMixpanel = React.useCallback(() => { mixpanel.track('Test event', { my_prop: 'foo bar' }); @@ -80,7 +80,7 @@ const Login = () => { ) } - + diff --git a/ui/shared/AppError/AppErrorBoundary.tsx b/ui/shared/AppError/AppErrorBoundary.tsx index 8129ac17c7..0560476c29 100644 --- a/ui/shared/AppError/AppErrorBoundary.tsx +++ b/ui/shared/AppError/AppErrorBoundary.tsx @@ -1,6 +1,7 @@ import { chakra } from '@chakra-ui/react'; import React from 'react'; +import { useRollbar } from 'lib/rollbar'; import ErrorBoundary from 'ui/shared/ErrorBoundary'; import AppError from './AppError'; @@ -8,11 +9,12 @@ import AppError from './AppError'; interface Props { className?: string; children: React.ReactNode; - onError?: (error: Error) => void; Container?: React.FC<{ children: React.ReactNode }>; } -const AppErrorBoundary = ({ className, children, onError, Container }: Props) => { +const AppErrorBoundary = ({ className, children, Container }: Props) => { + + const rollbar = useRollbar(); const renderErrorScreen = React.useCallback((error?: Error) => { const content = ; @@ -22,8 +24,12 @@ const AppErrorBoundary = ({ className, children, onError, Container }: Props) => return content; }, [ className, Container ]); + const handleError = React.useCallback((error: Error) => { + rollbar?.error(error); + }, [ rollbar ]); + return ( - + { children } ); diff --git a/yarn.lock b/yarn.lock index 5203c07524..518d8d1275 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4933,6 +4933,13 @@ prop-types "^15.7.2" tslib "^2.3.0" +"@rollbar/react@0.12.0-beta": + version "0.12.0-beta" + resolved "https://registry.yarnpkg.com/@rollbar/react/-/react-0.12.0-beta.tgz#b80dfab1535ece358a0e98a4f26aadee8b54edda" + integrity sha512-8udBX0lJwdBBq+O/jqDXpg/giHt8bo/Us1IlTkHEdCBO18Cjj7sxWJ80OPFxiPRNwZgZnhf2HbxQxvLN+4FeJA== + dependencies: + tiny-invariant "^1.1.0" + "@rollup/pluginutils@^5.0.0": version "5.0.2" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.2.tgz#012b8f53c71e4f6f9cb317e311df1404f56e7a33" @@ -7757,6 +7764,11 @@ async-mutex@^0.2.6: dependencies: tslib "^2.0.0" +async@~3.2.3: + version "3.2.6" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" + integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -8462,6 +8474,11 @@ consola@^3.2.3: resolved "https://registry.yarnpkg.com/consola/-/consola-3.2.3.tgz#0741857aa88cfa0d6fd53f1cff0375136e98502f" integrity sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ== +console-polyfill@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/console-polyfill/-/console-polyfill-0.3.0.tgz#84900902a18c47a5eba932be75fa44d23e8af861" + integrity sha512-w+JSDZS7XML43Xnwo2x5O5vxB0ID7T5BdqDtyqT6uiCAX2kZAgcWxNaGqT97tZfSHzfOcvrfsDAodKcJ3UvnXQ== + convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.9.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" @@ -9035,6 +9052,13 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +decache@^3.0.5: + version "3.1.0" + resolved "https://registry.yarnpkg.com/decache/-/decache-3.1.0.tgz#4f5036fbd6581fcc97237ac3954a244b9536c2da" + integrity sha512-p7D6wJ5EJFFq1CcF2lu1XeqKFLBob8jRQGNAvFLTsV3CbSKBl3VtliAVlUIGz2i9H6kEFnI2Amaft5ZopIG2Fw== + dependencies: + find "^0.2.4" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -9465,6 +9489,13 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +error-stack-parser@^2.0.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286" + integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== + dependencies: + stackframe "^1.3.4" + error@7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/error/-/error-7.0.2.tgz#a5f75fff4d9926126ddac0ea5dc38e689153cb02" @@ -10372,6 +10403,13 @@ find-yarn-workspace-root@^2.0.0: dependencies: micromatch "^4.0.2" +find@^0.2.4: + version "0.2.9" + resolved "https://registry.yarnpkg.com/find/-/find-0.2.9.tgz#4b73f1ff9e56ad91b76e716407fe5ffe6554bb8c" + integrity sha512-7a4/LCiInB9xYMnAUEjLilL9FKclwbwK7VlXw+h5jMvT2TDFeYFCHM24O1XdnC/on/hx8mxVO3FTQkyHZnOghQ== + dependencies: + traverse-chain "~0.1.0" + flat-cache@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" @@ -12223,6 +12261,11 @@ json-stable-stringify@^1.0.2: dependencies: jsonify "^0.0.1" +json-stringify-safe@~5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + json5@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" @@ -12596,6 +12639,11 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lru-cache@~2.2.1: + version "2.2.4" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d" + integrity sha512-Q5pAgXs+WEAfoEdw2qKQhNFFhMoFMTYqRVKKUMnzuiR7oKFHS7fWo848cPcTKw+4j/IdN17NyzdhVKgabFV0EA== + lz-string@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" @@ -14604,6 +14652,11 @@ repeat-string@^1.5.2: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== +request-ip@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/request-ip/-/request-ip-3.3.0.tgz#863451e8fec03847d44f223e30a5d63e369fa611" + integrity sha512-cA6Xh6e0fDBBBwH77SLJaJPBmD3nWVAcF9/XAcsrIHdjhFzFiB5aNQFytdjCGPezU3ROwrR11IddKAM08vohxA== + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -14726,6 +14779,21 @@ robust-predicates@^3.0.0: resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.1.tgz#ecde075044f7f30118682bd9fb3f123109577f9a" integrity sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g== +rollbar@2.26.4: + version "2.26.4" + resolved "https://registry.yarnpkg.com/rollbar/-/rollbar-2.26.4.tgz#05e47d3b1f52ab6da9f88710ec66371a76cdc3c9" + integrity sha512-JKmrj6riYm9ZPJisgxljgH4uCsvjMHDHXrinDF7aAFaP+eoF51HomVPtLcDTYLsrJ568aKVNLUhedFajONBwSg== + dependencies: + async "~3.2.3" + console-polyfill "0.3.0" + error-stack-parser "^2.0.4" + json-stringify-safe "~5.0.0" + lru-cache "~2.2.1" + request-ip "~3.3.0" + source-map "^0.5.7" + optionalDependencies: + decache "^3.0.5" + rollup-plugin-visualizer@^5.9.2: version "5.12.0" resolved "https://registry.yarnpkg.com/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.12.0.tgz#661542191ce78ee4f378995297260d0c1efb1302" @@ -15190,6 +15258,11 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" +stackframe@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" + integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== + stampit@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/stampit/-/stampit-4.3.2.tgz#cfd3f607dd628a161ce6305621597994b4d56573" @@ -15738,6 +15811,11 @@ tiny-invariant@^1.0.6: resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== +tiny-invariant@^1.1.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" + integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== + tiny-parse-argv@^2.2.0: version "2.4.0" resolved "https://registry.yarnpkg.com/tiny-parse-argv/-/tiny-parse-argv-2.4.0.tgz#8612163a88104a5af9a64e4775cd1e091d4fa265" @@ -15804,6 +15882,11 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +traverse-chain@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1" + integrity sha512-up6Yvai4PYKhpNp5PkYtx50m3KbwQrqDwbuZP/ItyL64YEWHAvH6Md83LFLV/GRSk/BoUVwwgUzX6SOQSbsfAg== + traverse@~0.6.6: version "0.6.7" resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.7.tgz#46961cd2d57dd8706c36664acde06a248f1173fe" From 0663118dfad8390e368f9506b7de26758268be34 Mon Sep 17 00:00:00 2001 From: tom Date: Fri, 15 Nov 2024 18:40:13 +0100 Subject: [PATCH 2/8] remove sentry code --- .env.example | 2 - .github/workflows/upload-source-maps.yml | 1 + .gitignore | 3 - configs/app/features/index.ts | 1 - configs/app/features/rollbar.ts | 10 +- configs/app/features/sentry.ts | 44 ------- configs/envs/.env.eth | 1 - configs/envs/.env.eth_sepolia | 1 - configs/envs/.env.main | 2 +- deploy/tools/envs-validator/index.ts | 19 +++ deploy/tools/envs-validator/schema.ts | 24 +--- deploy/tools/envs-validator/test/.env.base | 2 - deploy/tools/envs-validator/test/.env.sentry | 5 - deploy/values/review-l2/values.yaml.gotmpl | 4 +- deploy/values/review/values.yaml.gotmpl | 2 - docs/ENVS.md | 8 +- lib/api/useApiFetch.tsx | 2 +- lib/hooks/useAddressProfileApiQuery.tsx | 2 +- lib/hooks/useFetch.tsx | 21 ++-- lib/hooks/useGetCsrfToken.tsx | 14 +-- lib/hooks/useIsSafeAddress.tsx | 2 +- lib/rollbar/index.tsx | 7 +- lib/sentry/config.ts | 108 ------------------ next.config.js | 8 +- nextjs/PageNextJs.tsx | 3 - nextjs/csp/generateCspPolicy.ts | 1 - nextjs/csp/policies/app.ts | 31 ----- nextjs/csp/policies/index.ts | 1 - nextjs/csp/policies/sentry.ts | 10 -- package.json | 3 - pages/404.tsx | 8 +- ui/address/details/AddressQrCode.tsx | 7 +- .../auth/useRedirectForInvalidAuthToken.ts | 7 +- yarn.lock | 75 +----------- 34 files changed, 79 insertions(+), 360 deletions(-) delete mode 100644 configs/app/features/sentry.ts delete mode 100644 deploy/tools/envs-validator/test/.env.sentry delete mode 100644 lib/sentry/config.ts delete mode 100644 nextjs/csp/policies/sentry.ts diff --git a/.env.example b/.env.example index 1b3276a9f6..e2e81d3fe0 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,3 @@ -NEXT_PUBLIC_SENTRY_DSN=https://sentry.io -SENTRY_CSP_REPORT_URI=https://sentry.io NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN=xxx NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=xxx NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY=xxx diff --git a/.github/workflows/upload-source-maps.yml b/.github/workflows/upload-source-maps.yml index a5fbf31088..1f0d8c0430 100644 --- a/.github/workflows/upload-source-maps.yml +++ b/.github/workflows/upload-source-maps.yml @@ -1,3 +1,4 @@ +# TODO @tom2drum setup source maps for Rollbar name: Upload source maps to Sentry on: workflow_call: diff --git a/.gitignore b/.gitignore index 24bd046ba4..74d489ae6b 100644 --- a/.gitignore +++ b/.gitignore @@ -43,9 +43,6 @@ yarn-error.log* .eslintcache -# Sentry -.sentryclirc - **.decrypted~** /test-results/ /playwright-report/ diff --git a/configs/app/features/index.ts b/configs/app/features/index.ts index 009b5cb4e2..417e02e4c5 100644 --- a/configs/app/features/index.ts +++ b/configs/app/features/index.ts @@ -28,7 +28,6 @@ export { default as rollbar } from './rollbar'; export { default as rollup } from './rollup'; export { default as safe } from './safe'; export { default as saveOnGas } from './saveOnGas'; -export { default as sentry } from './sentry'; export { default as sol2uml } from './sol2uml'; export { default as stats } from './stats'; export { default as suave } from './suave'; diff --git a/configs/app/features/rollbar.ts b/configs/app/features/rollbar.ts index 56561e8f4e..671e6ab131 100644 --- a/configs/app/features/rollbar.ts +++ b/configs/app/features/rollbar.ts @@ -5,14 +5,14 @@ import { getEnvValue } from '../utils'; const clientToken = getEnvValue('NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN'); const instance = (() => { - // const envValue = getEnvValue('NEXT_PUBLIC_APP_INSTANCE'); - // if (envValue) { - // return envValue; - // } + const envValue = getEnvValue('NEXT_PUBLIC_APP_INSTANCE'); + if (envValue) { + return envValue; + } return app.host?.replace('.blockscout.com', '').replaceAll('-', '_'); })(); -const environment = getEnvValue('NEXT_PUBLIC_ROLLBAR_ENVIRONMENT') || 'development'; +const environment = getEnvValue('NEXT_PUBLIC_APP_ENV') || 'development'; const codeVersion = getEnvValue('NEXT_PUBLIC_GIT_TAG') || getEnvValue('NEXT_PUBLIC_GIT_COMMIT_SHA'); const title = 'Rollbar error monitoring'; diff --git a/configs/app/features/sentry.ts b/configs/app/features/sentry.ts deleted file mode 100644 index fb840ca9e5..0000000000 --- a/configs/app/features/sentry.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { Feature } from './types'; - -import app from '../app'; -import { getEnvValue } from '../utils'; - -const dsn = getEnvValue('NEXT_PUBLIC_SENTRY_DSN'); -const instance = (() => { - const envValue = getEnvValue('NEXT_PUBLIC_APP_INSTANCE'); - if (envValue) { - return envValue; - } - - return app.host?.replace('.blockscout.com', '').replaceAll('-', '_'); -})(); -const environment = getEnvValue('NEXT_PUBLIC_APP_ENV') || 'production'; -const release = getEnvValue('NEXT_PUBLIC_GIT_TAG'); -const title = 'Sentry error monitoring'; - -const config: Feature<{ - dsn: string; - instance: string; - release: string | undefined; - environment: string; - enableTracing: boolean; -}> = (() => { - if (dsn && instance && environment) { - return Object.freeze({ - title, - isEnabled: true, - dsn, - instance, - release, - environment, - enableTracing: getEnvValue('NEXT_PUBLIC_SENTRY_ENABLE_TRACING') === 'true', - }); - } - - return Object.freeze({ - title, - isEnabled: false, - }); -})(); - -export default config; diff --git a/configs/envs/.env.eth b/configs/envs/.env.eth index 781a15d702..216130b727 100644 --- a/configs/envs/.env.eth +++ b/configs/envs/.env.eth @@ -56,7 +56,6 @@ NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/eth.jpg NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://eth.drpc.org?ref=559183','text':'Public RPC'}] NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-mainnet.safe.global -NEXT_PUBLIC_SENTRY_ENABLE_TRACING=true NEXT_PUBLIC_SEO_ENHANCED_DATA_ENABLED=true NEXT_PUBLIC_STATS_API_HOST=https://stats-eth-main.k8s-prod-1.blockscout.com NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout diff --git a/configs/envs/.env.eth_sepolia b/configs/envs/.env.eth_sepolia index 7c75dd73d9..34e3641d6e 100644 --- a/configs/envs/.env.eth_sepolia +++ b/configs/envs/.env.eth_sepolia @@ -56,7 +56,6 @@ NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/sepolia-testnet.png NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://sepolia.drpc.org?ref=559183','text':'Public RPC'}] NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-sepolia.safe.global -NEXT_PUBLIC_SENTRY_ENABLE_TRACING=true NEXT_PUBLIC_STATS_API_HOST=https://stats-sepolia.k8s-dev.blockscout.com NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=noves NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true diff --git a/configs/envs/.env.main b/configs/envs/.env.main index 0568827c78..a5bcd4c351 100644 --- a/configs/envs/.env.main +++ b/configs/envs/.env.main @@ -7,6 +7,7 @@ NEXT_PUBLIC_APP_PROTOCOL=http NEXT_PUBLIC_APP_HOST=localhost NEXT_PUBLIC_APP_PORT=3000 NEXT_PUBLIC_APP_ENV=development +NEXT_PUBLIC_APP_INSTANCE=rubber_duck NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws # Instance ENVs @@ -60,7 +61,6 @@ NEXT_PUBLIC_OG_ENHANCED_DATA_ENABLED=true NEXT_PUBLIC_OG_IMAGE_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/og-images/sepolia-testnet.png NEXT_PUBLIC_OTHER_LINKS=[{'url':'https://sepolia.drpc.org?ref=559183','text':'Public RPC'}] NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-sepolia.safe.global -NEXT_PUBLIC_SENTRY_ENABLE_TRACING=true NEXT_PUBLIC_SEO_ENHANCED_DATA_ENABLED=true NEXT_PUBLIC_STATS_API_HOST=https://stats-sepolia.k8s-dev.blockscout.com NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout diff --git a/deploy/tools/envs-validator/index.ts b/deploy/tools/envs-validator/index.ts index fe7354f7a7..c085ea2800 100644 --- a/deploy/tools/envs-validator/index.ts +++ b/deploy/tools/envs-validator/index.ts @@ -147,6 +147,16 @@ function printDeprecationWarning(envsMap: Record) { console.log('❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗\n'); } + if ( + (envsMap.NEXT_PUBLIC_SENTRY_DSN || envsMap.SENTRY_CSP_REPORT_URI || envsMap.NEXT_PUBLIC_SENTRY_ENABLE_TRACING) && + envsMap.NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN + ) { + console.log('❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗'); + // eslint-disable-next-line max-len + console.warn('The Sentry monitoring is now deprecated and will be removed in the next release. Please migrate to the Rollbar error monitoring.'); + console.log('❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗\n'); + } + if ( envsMap.NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR || envsMap.NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND @@ -178,5 +188,14 @@ function checkDeprecatedEnvs(envsMap: Record) { throw new Error(); } + if ( + (envsMap.NEXT_PUBLIC_SENTRY_DSN || envsMap.SENTRY_CSP_REPORT_URI || envsMap.NEXT_PUBLIC_SENTRY_ENABLE_TRACING) && + !envsMap.NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN + ) { + // eslint-disable-next-line max-len + console.log('🚨 The Sentry error monitoring is no longer supported. Please migrate to the Rollbar error monitoring.'); + throw new Error(); + } + !silent && console.log('👍 All good!\n'); } diff --git a/deploy/tools/envs-validator/schema.ts b/deploy/tools/envs-validator/schema.ts index bf86708bc7..699084b552 100644 --- a/deploy/tools/envs-validator/schema.ts +++ b/deploy/tools/envs-validator/schema.ts @@ -334,6 +334,7 @@ const adsBannerSchema = yup NEXT_PUBLIC_AD_ADBUTLER_CONFIG_MOBILE: adButlerConfigSchema, }); +// DEPRECATED const sentrySchema = yup .object() .shape({ @@ -351,33 +352,12 @@ const sentrySchema = yup is: (value: string) => Boolean(value), then: (schema) => schema, }), - NEXT_PUBLIC_APP_INSTANCE: yup - .string() - .when('NEXT_PUBLIC_SENTRY_DSN', { - is: (value: string) => Boolean(value), - then: (schema) => schema, - otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_APP_INSTANCE cannot not be used without NEXT_PUBLIC_SENTRY_DSN'), - }), - NEXT_PUBLIC_APP_ENV: yup - .string() - .when('NEXT_PUBLIC_SENTRY_DSN', { - is: (value: string) => Boolean(value), - then: (schema) => schema, - otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_APP_ENV cannot not be used without NEXT_PUBLIC_SENTRY_DSN'), - }), }); const rollbarSchema = yup .object() .shape({ NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN: yup.string().required(), - NEXT_PUBLIC_ROLLBAR_ENVIRONMENT: yup - .string() - .when('NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN', { - is: (value: string) => Boolean(value), - then: (schema) => schema, - otherwise: (schema) => schema.max(-1, 'NEXT_PUBLIC_ROLLBAR_ENVIRONMENT cannot not be used without NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN'), - }), }); const accountSchema = yup @@ -567,6 +547,8 @@ const schema = yup NEXT_PUBLIC_APP_HOST: yup.string().required(), NEXT_PUBLIC_APP_PROTOCOL: yup.string().oneOf(protocols), NEXT_PUBLIC_APP_PORT: yup.number().positive().integer(), + NEXT_PUBLIC_APP_ENV: yup.string(), + NEXT_PUBLIC_APP_INSTANCE: yup.string(), // 2. Blockchain parameters NEXT_PUBLIC_NETWORK_NAME: yup.string().required(), diff --git a/deploy/tools/envs-validator/test/.env.base b/deploy/tools/envs-validator/test/.env.base index 9f46e47e42..c4807a95af 100644 --- a/deploy/tools/envs-validator/test/.env.base +++ b/deploy/tools/envs-validator/test/.env.base @@ -1,6 +1,4 @@ -NEXT_PUBLIC_SENTRY_DSN=https://sentry.io NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN=https://rollbar.com -NEXT_PUBLIC_ROLLBAR_ENVIRONMENT=development NEXT_PUBLIC_AUTH_URL=https://example.com NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true NEXT_PUBLIC_LOGOUT_URL=https://example.com diff --git a/deploy/tools/envs-validator/test/.env.sentry b/deploy/tools/envs-validator/test/.env.sentry deleted file mode 100644 index c34c4d4f26..0000000000 --- a/deploy/tools/envs-validator/test/.env.sentry +++ /dev/null @@ -1,5 +0,0 @@ -NEXT_PUBLIC_SENTRY_DSN=https://sentry.io -SENTRY_CSP_REPORT_URI=https://sentry.io -NEXT_PUBLIC_SENTRY_ENABLE_TRACING=true -NEXT_PUBLIC_APP_ENV=production -NEXT_PUBLIC_APP_INSTANCE=duck \ No newline at end of file diff --git a/deploy/values/review-l2/values.yaml.gotmpl b/deploy/values/review-l2/values.yaml.gotmpl index 782072ff59..a3f2535534 100644 --- a/deploy/values/review-l2/values.yaml.gotmpl +++ b/deploy/values/review-l2/values.yaml.gotmpl @@ -48,7 +48,7 @@ frontend: cpu: 250m env: NEXT_PUBLIC_APP_ENV: development - NEXT_PUBLIC_APP_INSTANCE: review_L2 + NEXT_PUBLIC_APP_INSTANCE: review NEXT_PUBLIC_NETWORK_LOGO: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/base.svg NEXT_PUBLIC_NETWORK_ICON: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/base.svg NEXT_PUBLIC_FEATURED_NETWORKS: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/base-mainnet.json @@ -73,8 +73,6 @@ frontend: NEXT_PUBLIC_NAVIGATION_LAYOUT: horizontal NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES: "['/blocks','/name-domains']" envFromSecret: - NEXT_PUBLIC_SENTRY_DSN: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_SENTRY_DSN - SENTRY_CSP_REPORT_URI: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/SENTRY_CSP_REPORT_URI NEXT_PUBLIC_AUTH0_CLIENT_ID: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_AUTH0_CLIENT_ID NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID diff --git a/deploy/values/review/values.yaml.gotmpl b/deploy/values/review/values.yaml.gotmpl index b0d34ffa99..ebbbf2a229 100644 --- a/deploy/values/review/values.yaml.gotmpl +++ b/deploy/values/review/values.yaml.gotmpl @@ -79,8 +79,6 @@ frontend: NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES: "['/apps']" PROMETHEUS_METRICS_ENABLED: true envFromSecret: - NEXT_PUBLIC_SENTRY_DSN: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_SENTRY_DSN - SENTRY_CSP_REPORT_URI: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/SENTRY_CSP_REPORT_URI NEXT_PUBLIC_AUTH0_CLIENT_ID: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_AUTH0_CLIENT_ID NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID diff --git a/docs/ENVS.md b/docs/ENVS.md index 37af2d2927..34918a4832 100644 --- a/docs/ENVS.md +++ b/docs/ENVS.md @@ -60,6 +60,7 @@ Please be aware that all environment variables prefixed with `NEXT_PUBLIC_` will - [MetaSuites extension](ENVS.md#metasuites-extension) - [Validators list](ENVS.md#validators-list) - [Sentry error monitoring](ENVS.md#sentry-error-monitoring) + - [Rollbar error monitoring](ENVS.md#rollbar-error-monitoring) - [OpenTelemetry](ENVS.md#opentelemetry) - [DeFi dropdown](ENVS.md#defi-dropdown) - [Multichain balance button](ENVS.md#multichain-balance-button) @@ -77,6 +78,8 @@ Please be aware that all environment variables prefixed with `NEXT_PUBLIC_` will | NEXT_PUBLIC_APP_PROTOCOL | `http \| https` | App url schema | - | `https` | `http` | v1.0.x+ | | NEXT_PUBLIC_APP_HOST | `string` | App host | Required | - | `blockscout.com` | v1.0.x+ | | NEXT_PUBLIC_APP_PORT | `number` | Port where app is running | - | `3000` | `3001` | v1.0.x+ | +| NEXT_PUBLIC_APP_ENV | `string` | App env (e.g development, staging, production, etc.). | - | `production` | `staging` | v1.0.x+ | +| NEXT_PUBLIC_APP_INSTANCE | `string` | Name of app instance. Used for app monitoring purposes. If not provided, it will be constructed from `NEXT_PUBLIC_APP_HOST` | - | - | `wonderful_kepler` | v1.0.x+ | | NEXT_PUBLIC_USE_NEXT_JS_PROXY | `boolean` | Tells the app to proxy all APIs request through the NextJS app. **We strongly advise not to use it in the production environment**, since it can lead to performance issues of the NodeJS server | - | `false` | `true` | v1.8.0+ |   @@ -725,13 +728,13 @@ The feature enables the Validators page which provides detailed information abou ### Sentry error monitoring +_Note_ This feature is **deprecated**. All ENV variables will be removed in the future releases. + | Variable | Type| Description | Compulsoriness | Default value | Example value | Version | | --- | --- | --- | --- | --- | --- | --- | | NEXT_PUBLIC_SENTRY_DSN | `string` | Client key for your Sentry.io app | Required | - | `` | v1.0.x+ | | SENTRY_CSP_REPORT_URI | `string` | URL for sending CSP-reports to your Sentry.io app | - | - | `` | v1.0.x+ | | NEXT_PUBLIC_SENTRY_ENABLE_TRACING | `boolean` | Enables tracing and performance monitoring in Sentry.io | - | `false` | `true` | v1.17.0+ | -| NEXT_PUBLIC_APP_ENV | `string` | App env (e.g development, review or production). Passed as `environment` property to Sentry config | - | `production` | `production` | v1.0.x+ | -| NEXT_PUBLIC_APP_INSTANCE | `string` | Name of app instance. Used as custom tag `app_instance` value in the main Sentry scope. If not provided, it will be constructed from `NEXT_PUBLIC_APP_HOST` | - | - | `wonderful_kepler` | v1.0.x+ |   @@ -740,7 +743,6 @@ The feature enables the Validators page which provides detailed information abou | Variable | Type| Description | Compulsoriness | Default value | Example value | Version | | --- | --- | --- | --- | --- | --- | --- | | NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN | `string` | Client token for your Rollbar project | Required | - | `` | v1.37.x+ | -| NEXT_PUBLIC_ROLLBAR_ENVIRONMENT | `string` | App env (e.g development, staging, e2e or production). Passed as `environment` property to Rollbar config | - | `development` | `production` | v1.37.x+ |   diff --git a/lib/api/useApiFetch.tsx b/lib/api/useApiFetch.tsx index 86e5fa9ea9..a3de353c6f 100644 --- a/lib/api/useApiFetch.tsx +++ b/lib/api/useApiFetch.tsx @@ -58,7 +58,7 @@ export default function useApiFetch() { }, { resource: resource.path, - omitSentryErrorLog: true, // disable logging of API errors to Sentry + omitMonitoringLog: true, // disable logging of API errors to Rollbar }, ); }, [ fetch, csrfToken ]); diff --git a/lib/hooks/useAddressProfileApiQuery.tsx b/lib/hooks/useAddressProfileApiQuery.tsx index 26298637fc..a637023f09 100644 --- a/lib/hooks/useAddressProfileApiQuery.tsx +++ b/lib/hooks/useAddressProfileApiQuery.tsx @@ -27,7 +27,7 @@ export default function useAddressProfileApiQuery(hash: string | undefined, isEn return Promise.reject(); } - return fetch(feature.apiUrlTemplate.replace('{address}', hash), undefined, { omitSentryErrorLog: true }); + return fetch(feature.apiUrlTemplate.replace('{address}', hash), undefined, { omitMonitoringLog: true }); }, enabled: isEnabled && Boolean(hash), refetchOnMount: false, diff --git a/lib/hooks/useFetch.tsx b/lib/hooks/useFetch.tsx index 06eea3fcae..caefe25ff4 100644 --- a/lib/hooks/useFetch.tsx +++ b/lib/hooks/useFetch.tsx @@ -1,8 +1,8 @@ -import * as Sentry from '@sentry/react'; import React from 'react'; import isBodyAllowed from 'lib/api/isBodyAllowed'; import type { ResourceError, ResourcePath } from 'lib/api/resources'; +import { useRollbar } from 'lib/rollbar'; export interface Params { method?: RequestInit['method']; @@ -14,10 +14,12 @@ export interface Params { interface Meta { resource?: ResourcePath; - omitSentryErrorLog?: boolean; + omitMonitoringLog?: boolean; } export default function useFetch() { + const rollbar = useRollbar(); + return React.useCallback((path: string, params?: Params, meta?: Meta): Promise> => { const _body = params?.body; const isFormData = _body instanceof FormData; @@ -51,13 +53,12 @@ export default function useFetch() { statusText: response.statusText, }; - if (!meta?.omitSentryErrorLog) { - Sentry.captureException(new Error('Client fetch failed'), { tags: { - source: 'fetch', - 'source.resource': meta?.resource, - 'status.code': error.status, - 'status.text': error.statusText, - } }); + if (!meta?.omitMonitoringLog && rollbar) { + rollbar.warn('Client fetch failed', { + resource: meta?.resource, + status_code: error.status, + status_text: error.statusText, + }); } return response.json().then( @@ -75,5 +76,5 @@ export default function useFetch() { return response.json() as Promise; } }); - }, [ ]); + }, [ rollbar ]); } diff --git a/lib/hooks/useGetCsrfToken.tsx b/lib/hooks/useGetCsrfToken.tsx index a301b25594..e1db1e595f 100644 --- a/lib/hooks/useGetCsrfToken.tsx +++ b/lib/hooks/useGetCsrfToken.tsx @@ -1,4 +1,3 @@ -import * as Sentry from '@sentry/react'; import { useQuery } from '@tanstack/react-query'; import buildUrl from 'lib/api/buildUrl'; @@ -6,9 +5,11 @@ import isNeedProxy from 'lib/api/isNeedProxy'; import { getResourceKey } from 'lib/api/useApiQuery'; import * as cookies from 'lib/cookies'; import useFetch from 'lib/hooks/useFetch'; +import { useRollbar } from 'lib/rollbar'; export default function useGetCsrfToken() { const nodeApiFetch = useFetch(); + const rollbar = useRollbar(); return useQuery({ queryKey: getResourceKey('csrf'), @@ -19,12 +20,11 @@ export default function useGetCsrfToken() { const csrfFromHeader = apiResponse.headers.get('x-bs-account-csrf'); if (!csrfFromHeader) { - Sentry.captureException(new Error('Client fetch failed'), { tags: { - source: 'fetch', - 'source.resource': 'csrf', - 'status.code': 500, - 'status.text': 'Unable to obtain csrf token from header', - } }); + rollbar?.warn('Client fetch failed', { + resource: 'csrf', + status_code: 500, + status_text: 'Unable to obtain csrf token from header', + }); return; } diff --git a/lib/hooks/useIsSafeAddress.tsx b/lib/hooks/useIsSafeAddress.tsx index 49062f7cc2..5796d175a9 100644 --- a/lib/hooks/useIsSafeAddress.tsx +++ b/lib/hooks/useIsSafeAddress.tsx @@ -15,7 +15,7 @@ export default function useIsSafeAddress(hash: string | undefined): boolean { return Promise.reject(); } - return fetch(`${ feature.apiUrl }/${ hash }`, undefined, { omitSentryErrorLog: true }); + return fetch(`${ feature.apiUrl }/${ hash }`, undefined, { omitMonitoringLog: true }); }, enabled: feature.isEnabled && Boolean(hash), refetchOnMount: false, diff --git a/lib/rollbar/index.tsx b/lib/rollbar/index.tsx index 233c06c9a6..9dfbb887a0 100644 --- a/lib/rollbar/index.tsx +++ b/lib/rollbar/index.tsx @@ -1,5 +1,6 @@ import { Provider as DefaultProvider, useRollbar as useRollbarDefault } from '@rollbar/react'; import type React from 'react'; +import type { Configuration } from 'rollbar'; import config from 'configs/app'; @@ -12,7 +13,11 @@ const useRollbarFallback = (): undefined => {}; export const Provider = feature.isEnabled ? DefaultProvider : FallbackProvider; export const useRollbar = feature.isEnabled ? useRollbarDefault : useRollbarFallback; -export const clientConfig = feature.isEnabled ? { +export const clientConfig: Configuration | undefined = feature.isEnabled ? { accessToken: feature.clientToken, environment: feature.environment, + payload: { + code_version: feature.codeVersion, + app_instance: feature.instance, + }, } : undefined; diff --git a/lib/sentry/config.ts b/lib/sentry/config.ts deleted file mode 100644 index f619c9346c..0000000000 --- a/lib/sentry/config.ts +++ /dev/null @@ -1,108 +0,0 @@ -import * as Sentry from '@sentry/react'; -import { BrowserTracing } from '@sentry/tracing'; - -import appConfig from 'configs/app'; -import { RESOURCE_LOAD_ERROR_MESSAGE } from 'lib/errors/throwOnResourceLoadError'; - -const feature = appConfig.features.sentry; - -export const config: Sentry.BrowserOptions | undefined = (() => { - if (!feature.isEnabled) { - return; - } - - const tracesSampleRate: number | undefined = (() => { - switch (feature.environment) { - case 'development': - return 1; - case 'staging': - return 0.75; - case 'production': - return 0.2; - } - })(); - - return { - environment: feature.environment, - dsn: feature.dsn, - release: feature.release, - enableTracing: feature.enableTracing, - tracesSampleRate, - integrations: feature.enableTracing ? [ new BrowserTracing() ] : undefined, - - // error filtering settings - // were taken from here - https://docs.sentry.io/platforms/node/guides/azure-functions/configuration/filtering/#decluttering-sentry - ignoreErrors: [ - // Random plugins/extensions - 'top.GLOBALS', - // See: http://blog.errorception.com/2012/03/tale-of-unfindable-js-error.html - 'originalCreateNotification', - 'canvas.contentDocument', - 'MyApp_RemoveAllHighlights', - 'http://tt.epicplay.com', - 'Can\'t find variable: ZiteReader', - 'jigsaw is not defined', - 'ComboSearch is not defined', - 'http://loading.retry.widdit.com/', - 'atomicFindClose', - // Facebook borked - 'fb_xd_fragment', - // ISP "optimizing" proxy - `Cache-Control: no-transform` seems to reduce this. (thanks @acdha) - // See http://stackoverflow.com/questions/4113268/how-to-stop-javascript-injection-from-vodafone-proxy - 'bmi_SafeAddOnload', - 'EBCallBackMessageReceived', - // See http://toolbar.conduit.com/Developer/HtmlAndGadget/Methods/JSInjection.aspx - 'conduitPage', - // Generic error code from errors outside the security sandbox - 'Script error.', - - // Relay and WalletConnect errors - 'The quota has been exceeded', - 'Attempt to connect to relay via', - 'WebSocket connection failed for URL: wss://relay.walletconnect.com', - - // API errors - RESOURCE_LOAD_ERROR_MESSAGE, - ], - denyUrls: [ - // Facebook flakiness - /graph\.facebook\.com/i, - // Facebook blocked - /connect\.facebook\.net\/en_US\/all\.js/i, - // Woopra flakiness - /eatdifferent\.com\.woopra-ns\.com/i, - /static\.woopra\.com\/js\/woopra\.js/i, - // Chrome and other extensions - /extensions\//i, - /^chrome:\/\//i, - /^chrome-extension:\/\//i, - /^moz-extension:\/\//i, - // Other plugins - /127\.0\.0\.1:4001\/isrunning/i, // Cacaoweb - /webappstoolbarba\.texthelp\.com\//i, - /metrics\.itunes\.apple\.com\.edgesuite\.net\//i, - - // AD fetch failed errors - /czilladx\.com/i, - /coinzilla\.com/i, - /coinzilla\.io/i, - /slise\.xyz/i, - ], - }; -})(); - -export function configureScope(scope: Sentry.Scope) { - if (!feature.isEnabled) { - return; - } - scope.setTag('app_instance', feature.instance); -} - -export function init() { - if (!config) { - return; - } - - Sentry.init(config); - Sentry.configureScope(configureScope); -} diff --git a/next.config.js b/next.config.js index e78614249b..1ac9991d07 100644 --- a/next.config.js +++ b/next.config.js @@ -18,13 +18,7 @@ const moduleExports = { 'swagger-ui-react', ], reactStrictMode: true, - webpack(config, { webpack }) { - config.plugins.push( - new webpack.DefinePlugin({ - __SENTRY_DEBUG__: false, - __SENTRY_TRACING__: false, - }), - ); + webpack(config) { config.module.rules.push( { test: /\.svg$/, diff --git a/nextjs/PageNextJs.tsx b/nextjs/PageNextJs.tsx index 89e066ca6d..9993410d8b 100644 --- a/nextjs/PageNextJs.tsx +++ b/nextjs/PageNextJs.tsx @@ -9,7 +9,6 @@ import useAdblockDetect from 'lib/hooks/useAdblockDetect'; import useGetCsrfToken from 'lib/hooks/useGetCsrfToken'; import * as metadata from 'lib/metadata'; import * as mixpanel from 'lib/mixpanel'; -import { init as initSentry } from 'lib/sentry/config'; interface Props { pathname: Pathname; @@ -18,8 +17,6 @@ interface Props { apiData?: PageProps['apiData']; } -initSentry(); - const PageNextJs = (props: Props) => { const { title, description, opengraph, canonical } = metadata.generate(props, props.apiData); diff --git a/nextjs/csp/generateCspPolicy.ts b/nextjs/csp/generateCspPolicy.ts index 2f178768df..5cce90bd7c 100644 --- a/nextjs/csp/generateCspPolicy.ts +++ b/nextjs/csp/generateCspPolicy.ts @@ -16,7 +16,6 @@ function generateCspPolicy() { descriptors.monaco(), descriptors.rollbar(), descriptors.safe(), - descriptors.sentry(), descriptors.usernameApi(), descriptors.walletConnect(), ); diff --git a/nextjs/csp/policies/app.ts b/nextjs/csp/policies/app.ts index 43b73147d0..946f976d49 100644 --- a/nextjs/csp/policies/app.ts +++ b/nextjs/csp/policies/app.ts @@ -11,25 +11,6 @@ const MAIN_DOMAINS = [ config.app.host, ].filter(Boolean); -const getCspReportUrl = () => { - try { - const sentryFeature = config.features.sentry; - if (!sentryFeature.isEnabled || !process.env.SENTRY_CSP_REPORT_URI) { - return; - } - - const url = new URL(process.env.SENTRY_CSP_REPORT_URI); - - // https://docs.sentry.io/product/security-policy-reporting/#additional-configuration - url.searchParams.set('sentry_environment', sentryFeature.environment); - sentryFeature.release && url.searchParams.set('sentry_release', sentryFeature.release); - - return url.toString(); - } catch (error) { - return; - } -}; - const externalFontsDomains = (() => { try { return [ @@ -148,17 +129,5 @@ export function app(): CspDev.DirectiveDescriptor { 'frame-ancestors': [ KEY_WORDS.SELF, ], - - ...((() => { - if (!config.features.sentry.isEnabled) { - return {}; - } - - return { - 'report-uri': [ - getCspReportUrl(), - ].filter(Boolean), - }; - })()), }; } diff --git a/nextjs/csp/policies/index.ts b/nextjs/csp/policies/index.ts index 456dad54a7..978a95a9c4 100644 --- a/nextjs/csp/policies/index.ts +++ b/nextjs/csp/policies/index.ts @@ -11,6 +11,5 @@ export { mixpanel } from './mixpanel'; export { monaco } from './monaco'; export { rollbar } from './rollbar'; export { safe } from './safe'; -export { sentry } from './sentry'; export { usernameApi } from './usernameApi'; export { walletConnect } from './walletConnect'; diff --git a/nextjs/csp/policies/sentry.ts b/nextjs/csp/policies/sentry.ts deleted file mode 100644 index 298c17a63e..0000000000 --- a/nextjs/csp/policies/sentry.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type CspDev from 'csp-dev'; - -export function sentry(): CspDev.DirectiveDescriptor { - return { - 'connect-src': [ - 'sentry.io', - '*.sentry.io', - ], - }; -} diff --git a/package.json b/package.json index 67eb984de3..fddafb44f3 100644 --- a/package.json +++ b/package.json @@ -60,9 +60,6 @@ "@opentelemetry/semantic-conventions": "1.22.0", "@rollbar/react": "0.12.0-beta", "@scure/base": "1.1.9", - "@sentry/cli": "^2.21.2", - "@sentry/react": "7.24.0", - "@sentry/tracing": "7.24.0", "@slise/embed-react": "^2.2.0", "@tanstack/react-query": "5.55.4", "@tanstack/react-query-devtools": "5.55.4", diff --git a/pages/404.tsx b/pages/404.tsx index 0e747ae875..bd4e020c0d 100644 --- a/pages/404.tsx +++ b/pages/404.tsx @@ -1,19 +1,21 @@ -import * as Sentry from '@sentry/react'; import React from 'react'; import type { NextPageWithLayout } from 'nextjs/types'; import PageNextJs from 'nextjs/PageNextJs'; +import { useRollbar } from 'lib/rollbar'; import AppError from 'ui/shared/AppError/AppError'; import LayoutError from 'ui/shared/layout/LayoutError'; const error = new Error('Not found', { cause: { status: 404 } }); const Page: NextPageWithLayout = () => { + const rollbar = useRollbar(); + React.useEffect(() => { - Sentry.captureException(new Error('Page not found'), { tags: { source: '404' } }); - }, []); + rollbar?.error('Page not found'); + }, [ rollbar ]); return ( diff --git a/ui/address/details/AddressQrCode.tsx b/ui/address/details/AddressQrCode.tsx index f3f58e546c..bbeaca7910 100644 --- a/ui/address/details/AddressQrCode.tsx +++ b/ui/address/details/AddressQrCode.tsx @@ -14,7 +14,6 @@ import { IconButton, Skeleton, } from '@chakra-ui/react'; -import * as Sentry from '@sentry/react'; import { useRouter } from 'next/router'; import QRCode from 'qrcode'; import React from 'react'; @@ -23,6 +22,7 @@ import type { Address as AddressType } from 'types/api/address'; import getPageType from 'lib/mixpanel/getPageType'; import * as mixpanel from 'lib/mixpanel/index'; +import { useRollbar } from 'lib/rollbar'; import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import IconSvg from 'ui/shared/IconSvg'; @@ -40,6 +40,7 @@ const AddressQrCode = ({ address, className, isLoading }: Props) => { const { isOpen, onOpen, onClose } = useDisclosure(); const router = useRouter(); + const rollbar = useRollbar(); const [ qr, setQr ] = React.useState(''); const [ error, setError ] = React.useState(''); @@ -51,7 +52,7 @@ const AddressQrCode = ({ address, className, isLoading }: Props) => { QRCode.toString(address.hash, SVG_OPTIONS, (error: Error | null | undefined, svg: string) => { if (error) { setError('We were unable to generate QR code.'); - Sentry.captureException(error, { tags: { source: 'qr_code' } }); + rollbar?.error('QR code generation failed'); return; } @@ -60,7 +61,7 @@ const AddressQrCode = ({ address, className, isLoading }: Props) => { mixpanel.logEvent(mixpanel.EventTypes.QR_CODE, { 'Page type': pageType }); }); } - }, [ address.hash, isOpen, onClose, pageType ]); + }, [ address.hash, isOpen, onClose, pageType, rollbar ]); if (isLoading) { return ; diff --git a/ui/snippets/auth/useRedirectForInvalidAuthToken.ts b/ui/snippets/auth/useRedirectForInvalidAuthToken.ts index afbb6a5d61..fd75c7a06f 100644 --- a/ui/snippets/auth/useRedirectForInvalidAuthToken.ts +++ b/ui/snippets/auth/useRedirectForInvalidAuthToken.ts @@ -1,10 +1,11 @@ -import * as Sentry from '@sentry/react'; import React from 'react'; import * as cookies from 'lib/cookies'; +import { useRollbar } from 'lib/rollbar'; import useProfileQuery from 'ui/snippets/auth/useProfileQuery'; export default function useRedirectForInvalidAuthToken() { + const rollbar = useRollbar(); const profileQuery = useProfileQuery(); const errorStatus = profileQuery.error?.status; @@ -13,10 +14,10 @@ export default function useRedirectForInvalidAuthToken() { const apiToken = cookies.get(cookies.NAMES.API_TOKEN); if (apiToken) { - Sentry.captureException(new Error('Invalid API token'), { tags: { source: 'invalid_api_token' } }); + rollbar?.warn('Invalid API token'); cookies.remove(cookies.NAMES.API_TOKEN); window.location.assign('/'); } } - }, [ errorStatus ]); + }, [ errorStatus, rollbar ]); } diff --git a/yarn.lock b/yarn.lock index 518d8d1275..d22e36261d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5125,70 +5125,6 @@ "@noble/hashes" "~1.5.0" "@scure/base" "~1.1.8" -"@sentry/browser@7.24.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.24.0.tgz#3e657f8032322d07f98486f44e048fcdbc3aaff7" - integrity sha512-G2eeYWF7rIz1Dm8PCQiuuTzctrrJSWqD5MCWOICqHr8FrxOPVsVO3Qa/B7/+BSpHd+V7sSUU17oFu41SAWZCOg== - dependencies: - "@sentry/core" "7.24.0" - "@sentry/types" "7.24.0" - "@sentry/utils" "7.24.0" - tslib "^1.9.3" - -"@sentry/cli@^2.21.2": - version "2.21.2" - resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.21.2.tgz#89e5633ff48a83d078c76c6997fffd4b68b2da1c" - integrity sha512-X1nye89zl+QV3FSuQDGItfM51tW9PQ7ce0TtV/12DgGgTVEgnVp5uvO3wX5XauHvulQzRPzwUL3ZK+yS5bAwCw== - 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" - -"@sentry/core@7.24.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.24.0.tgz#e856a071c702279854d6e5221957d61cd48036cc" - integrity sha512-QVRtmnaWEI0/MHIfBozgsMfh+7WU6OfpvUd72x1Dpk3Zk6Zs7Hqq0YfxfeBd7ApjNjGogPl1beaHcHAHlr3IyA== - dependencies: - "@sentry/types" "7.24.0" - "@sentry/utils" "7.24.0" - tslib "^1.9.3" - -"@sentry/react@7.24.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.24.0.tgz#aa51b09bad8c5d7af163a28a4718abb1e68ea232" - integrity sha512-uW6j7wrPxg7UillUVdsjrsIPqqPEAN/PdotR2O75Qh7s0aR7+Le8i29C4VeW/iubXhlxF/qFvnXwqG5Ji4GwBg== - dependencies: - "@sentry/browser" "7.24.0" - "@sentry/types" "7.24.0" - "@sentry/utils" "7.24.0" - hoist-non-react-statics "^3.3.2" - tslib "^1.9.3" - -"@sentry/tracing@7.24.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-7.24.0.tgz#d9477a2da9c902ca9663cd4cd87ba279f73f212c" - integrity sha512-O/4hE/lYM6+hM4K5O06pWNuHzZb2ex5f2497bxkwxq17wpJhVp1oDuz8hbWNL7BUNeIbeDpqunBHQzzmVRbL1Q== - dependencies: - "@sentry/core" "7.24.0" - "@sentry/types" "7.24.0" - "@sentry/utils" "7.24.0" - tslib "^1.9.3" - -"@sentry/types@7.24.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.24.0.tgz#1acc841efe7bd56fc3eb647a613dba92631e8413" - integrity sha512-Xs4r9esBPieJUA6cGmMqfSQiinILdlhScjM+NqDSzxOo8+LRCJzckTLhUttBGVlaAoa4hjCEsfkHA1tVV1DycA== - -"@sentry/utils@7.24.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.24.0.tgz#73f100dc8942e73353473eaf3168e5052e2f45be" - integrity sha512-baaRDhHWHTyhmR6V8YKSo0NvN+D17pIKRDmb2vpWHVpTjobKCivNBLRoy3VhnIMS/24XyZnL028QLwkUNLg1Ug== - dependencies: - "@sentry/types" "7.24.0" - tslib "^1.9.3" - "@sideway/address@^4.1.3": version "4.1.4" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" @@ -11086,7 +11022,7 @@ http-shutdown@^1.2.2: resolved "https://registry.yarnpkg.com/http-shutdown/-/http-shutdown-1.2.2.tgz#41bc78fc767637c4c95179bc492f312c0ae64c5f" integrity sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw== -https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: +https-proxy-agent@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== @@ -13957,11 +13893,6 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== -progress@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - prom-client@15.1.1: version "15.1.1" resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-15.1.1.tgz#71ba84371241acd173181b04a436782c246f3652" @@ -15972,7 +15903,7 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@1.14.1, tslib@^1.8.1, tslib@^1.9.3: +tslib@1.14.1, tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -16640,7 +16571,7 @@ which-typed-array@^1.1.2, which-typed-array@^1.1.8, which-typed-array@^1.1.9: has-tostringtag "^1.0.0" is-typed-array "^1.1.10" -which@^2.0.1, which@^2.0.2: +which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== From 96c35d52ce21ddca39af77fcdf1858f276358858 Mon Sep 17 00:00:00 2001 From: tom Date: Fri, 15 Nov 2024 18:41:32 +0100 Subject: [PATCH 3/8] add rollback env to values for demo --- deploy/values/review/values.yaml.gotmpl | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/values/review/values.yaml.gotmpl b/deploy/values/review/values.yaml.gotmpl index ebbbf2a229..c74841a947 100644 --- a/deploy/values/review/values.yaml.gotmpl +++ b/deploy/values/review/values.yaml.gotmpl @@ -85,3 +85,4 @@ frontend: NEXT_PUBLIC_GROWTH_BOOK_CLIENT_KEY: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_GROWTH_BOOK_CLIENT_KEY NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_RE_CAPTCHA_V3_APP_SITE_KEY + NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN: ref+vault://deployment-values/blockscout/common?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN From 0a9b9c62b88a104a2151eb586327f733113da5b0 Mon Sep 17 00:00:00 2001 From: tom Date: Fri, 15 Nov 2024 19:02:59 +0100 Subject: [PATCH 4/8] [skip ci] adjust instance name --- configs/app/features/rollbar.ts | 2 +- deploy/values/review-l2/values.yaml.gotmpl | 3 +-- deploy/values/review/values.yaml.gotmpl | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/configs/app/features/rollbar.ts b/configs/app/features/rollbar.ts index 671e6ab131..88691a7577 100644 --- a/configs/app/features/rollbar.ts +++ b/configs/app/features/rollbar.ts @@ -10,7 +10,7 @@ const instance = (() => { return envValue; } - return app.host?.replace('.blockscout.com', '').replaceAll('-', '_'); + return app.host?.replace('.blockscout.com', '').replace('.k8s-dev', '').replaceAll('-', '_'); })(); const environment = getEnvValue('NEXT_PUBLIC_APP_ENV') || 'development'; const codeVersion = getEnvValue('NEXT_PUBLIC_GIT_TAG') || getEnvValue('NEXT_PUBLIC_GIT_COMMIT_SHA'); diff --git a/deploy/values/review-l2/values.yaml.gotmpl b/deploy/values/review-l2/values.yaml.gotmpl index a3f2535534..492ba76c9c 100644 --- a/deploy/values/review-l2/values.yaml.gotmpl +++ b/deploy/values/review-l2/values.yaml.gotmpl @@ -47,8 +47,7 @@ frontend: memory: 384Mi cpu: 250m env: - NEXT_PUBLIC_APP_ENV: development - NEXT_PUBLIC_APP_INSTANCE: review + NEXT_PUBLIC_APP_ENV: review NEXT_PUBLIC_NETWORK_LOGO: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/base.svg NEXT_PUBLIC_NETWORK_ICON: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/base.svg NEXT_PUBLIC_FEATURED_NETWORKS: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/base-mainnet.json diff --git a/deploy/values/review/values.yaml.gotmpl b/deploy/values/review/values.yaml.gotmpl index c74841a947..30eda36084 100644 --- a/deploy/values/review/values.yaml.gotmpl +++ b/deploy/values/review/values.yaml.gotmpl @@ -47,8 +47,7 @@ frontend: memory: 384Mi cpu: 250m env: - NEXT_PUBLIC_APP_ENV: development - NEXT_PUBLIC_APP_INSTANCE: review + NEXT_PUBLIC_APP_ENV: review NEXT_PUBLIC_FEATURED_NETWORKS: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-sepolia.json NEXT_PUBLIC_NETWORK_LOGO: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/sepolia.svg NEXT_PUBLIC_NETWORK_ICON: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/sepolia.png From 8339d379a82f1563805c0d6fa07f5a2b98980c67 Mon Sep 17 00:00:00 2001 From: tom Date: Fri, 15 Nov 2024 19:30:51 +0100 Subject: [PATCH 5/8] fix validator --- deploy/tools/envs-validator/schema.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/deploy/tools/envs-validator/schema.ts b/deploy/tools/envs-validator/schema.ts index 699084b552..5ae8d12b31 100644 --- a/deploy/tools/envs-validator/schema.ts +++ b/deploy/tools/envs-validator/schema.ts @@ -354,12 +354,6 @@ const sentrySchema = yup }), }); -const rollbarSchema = yup - .object() - .shape({ - NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN: yup.string().required(), - }); - const accountSchema = yup .object() .shape({ @@ -854,6 +848,7 @@ const schema = yup NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID: yup.string(), NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN: yup.string(), NEXT_PUBLIC_GROWTH_BOOK_CLIENT_KEY: yup.string(), + NEXT_PUBLIC_ROLLBAR_CLIENT_TOKEN: yup.string(), // Misc NEXT_PUBLIC_USE_NEXT_JS_PROXY: yup.boolean(), @@ -864,7 +859,6 @@ const schema = yup .concat(rollupSchema) .concat(beaconChainSchema) .concat(bridgedTokensSchema) - .concat(sentrySchema) - .concat(rollbarSchema); + .concat(sentrySchema); export default schema; From 742e3815193689df3b1818c6f46311d58d12490f Mon Sep 17 00:00:00 2001 From: tom Date: Mon, 18 Nov 2024 12:27:16 +0100 Subject: [PATCH 6/8] don't log errors from API by default and change error levels --- lib/api/useApiFetch.tsx | 5 +++-- lib/api/useApiQuery.tsx | 5 +++-- lib/hooks/useAddressProfileApiQuery.tsx | 2 +- lib/hooks/useFetch.tsx | 4 ++-- lib/hooks/useIsSafeAddress.tsx | 2 +- ui/address/details/AddressQrCode.tsx | 2 +- ui/address/utils/useAddressQuery.ts | 1 + ui/shared/AppError/AppErrorBoundary.tsx | 12 +++++++++++- ui/snippets/auth/useRedirectForInvalidAuthToken.ts | 1 - 9 files changed, 23 insertions(+), 11 deletions(-) diff --git a/lib/api/useApiFetch.tsx b/lib/api/useApiFetch.tsx index a3de353c6f..cda519c1c1 100644 --- a/lib/api/useApiFetch.tsx +++ b/lib/api/useApiFetch.tsx @@ -21,6 +21,7 @@ export interface Params { pathParams?: ResourcePathParams; queryParams?: Record | number | boolean | undefined | null>; fetchParams?: Pick; + logError?: boolean; } export default function useApiFetch() { @@ -30,7 +31,7 @@ export default function useApiFetch() { return React.useCallback(( resourceName: R, - { pathParams, queryParams, fetchParams }: Params = {}, + { pathParams, queryParams, fetchParams, logError }: Params = {}, ) => { const apiToken = cookies.get(cookies.NAMES.API_TOKEN); @@ -58,7 +59,7 @@ export default function useApiFetch() { }, { resource: resource.path, - omitMonitoringLog: true, // disable logging of API errors to Rollbar + logError, }, ); }, [ fetch, csrfToken ]); diff --git a/lib/api/useApiQuery.tsx b/lib/api/useApiQuery.tsx index 8dfa918b8c..6cd58c024e 100644 --- a/lib/api/useApiQuery.tsx +++ b/lib/api/useApiQuery.tsx @@ -11,6 +11,7 @@ export interface Params | number | boolean | undefined>; fetchParams?: Pick; queryOptions?: Partial, ResourceError, D>, 'queryFn'>>; + logError?: boolean; } export function getResourceKey(resource: R, { pathParams, queryParams }: Params = {}) { @@ -23,7 +24,7 @@ export function getResourceKey(resource: R, { pathParams export default function useApiQuery>( resource: R, - { queryOptions, pathParams, queryParams, fetchParams }: Params = {}, + { queryOptions, pathParams, queryParams, fetchParams, logError }: Params = {}, ) { const apiFetch = useApiFetch(); @@ -33,7 +34,7 @@ export default function useApiQuery>" - return apiFetch(resource, { pathParams, queryParams, fetchParams: { ...fetchParams, signal } }) as Promise>; + return apiFetch(resource, { pathParams, queryParams, logError, fetchParams: { ...fetchParams, signal } }) as Promise>; }, ...queryOptions, }); diff --git a/lib/hooks/useAddressProfileApiQuery.tsx b/lib/hooks/useAddressProfileApiQuery.tsx index a637023f09..ef39555d43 100644 --- a/lib/hooks/useAddressProfileApiQuery.tsx +++ b/lib/hooks/useAddressProfileApiQuery.tsx @@ -27,7 +27,7 @@ export default function useAddressProfileApiQuery(hash: string | undefined, isEn return Promise.reject(); } - return fetch(feature.apiUrlTemplate.replace('{address}', hash), undefined, { omitMonitoringLog: true }); + return fetch(feature.apiUrlTemplate.replace('{address}', hash)); }, enabled: isEnabled && Boolean(hash), refetchOnMount: false, diff --git a/lib/hooks/useFetch.tsx b/lib/hooks/useFetch.tsx index caefe25ff4..4b50945f97 100644 --- a/lib/hooks/useFetch.tsx +++ b/lib/hooks/useFetch.tsx @@ -14,7 +14,7 @@ export interface Params { interface Meta { resource?: ResourcePath; - omitMonitoringLog?: boolean; + logError?: boolean; } export default function useFetch() { @@ -53,7 +53,7 @@ export default function useFetch() { statusText: response.statusText, }; - if (!meta?.omitMonitoringLog && rollbar) { + if (meta?.logError && rollbar) { rollbar.warn('Client fetch failed', { resource: meta?.resource, status_code: error.status, diff --git a/lib/hooks/useIsSafeAddress.tsx b/lib/hooks/useIsSafeAddress.tsx index 5796d175a9..7888050a6c 100644 --- a/lib/hooks/useIsSafeAddress.tsx +++ b/lib/hooks/useIsSafeAddress.tsx @@ -15,7 +15,7 @@ export default function useIsSafeAddress(hash: string | undefined): boolean { return Promise.reject(); } - return fetch(`${ feature.apiUrl }/${ hash }`, undefined, { omitMonitoringLog: true }); + return fetch(`${ feature.apiUrl }/${ hash }`); }, enabled: feature.isEnabled && Boolean(hash), refetchOnMount: false, diff --git a/ui/address/details/AddressQrCode.tsx b/ui/address/details/AddressQrCode.tsx index bbeaca7910..4a3f3970a0 100644 --- a/ui/address/details/AddressQrCode.tsx +++ b/ui/address/details/AddressQrCode.tsx @@ -52,7 +52,7 @@ const AddressQrCode = ({ address, className, isLoading }: Props) => { QRCode.toString(address.hash, SVG_OPTIONS, (error: Error | null | undefined, svg: string) => { if (error) { setError('We were unable to generate QR code.'); - rollbar?.error('QR code generation failed'); + rollbar?.warn('QR code generation failed'); return; } diff --git a/ui/address/utils/useAddressQuery.ts b/ui/address/utils/useAddressQuery.ts index 3f1ae73929..ebeac2eb25 100644 --- a/ui/address/utils/useAddressQuery.ts +++ b/ui/address/utils/useAddressQuery.ts @@ -45,6 +45,7 @@ export default function useAddressQuery({ hash, isEnabled = true }: Params): Add return isRefetchEnabled ? 15 * SECOND : false; }, }, + logError: true, }); const rpcQuery = useQuery({ diff --git a/ui/shared/AppError/AppErrorBoundary.tsx b/ui/shared/AppError/AppErrorBoundary.tsx index 0560476c29..4c666967be 100644 --- a/ui/shared/AppError/AppErrorBoundary.tsx +++ b/ui/shared/AppError/AppErrorBoundary.tsx @@ -1,6 +1,7 @@ import { chakra } from '@chakra-ui/react'; import React from 'react'; +import getErrorCauseStatusCode from 'lib/errors/getErrorCauseStatusCode'; import { useRollbar } from 'lib/rollbar'; import ErrorBoundary from 'ui/shared/ErrorBoundary'; @@ -25,7 +26,16 @@ const AppErrorBoundary = ({ className, children, Container }: Props) => { }, [ className, Container ]); const handleError = React.useCallback((error: Error) => { - rollbar?.error(error); + const statusCode = getErrorCauseStatusCode(error); + if (statusCode || !rollbar) { + // For now, we are not interested in logging errors from the API. + // If an error from a resource should be logged, please consider passing "logError: true" to the useApiQuery or useApiFetch hook. + return; + } + + // To this point, there can only be errors that lead to a page crash. + // Therefore, we set the error level to "critical." + rollbar.critical(error); }, [ rollbar ]); return ( diff --git a/ui/snippets/auth/useRedirectForInvalidAuthToken.ts b/ui/snippets/auth/useRedirectForInvalidAuthToken.ts index fd75c7a06f..96634a138b 100644 --- a/ui/snippets/auth/useRedirectForInvalidAuthToken.ts +++ b/ui/snippets/auth/useRedirectForInvalidAuthToken.ts @@ -14,7 +14,6 @@ export default function useRedirectForInvalidAuthToken() { const apiToken = cookies.get(cookies.NAMES.API_TOKEN); if (apiToken) { - rollbar?.warn('Invalid API token'); cookies.remove(cookies.NAMES.API_TOKEN); window.location.assign('/'); } From cebd49c958e113a9f8156c2cb28dba67cf194712 Mon Sep 17 00:00:00 2001 From: tom Date: Mon, 18 Nov 2024 13:28:13 +0100 Subject: [PATCH 7/8] [skip ci] change default value for environment property --- configs/app/features/rollbar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/app/features/rollbar.ts b/configs/app/features/rollbar.ts index 88691a7577..276f782e4e 100644 --- a/configs/app/features/rollbar.ts +++ b/configs/app/features/rollbar.ts @@ -12,7 +12,7 @@ const instance = (() => { return app.host?.replace('.blockscout.com', '').replace('.k8s-dev', '').replaceAll('-', '_'); })(); -const environment = getEnvValue('NEXT_PUBLIC_APP_ENV') || 'development'; +const environment = getEnvValue('NEXT_PUBLIC_APP_ENV') || 'production'; const codeVersion = getEnvValue('NEXT_PUBLIC_GIT_TAG') || getEnvValue('NEXT_PUBLIC_GIT_COMMIT_SHA'); const title = 'Rollbar error monitoring'; From 30aed673ce842e3e28fa04381ce28bce4ae68653 Mon Sep 17 00:00:00 2001 From: tom Date: Wed, 27 Nov 2024 19:57:00 +0100 Subject: [PATCH 8/8] [skip ci] do not log api errors of address endpoint --- ui/address/utils/useAddressQuery.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/address/utils/useAddressQuery.ts b/ui/address/utils/useAddressQuery.ts index ebeac2eb25..3f1ae73929 100644 --- a/ui/address/utils/useAddressQuery.ts +++ b/ui/address/utils/useAddressQuery.ts @@ -45,7 +45,6 @@ export default function useAddressQuery({ hash, isEnabled = true }: Params): Add return isRefetchEnabled ? 15 * SECOND : false; }, }, - logError: true, }); const rpcQuery = useQuery({