diff --git a/.github/workflows/build-and-deploy-production.yml b/.github/workflows/build-and-deploy-production.yml index 26f73aae..6ced2d48 100644 --- a/.github/workflows/build-and-deploy-production.yml +++ b/.github/workflows/build-and-deploy-production.yml @@ -51,6 +51,11 @@ jobs: GD_APP_ID: ${{ secrets.GD_APP_ID }} GD_CLIENT_ID: ${{ secrets.GD_CLIENT_ID }} TRACKJS_TOKEN: ${{ secrets.TRACKJS_TOKEN }} + DATADOG_APPLICATION_ID: ${{ secrets.DATADOG_APPLICATION_ID }} + DATADOG_CLIENT_TOKEN: ${{ secrets.DATADOG_CLIENT_TOKEN }} + DATADOG_SESSION_REPLAY_SAMPLE_RATE: ${{ vars.DATADOG_SESSION_REPLAY_SAMPLE_RATE }} + DATADOG_SESSION_SAMPLE_RATE: ${{ vars.DATADOG_SESSION_SAMPLE_RATE }} + REF_NAME: ${{ github.ref_name }} - name: Run tests for Eslint run: npm run test:lint diff --git a/.github/workflows/build-and-deploy-staging.yml b/.github/workflows/build-and-deploy-staging.yml index e9aa1a8a..1c962374 100644 --- a/.github/workflows/build-and-deploy-staging.yml +++ b/.github/workflows/build-and-deploy-staging.yml @@ -50,6 +50,11 @@ jobs: GD_API_KEY: ${{ secrets.GD_API_KEY }} GD_APP_ID: ${{ secrets.GD_APP_ID }} GD_CLIENT_ID: ${{ secrets.GD_CLIENT_ID }} + DATADOG_APPLICATION_ID: ${{ secrets.DATADOG_APPLICATION_ID }} + DATADOG_CLIENT_TOKEN: ${{ secrets.DATADOG_CLIENT_TOKEN }} + DATADOG_SESSION_REPLAY_SAMPLE_RATE: ${{ vars.DATADOG_SESSION_REPLAY_SAMPLE_RATE }} + DATADOG_SESSION_SAMPLE_RATE: ${{ vars.DATADOG_SESSION_SAMPLE_RATE }} + REF_NAME: ${{ github.ref_name }} - name: Run tests for Eslint run: npm run test:lint diff --git a/package-lock.json b/package-lock.json index f26f5bca..999e1d48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "bot", "version": "0.0.1", "dependencies": { + "@datadog/browser-rum": "^5.31.1", "@deriv-com/analytics": "^1.5.3", "@deriv-com/quill-ui": "1.18.1", "@deriv-com/translations": "^1.3.9", @@ -2534,6 +2535,36 @@ "postcss-selector-parser": "^6.1.0" } }, + "node_modules/@datadog/browser-core": { + "version": "5.31.1", + "resolved": "https://registry.npmjs.org/@datadog/browser-core/-/browser-core-5.31.1.tgz", + "integrity": "sha512-mMbyyMeRfiaJ3CtXAPN1+gTZk9qCl9UfDO8Cr0dZGXCcBvZUyeSCocKYZcfnJkqF5/zv7n8/eBmkyzdsAcYaLg==" + }, + "node_modules/@datadog/browser-rum": { + "version": "5.31.1", + "resolved": "https://registry.npmjs.org/@datadog/browser-rum/-/browser-rum-5.31.1.tgz", + "integrity": "sha512-LXGkG1f8eggLh/wynbca9U9augELcle0/3HMpC2RbMWWtIZEYmj1S7fZmAm6lKz22OoheW4dnTdheyaZEXkY/g==", + "dependencies": { + "@datadog/browser-core": "5.31.1", + "@datadog/browser-rum-core": "5.31.1" + }, + "peerDependencies": { + "@datadog/browser-logs": "5.31.1" + }, + "peerDependenciesMeta": { + "@datadog/browser-logs": { + "optional": true + } + } + }, + "node_modules/@datadog/browser-rum-core": { + "version": "5.31.1", + "resolved": "https://registry.npmjs.org/@datadog/browser-rum-core/-/browser-rum-core-5.31.1.tgz", + "integrity": "sha512-IhKQ5KX8/YFRacZSYJz8WIMik+HzKb6japC4B5funnXDCFljX9bM/z1T1cXha73t5zwECJ49lY8hpouxHirwNA==", + "dependencies": { + "@datadog/browser-core": "5.31.1" + } + }, "node_modules/@deriv-com/analytics": { "version": "1.26.1", "resolved": "https://registry.npmjs.org/@deriv-com/analytics/-/analytics-1.26.1.tgz", diff --git a/package.json b/package.json index 24e508f2..4666430f 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "build:analyze": "BUNDLE_ANALYZE=true rsbuild build" }, "dependencies": { + "@datadog/browser-rum": "^5.31.1", "@deriv-com/analytics": "^1.5.3", "@deriv-com/quill-ui": "1.18.1", "@deriv-com/translations": "^1.3.9", diff --git a/src/app/app-content.jsx b/src/app/app-content.jsx index 8419e6bf..9730127d 100644 --- a/src/app/app-content.jsx +++ b/src/app/app-content.jsx @@ -24,7 +24,6 @@ import 'react-toastify/dist/ReactToastify.css'; import '../components/bot-notification/bot-notification.scss'; const AppContent = observer(() => { - const { initTrackJS } = useTrackjs(); const [is_api_initialized, setIsApiInitialized] = React.useState(false); const [is_loading, setIsLoading] = React.useState(true); const store = useStore(); @@ -36,7 +35,10 @@ const AppContent = observer(() => { const is_subscribed_to_msg_listener = React.useRef(false); const msg_listener = React.useRef(null); const { connectionStatus } = useApiBase(); + const { initTrackJS } = useTrackjs(); + console.log(client); + console.log('before initTrackJS'); initTrackJS(); useEffect(() => { diff --git a/src/utils/datadog.ts b/src/utils/datadog.ts new file mode 100644 index 00000000..c409ee49 --- /dev/null +++ b/src/utils/datadog.ts @@ -0,0 +1,74 @@ +import { datadogRum } from '@datadog/browser-rum'; + +/** + * Gets the configuration values for datadog based on the environment. + * It returns null if the environment is not staging or production. + * @param {string} environment - The environment to get the configuration values for. + * @example getConfigValues('staging'); + * @returns {object|null} - The configuration values for datadog. + * **/ +const getConfigValues = (environment: string) => { + if (environment === 'production') { + return { + serviceName: 'deriv-bot', + dataDogVersion: `deriv-bot-${process.env.REF_NAME}`, + dataDogSessionReplaySampleRate: Number(process.env.DATADOG_SESSION_REPLAY_SAMPLE_RATE ?? 1), + dataDogSessionSampleRate: Number(process.env.DATADOG_SESSION_SAMPLE_RATE ?? 10), + dataDogEnv: 'production', + }; + } else if (environment === 'staging') { + return { + serviceName: 'staging-dbot.deriv.com', + dataDogVersion: `deriv-dbot-staging-v${process.env.REF_NAME}`, + dataDogSessionReplaySampleRate: 0, + dataDogSessionSampleRate: 100, + dataDogEnv: 'staging', + }; + } +}; + +/** + * Initializes datadog for tracking user interactions, resources, long tasks, and frustrations on production or staging environments, conditionally based on environment variables. + * It also masks user input and redacts sensitive data from the URL. + * + * @param {boolean} is_datadog_enabled - The parameter to enable or disable datadog tracking. + * @example initDatadog(true); + * @returns {void} + * **/ +const initDatadog = (is_datadog_enabled: boolean) => { + if (!is_datadog_enabled) return; + const DATADOG_APP_ID = process.env.DATADOG_APPLICATION_ID ?? ''; + const DATADOG_CLIENT_TOKEN = process.env.DATADOG_CLIENT_TOKEN ?? ''; + const isProduction = process.env.NODE_ENV === 'production'; + const isStaging = process.env.NODE_ENV === 'staging'; + + const { + dataDogSessionSampleRate = 0, + dataDogSessionReplaySampleRate = 0, + dataDogVersion = '', + dataDogEnv = '', + serviceName = '', + } = getConfigValues(process.env.NODE_ENV ?? '') ?? {}; + + // we do it in order avoid error "application id is not configured, no RUM data will be collected" + // for test-links where application ID has not been configured and therefore RUM data will not be collected + if (isProduction || isStaging) { + datadogRum.init({ + applicationId: isStaging || isProduction ? DATADOG_APP_ID : '', + clientToken: isStaging || isProduction ? DATADOG_CLIENT_TOKEN : '', + site: 'datadoghq.com', + service: serviceName, + env: dataDogEnv, + sessionSampleRate: dataDogSessionSampleRate, + sessionReplaySampleRate: dataDogSessionReplaySampleRate, + trackUserInteractions: true, + trackResources: true, + trackLongTasks: true, + defaultPrivacyLevel: 'mask-user-input', + version: dataDogVersion, + enableExperimentalFeatures: ['clickmap'], + }); + } +}; + +export default initDatadog;