diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 733d98b6..3b326a11 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -49,9 +49,12 @@ jobs: SITE_DEFAULT_TITLE = "${{ secrets.SITE_DEFAULT_TITLE }}" GA_TRACKING_ID = "${{ secrets.GA_TRACKING_ID }}" PROOFMARKET_TOOLCHAIN_REPO = "${{ secrets.PROOFMARKET_TOOLCHAIN_REPO }}" - SENTRY_DSN = "${{ secrets.SENTRY_DSN }}" CIRCUIT_DEVELOPER_GUIDE_URL = "${{ secrets.CIRCUIT_DEVELOPER_GUIDE_URL }}" API_RESPONSE_WAIT_TIMEOUT = "${{ secrets.API_RESPONSE_WAIT_TIMEOUT }}" + DATADOG_APPLICATION_ID = "${{ secrets.DATADOG_APPLICATION_ID }}" + DATADOG_CLIENT_TOKEN = "${{ secrets.DATADOG_CLIENT_TOKEN }}" + DATADOG_SITE = "${{ secrets.DATADOG_SITE }}" + DATADOG_SERVICE_NAME = "${{ secrets.DATADOG_SERVICE_NAME }}" ' echo "$config" > runtime-config.toml echo runtime-config.toml diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d3493be0..39255482 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -5,8 +5,6 @@ on: push: tags: - 'v*' - branches: - - master jobs: release: diff --git a/.husky/pre-commit b/.husky/pre-commit old mode 100644 new mode 100755 diff --git a/.vscode/settings.json b/.vscode/settings.json index 9910d572..6b9cac07 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,17 +1,17 @@ { "[typescript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[typescriptreact]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[javascript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "esbenp.prettier-vscode" }, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "editor.formatOnSave": true, "editor.formatOnPaste": true, - "editor.formatOnType": true, + "editor.formatOnType": true } diff --git a/package-lock.json b/package-lock.json index 8afc93b2..514f94d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,12 +8,11 @@ "name": "proof-market.frontend", "version": "0.1.7", "dependencies": { + "@datadog/browser-rum": "^5.17.1", "@loadable/component": "^5.15.3", "@nilfoundation/react-components": "^0.8.3", "@nilfoundation/ui-kit": "^2.1.3", "@reduxjs/toolkit": "^1.8.5", - "@sentry/react": "^7.21.1", - "@sentry/tracing": "^7.21.1", "baseui": "^13.0.0", "bootstrap-sass": "^3.4.3", "clsx": "^1.2.1", @@ -29,6 +28,7 @@ "react-copy-to-clipboard": "^5.1.0", "react-dom": "18.2.0", "react-dropzone": "^14.2.3", + "react-error-boundary": "^4.0.13", "react-ga4": "^1.4.1", "react-helmet-async": "^1.3.0", "react-hook-form": "^7.39.1", @@ -1932,6 +1932,36 @@ "w3c-keyname": "^2.2.4" } }, + "node_modules/@datadog/browser-core": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/@datadog/browser-core/-/browser-core-5.17.1.tgz", + "integrity": "sha512-OsdjeRCCT1U9+ddygqg3PkqHOkkk7Vr2tI3U8xgZQyiqCzCuooDHebq/40UMP6mf9OVETDkqlSWQ/ouqvFKjUQ==" + }, + "node_modules/@datadog/browser-rum": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/@datadog/browser-rum/-/browser-rum-5.17.1.tgz", + "integrity": "sha512-BiXA47pBTCjifQxseEVDsrKzLByMdhcp223z8LpyJfjAjMsJad0qxJV5EC+sXANN6yXvpCiC0IjMWNpNHRqpIA==", + "dependencies": { + "@datadog/browser-core": "5.17.1", + "@datadog/browser-rum-core": "5.17.1" + }, + "peerDependencies": { + "@datadog/browser-logs": "5.17.1" + }, + "peerDependenciesMeta": { + "@datadog/browser-logs": { + "optional": true + } + } + }, + "node_modules/@datadog/browser-rum-core": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/@datadog/browser-rum-core/-/browser-rum-core-5.17.1.tgz", + "integrity": "sha512-tb+kzIR5C5EHeCXLiTW5bQTm4T1KsuBUE+Xdf1MJJlpcPKtiqnNKS2gJ1OJQpfuOHWwWrGsH2tIO7fZUtALqAg==", + "dependencies": { + "@datadog/browser-core": "5.17.1" + } + }, "node_modules/@date-io/core": { "version": "2.17.0", "resolved": "https://registry.npmjs.org/@date-io/core/-/core-2.17.0.tgz", @@ -2728,107 +2758,6 @@ "resolved": "https://registry.npmjs.org/@rtsao/csstype/-/csstype-2.6.5-forked.0.tgz", "integrity": "sha512-0HwnY8uPWcCloTgdbbaJG3MbDUfNf6yKWZfCKxFv9yj2Sbp4mSKaIjC7Cr/5L4hMxvrrk85CU3wlAg7EtBBJ1Q==" }, - "node_modules/@sentry-internal/tracing": { - "version": "7.81.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.81.0.tgz", - "integrity": "sha512-mc3tdOEvAE6kaCvT3BpMwCgfTT2yfXjWpC7g+3N8U/yuQEmQSCDZA/ut7EkzU0DyhG3t8HzT0c+CAG3HtilEAQ==", - "dependencies": { - "@sentry/core": "7.81.0", - "@sentry/types": "7.81.0", - "@sentry/utils": "7.81.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/browser": { - "version": "7.81.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.81.0.tgz", - "integrity": "sha512-/6xsdSeZspq7+LARg6Gt0KMUQRf6nZcuA20X9Y28uJqyZFYoXBnxG3+JJcxycxleEJRci20gjBwOtM157anUJA==", - "dependencies": { - "@sentry-internal/tracing": "7.81.0", - "@sentry/core": "7.81.0", - "@sentry/replay": "7.81.0", - "@sentry/types": "7.81.0", - "@sentry/utils": "7.81.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/core": { - "version": "7.81.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.81.0.tgz", - "integrity": "sha512-FCAKlqo9Z6fku69bkahw1AN+eBfAgRgOL1RpBLZgyG7YBW12vtSkHb5SDvZZTkm541Fo3hhepUTLtX0qmpA4yw==", - "dependencies": { - "@sentry/types": "7.81.0", - "@sentry/utils": "7.81.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/react": { - "version": "7.81.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.81.0.tgz", - "integrity": "sha512-r6MlVc9I6I3frFGvQ3DKjtt6AAZYHxShOYWoxc7vUxNHp6Tgm8d73Y19EbKCLEXzIKdCp2OR7zQJtY0kYe3Isg==", - "dependencies": { - "@sentry/browser": "7.81.0", - "@sentry/types": "7.81.0", - "@sentry/utils": "7.81.0", - "hoist-non-react-statics": "^3.3.2" - }, - "engines": { - "node": ">=8" - }, - "peerDependencies": { - "react": "15.x || 16.x || 17.x || 18.x" - } - }, - "node_modules/@sentry/replay": { - "version": "7.81.0", - "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.81.0.tgz", - "integrity": "sha512-kJRWjEzby1015Ds5TTNNVe9EkzfwPfPcM06ycba+DIXPJ2LiaSXvH3OU0s2HEJ9Vo/+jcpFMlODXFF/wrYIn9w==", - "dependencies": { - "@sentry-internal/tracing": "7.81.0", - "@sentry/core": "7.81.0", - "@sentry/types": "7.81.0", - "@sentry/utils": "7.81.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@sentry/tracing": { - "version": "7.81.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.81.0.tgz", - "integrity": "sha512-3QRusk7AZzbNWuPalqSCQCPAEJ9L167txYUkL5x3Y+YK4gZt3/bNovoVNDaQ06XmIYL9ENXVw1hbdk0DIgirpw==", - "dependencies": { - "@sentry-internal/tracing": "7.81.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/types": { - "version": "7.81.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.81.0.tgz", - "integrity": "sha512-rbYNYSSrrnwNndC7S+eVT84GRLEyCZNh9oXUQqzgSD6ngXCZ0xFJW6si75uv/XQBWIw4rkj9xfRcy8DU0Tj4fg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/utils": { - "version": "7.81.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.81.0.tgz", - "integrity": "sha512-yC9IvfeVbG4dygi4b+iUUMHp9xeHJfCn6XLbqjJVfq3xjAzBGHgfrpw6fYPNyTljXKb6CTiSXSqaNaQJE4CkPA==", - "dependencies": { - "@sentry/types": "7.81.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@types/connect-history-api-fallback": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", @@ -8127,6 +8056,17 @@ "react": ">= 16.8 || 18.0.0" } }, + "node_modules/react-error-boundary": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.13.tgz", + "integrity": "sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ==", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, "node_modules/react-fast-compare": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", diff --git a/package.json b/package.json index b6f9efc7..76aa09ca 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,11 @@ "version": "0.1.7", "private": true, "dependencies": { + "@datadog/browser-rum": "^5.17.1", "@loadable/component": "^5.15.3", "@nilfoundation/react-components": "^0.8.3", "@nilfoundation/ui-kit": "^2.1.3", "@reduxjs/toolkit": "^1.8.5", - "@sentry/react": "^7.21.1", - "@sentry/tracing": "^7.21.1", "baseui": "^13.0.0", "bootstrap-sass": "^3.4.3", "clsx": "^1.2.1", @@ -24,6 +23,7 @@ "react-copy-to-clipboard": "^5.1.0", "react-dom": "18.2.0", "react-dropzone": "^14.2.3", + "react-error-boundary": "^4.0.13", "react-ga4": "^1.4.1", "react-helmet-async": "^1.3.0", "react-hook-form": "^7.39.1", diff --git a/public/runtime-config.toml b/public/runtime-config.toml index bea9de59..595eaea5 100644 --- a/public/runtime-config.toml +++ b/public/runtime-config.toml @@ -6,6 +6,9 @@ READONLY_USER = "" SITE_DEFAULT_TITLE = "" GA_TRACKING_ID = "" PROOFMARKET_TOOLCHAIN_REPO = "" -SENTRY_DSN = "" CIRCUIT_DEVELOPER_GUIDE_URL = "" API_RESPONSE_WAIT_TIMEOUT = "" +DATADOG_APPLICATION_ID = "" +DATADOG_CLIENT_TOKEN = "" +DATADOG_SITE = "" +DATADOG_SERVICE_NAME = "" diff --git a/src/App.tsx b/src/App.tsx index 32bb38e0..0104e07b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,7 +5,7 @@ import type { ReactElement } from 'react'; import { Suspense } from 'react'; -import { ErrorBoundary, withProfiler } from '@sentry/react'; +import { ErrorBoundary } from 'react-error-boundary'; import { Helmet } from 'react-helmet-async'; import { FullScreenLoader, GALocationTracker, PageVisibilityDetector } from './components'; import { Router, routesConfig as desktopRoutesConfig } from './features/routing'; @@ -41,4 +41,4 @@ function App(): ReactElement { ); } -export default withProfiler(App); +export default App; diff --git a/src/datadog.ts b/src/datadog.ts new file mode 100644 index 00000000..e301c1bd --- /dev/null +++ b/src/datadog.ts @@ -0,0 +1,40 @@ +/** + * @file Datadog rum configuration. + * @copyright Yury Korotovskikh + */ + +import { datadogRum } from '@datadog/browser-rum'; +import { getRuntimeConfigOrThrow } from './utils'; + +/** + * Configures Datadog Real User Monitoring (RUM) for the application. + * + * @see {@link https://docs.datadoghq.com/real_user_monitoring/browser/} + */ +export const configureDatadogRUM = (): void => { + // if (!import.meta.env.PROD) { + // return; + // } + + const { DATADOG_APPLICATION_ID, DATADOG_CLIENT_TOKEN, DATADOG_SERVICE_NAME, DATADOG_SITE } = + getRuntimeConfigOrThrow(); + + if (!DATADOG_APPLICATION_ID || !DATADOG_CLIENT_TOKEN || !DATADOG_SERVICE_NAME || !DATADOG_SITE) { + return; + } + + datadogRum.init({ + applicationId: DATADOG_APPLICATION_ID, + clientToken: DATADOG_CLIENT_TOKEN, + site: DATADOG_SITE, + service: DATADOG_SERVICE_NAME, + env: 'production', + sessionSampleRate: 100, + sessionReplaySampleRate: 100, + trackResources: false, + trackLongTasks: false, + trackUserInteractions: false, + silentMultipleInit: true, + allowFallbackToLocalStorage: true, + }); +}; diff --git a/src/index.tsx b/src/index.tsx index 7a659737..077e1744 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -15,14 +15,14 @@ import { Provider as StyletronProvider } from 'styletron-react'; import { BaseProvider } from 'baseui'; import App from './App'; import { store } from './redux'; -import { configureSentry } from './sentry'; +import { configureDatadogRUM } from './datadog'; import { reportWebVitals } from './reportWebVitals'; import configureGA from './ga'; //import * as serviceWorkerRegistration from './serviceWorkerRegistration'; import { checkRuntimeConfig } from './utils'; checkRuntimeConfig(); -configureSentry(); +configureDatadogRUM(); configureGA(); const engine = new Styletron(); diff --git a/src/sentry.ts b/src/sentry.ts deleted file mode 100644 index 9b2f45dc..00000000 --- a/src/sentry.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @file Sentry configuration. - * @copyright Yury Korotovskikh - */ - -import * as Sentry from '@sentry/react'; -import { BrowserTracing } from '@sentry/tracing'; -import { getRuntimeConfigOrThrow } from './utils'; - -/** - * Configures sentry for app. - * - * @see {@link https://docs.sentry.io/platforms/javascript/guides/react/} - */ -export const configureSentry = (): void => { - if (!import.meta.env.PROD) { - return; - } - - const dsn = getRuntimeConfigOrThrow().SENTRY_DSN; - - if (!dsn) { - return; - } - - Sentry.init({ - dsn, - integrations: [new BrowserTracing()], - tracesSampleRate: 0.2, - denyUrls: [ - // Chrome extensions - /extensions\//i, - /^chrome/i, - ], - }); -}; diff --git a/src/types/runtime-config.d.ts b/src/types/runtime-config.d.ts index 7e4048bd..743e26d6 100644 --- a/src/types/runtime-config.d.ts +++ b/src/types/runtime-config.d.ts @@ -13,10 +13,13 @@ const keys = [ 'SITE_DEFAULT_TITLE', 'PROOFMARKET_TOOLCHAIN_REPO', 'REVALIDATE_DATA_INTERVAL', - 'SENTRY_DSN', 'GA_TRACKING_ID', 'CIRCUIT_DEVELOPER_GUIDE_URL', 'API_RESPONSE_WAIT_TIMEOUT', + 'DATADOG_APPLICATION_ID', + 'DATADOG_CLIENT_TOKEN', + 'DATADOG_SITE', + 'DATADOG_SERVICE_NAME', ] as const; type RuntimConfigKeys = (typeof keys)[number]; diff --git a/src/utils/runtimeConfig/checkRuntimeConfig.ts b/src/utils/runtimeConfig/checkRuntimeConfig.ts index 0633fe13..c6684d10 100644 --- a/src/utils/runtimeConfig/checkRuntimeConfig.ts +++ b/src/utils/runtimeConfig/checkRuntimeConfig.ts @@ -15,6 +15,10 @@ const requiredEnvs: Array = [ 'PROOFMARKET_TOOLCHAIN_REPO', 'SITE_DEFAULT_TITLE', 'CIRCUIT_DEVELOPER_GUIDE_URL', + 'DATADOG_APPLICATION_ID', + 'DATADOG_CLIENT_TOKEN', + 'DATADOG_SITE', + 'DATADOG_SERVICE_NAME', ]; /**