diff --git a/airbyte-webapp/package-lock.json b/airbyte-webapp/package-lock.json index 3e520af63247..12dbb3e0b9ac 100644 --- a/airbyte-webapp/package-lock.json +++ b/airbyte-webapp/package-lock.json @@ -8,6 +8,7 @@ "name": "airbyte-webapp", "version": "0.40.14", "dependencies": { + "@datadog/browser-rum": "^4.21.2", "@floating-ui/react-dom": "^1.0.0", "@fortawesome/fontawesome-svg-core": "^6.1.1", "@fortawesome/free-brands-svg-icons": "^6.1.1", @@ -2498,6 +2499,36 @@ "integrity": "sha512-M0qqxAcwCsIVfpFQSlGN5XjXWu8l5JDZN+fPt1LeW5SZexQTgnaEvgXAY+CeygRw0EeppWHi12JxESWiWrB0Sg==", "dev": true }, + "node_modules/@datadog/browser-core": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@datadog/browser-core/-/browser-core-4.21.2.tgz", + "integrity": "sha512-o3UvCPBF0OdCInCbiC9j79K0F7/wThARZFq8+wnAOitZu64VT5XNpHFQqFP+9c+zzcxmwlTIINHmWLdkpKEECg==" + }, + "node_modules/@datadog/browser-rum": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@datadog/browser-rum/-/browser-rum-4.21.2.tgz", + "integrity": "sha512-qvC7sRrZ5yy7siCHeGPnBsM6sKoU+jc1YGy/5WgRSs24WUt9trgBoRcVR1KwU/aK8xn6hUOKRdEIxkrss5JaiA==", + "dependencies": { + "@datadog/browser-core": "4.21.2", + "@datadog/browser-rum-core": "4.21.2" + }, + "peerDependencies": { + "@datadog/browser-logs": "4.21.2" + }, + "peerDependenciesMeta": { + "@datadog/browser-logs": { + "optional": true + } + } + }, + "node_modules/@datadog/browser-rum-core": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@datadog/browser-rum-core/-/browser-rum-core-4.21.2.tgz", + "integrity": "sha512-8hNiNygHY8Jt2APtm4nvciGyRKIEniaupe7Uj5Bq6OFZIFNgf6qj88bRXwOdPsP9ksBNNK18Hol1oI4EdxdkkQ==", + "dependencies": { + "@datadog/browser-core": "4.21.2" + } + }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -49338,6 +49369,28 @@ "integrity": "sha512-M0qqxAcwCsIVfpFQSlGN5XjXWu8l5JDZN+fPt1LeW5SZexQTgnaEvgXAY+CeygRw0EeppWHi12JxESWiWrB0Sg==", "dev": true }, + "@datadog/browser-core": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@datadog/browser-core/-/browser-core-4.21.2.tgz", + "integrity": "sha512-o3UvCPBF0OdCInCbiC9j79K0F7/wThARZFq8+wnAOitZu64VT5XNpHFQqFP+9c+zzcxmwlTIINHmWLdkpKEECg==" + }, + "@datadog/browser-rum": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@datadog/browser-rum/-/browser-rum-4.21.2.tgz", + "integrity": "sha512-qvC7sRrZ5yy7siCHeGPnBsM6sKoU+jc1YGy/5WgRSs24WUt9trgBoRcVR1KwU/aK8xn6hUOKRdEIxkrss5JaiA==", + "requires": { + "@datadog/browser-core": "4.21.2", + "@datadog/browser-rum-core": "4.21.2" + } + }, + "@datadog/browser-rum-core": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/@datadog/browser-rum-core/-/browser-rum-core-4.21.2.tgz", + "integrity": "sha512-8hNiNygHY8Jt2APtm4nvciGyRKIEniaupe7Uj5Bq6OFZIFNgf6qj88bRXwOdPsP9ksBNNK18Hol1oI4EdxdkkQ==", + "requires": { + "@datadog/browser-core": "4.21.2" + } + }, "@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", diff --git a/airbyte-webapp/package.json b/airbyte-webapp/package.json index 7354e7bc034e..a6fa2a1a9db4 100644 --- a/airbyte-webapp/package.json +++ b/airbyte-webapp/package.json @@ -24,6 +24,7 @@ "validate-links": "ts-node --skip-project ./scripts/validate-links.ts" }, "dependencies": { + "@datadog/browser-rum": "^4.21.2", "@floating-ui/react-dom": "^1.0.0", "@fortawesome/fontawesome-svg-core": "^6.1.1", "@fortawesome/free-brands-svg-icons": "^6.1.1", @@ -162,7 +163,9 @@ }, "jest": { "transformIgnorePatterns": [], - "snapshotSerializers": ["./scripts/classname-serializer.js"], + "snapshotSerializers": [ + "./scripts/classname-serializer.js" + ], "coveragePathIgnorePatterns": [ ".stories.tsx" ] diff --git a/airbyte-webapp/src/config/types.ts b/airbyte-webapp/src/config/types.ts index 92265730edb8..ad818fd46446 100644 --- a/airbyte-webapp/src/config/types.ts +++ b/airbyte-webapp/src/config/types.ts @@ -4,6 +4,10 @@ declare global { AIRBYTE_VERSION?: string; API_URL?: string; CLOUD?: string; + REACT_APP_DATADOG_APPLICATION_ID: string; + REACT_APP_DATADOG_CLIENT_TOKEN: string; + REACT_APP_DATADOG_SITE: string; + REACT_APP_DATADOG_SERVICE: string; REACT_APP_SENTRY_DSN?: string; REACT_APP_WEBAPP_TAG?: string; REACT_APP_INTERCOM_APP_ID?: string; diff --git a/airbyte-webapp/src/index.tsx b/airbyte-webapp/src/index.tsx index 84e3678e5f54..751cd8a448c4 100644 --- a/airbyte-webapp/src/index.tsx +++ b/airbyte-webapp/src/index.tsx @@ -1,21 +1,17 @@ -import * as Sentry from "@sentry/react"; -import { Integrations } from "@sentry/tracing"; import { lazy, Suspense } from "react"; import ReactDOM from "react-dom"; import "react-reflex/styles.css"; import { isCloudApp } from "utils/app"; +import { loadDatadog } from "utils/datadog"; import { loadOsano } from "utils/dataPrivacy"; +import { loadSentry } from "utils/sentry"; import "./globals"; -// We do not follow default config approach since we want to init sentry asap -Sentry.init({ - dsn: process.env.REACT_APP_SENTRY_DSN || window.REACT_APP_SENTRY_DSN, - release: process.env.REACT_APP_WEBAPP_TAG || window.REACT_APP_WEBAPP_TAG || "dev", - integrations: [new Integrations.BrowserTracing()], - tracesSampleRate: 1.0, // may need to adjust this in the future -}); +// We do not follow default config approach since we want to init sentry/datadog asap +loadSentry(); +loadDatadog(); // In Cloud load the Osano script (GDPR consent tool before anything else) if (isCloudApp()) { diff --git a/airbyte-webapp/src/utils/datadog.ts b/airbyte-webapp/src/utils/datadog.ts new file mode 100644 index 000000000000..4fa03ed73500 --- /dev/null +++ b/airbyte-webapp/src/utils/datadog.ts @@ -0,0 +1,28 @@ +import { datadogRum } from "@datadog/browser-rum"; +export const loadDatadog = (): void => { + const applicationId = window.REACT_APP_DATADOG_APPLICATION_ID ?? process.env.REACT_APP_DATADOG_APPLICATION_ID; + if (!applicationId) { + return; + } + + const clientToken = window.REACT_APP_DATADOG_CLIENT_TOKEN ?? process.env.REACT_APP_DATADOG_CLIENT_TOKEN; + const site = window.REACT_APP_DATADOG_SITE ?? process.env.REACT_APP_DATADOG_SITE; + const service = window.REACT_APP_DATADOG_SERVICE ?? process.env.REACT_APP_DATADOG_SERVICE; + const version = window.REACT_APP_WEBAPP_TAG ?? process.env.REACT_APP_WEBAPP_TAG ?? "dev"; + + datadogRum.init({ + applicationId, + clientToken, + site, + service, + version, + sampleRate: 100, + sessionReplaySampleRate: 0, + trackInteractions: false, + trackResources: true, + trackLongTasks: true, + defaultPrivacyLevel: "mask-user-input", + }); + + datadogRum.startSessionReplayRecording(); +}; diff --git a/airbyte-webapp/src/utils/sentry.ts b/airbyte-webapp/src/utils/sentry.ts new file mode 100644 index 000000000000..d8f63339f019 --- /dev/null +++ b/airbyte-webapp/src/utils/sentry.ts @@ -0,0 +1,19 @@ +import * as Sentry from "@sentry/react"; +import { Integrations } from "@sentry/tracing"; + +export const loadSentry = (): void => { + const dsn = window.REACT_APP_SENTRY_DSN ?? process.env.REACT_APP_SENTRY_DSN; + if (!dsn) { + return; + } + + const release = window.REACT_APP_WEBAPP_TAG ?? process.env.REACT_APP_WEBAPP_TAG ?? "dev"; + const integrations = [new Integrations.BrowserTracing()]; + + Sentry.init({ + dsn, + release, + integrations, + tracesSampleRate: 1.0, + }); +};