Skip to content

Commit 2c28e84

Browse files
authored
fix: fix datadog tracking and sync with the chatbot (#1388)
## Description ## Linear Ticket ## What type of PR is this? (check all applicable) - [ ] πŸ’‘ (feat) - A new feature (non-breaking change which adds functionality) - [ ] πŸ”„ (refactor) - Code Refactoring - A code change that neither fixes a bug nor adds a feature - [ ] 🐞 (fix) - Bug Fix (non-breaking change which fixes an issue) - [ ] 🏎 (perf) - Optimization - [ ] πŸ“„ (docs) - Documentation - Documentation only changes - [ ] πŸ“„ (test) - Tests - Adding missing tests or correcting existing tests - [ ] βš™οΈ (ci) - Continuous Integrations - Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs) - [ ] β˜‘οΈ (chore) - Chores - Other changes that don't modify src or test files - [ ] ↩️ (revert) - Reverts - Reverts a previous commit(s). <!-- For a timely review/response, please avoid force-pushing additional commits if your PR already received reviews or comments. Before submitting a Pull Request, please ensure you've done the following: - πŸ‘·β€β™€οΈ Create small PRs. In most cases this will be possible. - βœ… Provide tests for your changes. - πŸ“ Use descriptive commit messages (as described below). - πŸ“— Update any related documentation and include any relevant screenshots. Commit Message Structure (all lower-case): <type>(optional ticket number): <description> [optional body] -->
1 parent 21ba233 commit 2c28e84

26 files changed

+589
-493
lines changed

β€Ž.gitignoreβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ directory_contents.json
4848
.codex
4949
.claude
5050
.cursor
51+
.vscode/extensions.json
5152

5253
# MCPs
5354
.vscode/mcp.json

β€Ž.hintrcβ€Ž

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"development"
44
],
55
"hints": {
6-
"axe/forms": "off"
6+
"axe/forms": "off",
7+
"typescript-config/consistent-casing": "off"
78
}
89
}

β€Ž.vscode/settings.jsonβ€Ž

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
{
2+
"eslint.enable": true,
3+
"eslint.validate": [
4+
"javascript",
5+
"javascriptreact",
6+
"typescript",
7+
"typescriptreact",
8+
"html"
9+
],
10+
"eslint.workingDirectories": [
11+
{
12+
"mode": "auto"
13+
}
14+
],
215
"eslint.format.enable": true,
3-
"editor.formatOnSave": false,
416
"editor.codeActionsOnSave": {
517
"source.fixAll.eslint": "always"
618
},
7-
"eslint.validate": ["typescriptreact"],
8-
"editor.insertSpaces": false,
9-
"chat.agent.enabled": true,
10-
"chat.tools.autoApprove": true
11-
}
19+
"editor.formatOnSave": true
20+
}

β€Žpackage-lock.jsonβ€Ž

Lines changed: 25 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

β€Žpackage.jsonβ€Ž

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@
3636
},
3737
"dependencies": {
3838
"@bufbuild/protobuf": "^1.10.0",
39-
"@datadog/browser-rum": "^6.21.1",
40-
"@datadog/browser-rum-react": "^6.21.1",
39+
"@datadog/browser-rum": "^6.22.0",
40+
"@datadog/browser-rum-react": "^6.22.0",
4141
"@descope/react-sdk": "^2.16.1",
4242
"@estruyf/github-actions-reporter": "^1.9.2",
4343
"@floating-ui/react": "^0.27.2",

β€Žsrc/app.tsxβ€Ž

Lines changed: 5 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,10 @@
11
import React, { useEffect, useState } from "react";
22

3-
import * as Sentry from "@sentry/react";
43
import ga4 from "react-ga4";
54
import { useTranslation } from "react-i18next";
6-
import {
7-
Navigate,
8-
Route,
9-
createRoutesFromChildren,
10-
matchRoutes,
11-
useLocation,
12-
useNavigationType,
13-
useParams,
14-
} from "react-router-dom";
15-
16-
import { AKRoutes, googleAnalyticsId, isProduction, sentryDsn } from "@constants";
5+
import { Navigate, Route, Routes, useLocation, useParams } from "react-router-dom";
6+
7+
import { googleAnalyticsId, isProduction } from "@constants";
178
import { MemberRole } from "@enums";
189
import { useHubspot } from "@src/hooks";
1910
import { getPageTitleFromPath } from "@utilities";
@@ -111,40 +102,10 @@ export const App = () => {
111102
// eslint-disable-next-line react-hooks/exhaustive-deps
112103
}, [location.pathname, user, organization, params, pageTitleKey, activeFileName, extractedProjectName]);
113104

114-
if (isProduction) {
115-
Sentry.init({
116-
dsn: sentryDsn,
117-
integrations: [
118-
// See docs for support of different versions of variation of react router
119-
// https://docs.sentry.io/platforms/javascript/guides/react/configuration/integrations/react-router/
120-
Sentry.reactRouterV7BrowserTracingIntegration({
121-
useEffect,
122-
useLocation,
123-
useNavigationType,
124-
createRoutesFromChildren,
125-
matchRoutes,
126-
}),
127-
Sentry.feedbackIntegration({
128-
colorScheme: "system",
129-
autoInject: false,
130-
}),
131-
],
132-
// Set tracesSampleRate to 1.0 to capture 100%
133-
// of transactions for tracing.
134-
tracesSampleRate: 1.0,
135-
// Set `tracePropagationTargets` to control for which URLs trace propagation should be enabled
136-
tracePropagationTargets: [
137-
"localhost",
138-
/^https:\/\/[\w.-]+\.autokitteh\.cloud/,
139-
/^https:\/\/autokitteh\.cloud/,
140-
],
141-
});
142-
}
143-
144105
return (
145106
<>
146107
<PageTitle title={pageTitle} />
147-
<AKRoutes>
108+
<Routes>
148109
<Route element={<AppLayout hideTopbar />} path="/">
149110
<Route element={<Dashboard />} index />
150111
<Route element={<CreateNewProject />} path="ai" />
@@ -336,7 +297,7 @@ export const App = () => {
336297
<Route element={<AppLayout hideTopbar />} path="error">
337298
<Route element={<CustomError />} index />
338299
</Route>
339-
</AKRoutes>
300+
</Routes>
340301
</>
341302
);
342303
};

β€Žsrc/components/organisms/chatbotIframe/chatbotIframe.tsxβ€Ž

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import React, { useEffect, useState, useRef, useCallback, useMemo, RefObject } f
33

44
import { TFunction } from "i18next";
55
import { useTranslation } from "react-i18next";
6-
import { useNavigate, useLocation } from "react-router-dom";
6+
import { useNavigate } from "react-router-dom";
77

88
import { ChatbotLoadingStates } from "./chatbotLoadingStates";
99
import { ChatbotToolbar } from "./chatbotToolbar";
@@ -18,9 +18,11 @@ import { MessageTypes } from "@src/types/iframeCommunication.type";
1818
import {
1919
cn,
2020
compareUrlParams,
21+
CorrelationIdUtils,
2122
isNavigateToProjectMessage,
2223
isNavigateToConnectionMessage,
2324
isVarUpdatedMessage,
25+
isE2E,
2426
} from "@src/utilities";
2527
import { useCacheStore } from "@store/cache/useCacheStore";
2628

@@ -64,14 +66,12 @@ export const ChatbotIframe = ({
6466
const { t } = useTranslation("chatbot");
6567
const iframeRef = useRef<HTMLIFrameElement | null>(null);
6668
const navigate = useNavigate();
67-
const location = useLocation();
6869
const { getProjectsList } = useProjectStore();
6970

7071
const addToast = useToastStore((state) => state.addToast);
71-
const currentOrganization = useOrganizationStore((state) => state.currentOrganization);
72-
const setExpandedProjectNavigation = useSharedBetweenProjectsStore((state) => state.setExpandedProjectNavigation);
73-
const selectionPerProject = useSharedBetweenProjectsStore((state) => state.selectionPerProject);
74-
const chatbotHelperConfigMode = useSharedBetweenProjectsStore((state) => state.chatbotHelperConfigMode);
72+
const { currentOrganization, user } = useOrganizationStore();
73+
const { setExpandedProjectNavigation, selectionPerProject, chatbotHelperConfigMode } =
74+
useSharedBetweenProjectsStore();
7575
const [retryToastDisplayed, setRetryToastDisplayed] = useState(false);
7676
const [chatbotUrlWithOrgId, setChatbotUrlWithOrgId] = useState("");
7777

@@ -85,6 +85,12 @@ export const ChatbotIframe = ({
8585
if (descopeProjectId && !currentOrganization?.id && !isDevelopment) return "";
8686

8787
const params = new URLSearchParams();
88+
89+
const akCorrelationId = CorrelationIdUtils.get();
90+
if (akCorrelationId) {
91+
params.append("ak-correlation-id", akCorrelationId);
92+
}
93+
8894
if (currentOrganization?.id) {
8995
params.append("org-id", currentOrganization.id);
9096
}
@@ -98,9 +104,13 @@ export const ChatbotIframe = ({
98104
if (displayDeployButton) {
99105
params.append("display-deploy-button", displayDeployButton ? "true" : "false");
100106
}
107+
if (isE2E()) {
108+
params.append("e2e", "true");
109+
}
101110
params.append("_cb", cacheBuster);
111+
102112
return `${aiChatbotUrl}?${params.toString()}`;
103-
}, [currentOrganization?.id, currentProjectConfigMode, projectId, displayDeployButton, isTransparent, cacheBuster]);
113+
}, [currentOrganization, currentProjectConfigMode, projectId, displayDeployButton, isTransparent, cacheBuster]);
104114

105115
useEffect(() => {
106116
if (!computedChatbotUrl || computedChatbotUrl === chatbotUrlWithOrgId) return;
@@ -126,6 +136,12 @@ export const ChatbotIframe = ({
126136

127137
const handleConnectionCallback = useCallback(() => {
128138
onConnect?.();
139+
140+
iframeCommService.sendDatadogContext({
141+
currentOrganization,
142+
user,
143+
});
144+
129145
if (projectId && selectionPerProject[projectId]) {
130146
const selectionData = selectionPerProject[projectId];
131147

@@ -136,7 +152,7 @@ export const ChatbotIframe = ({
136152
});
137153
});
138154
}
139-
}, [onConnect, projectId, selectionPerProject]);
155+
}, [onConnect, projectId, selectionPerProject, currentOrganization, user]);
140156

141157
const { isLoading, loadError, isIframeLoaded, handleIframeElementLoad, handleRetry, isRetryLoading } =
142158
useChatbotIframeConnection(iframeRef, handleConnectionCallback, chatbotUrlWithOrgId);
@@ -229,13 +245,6 @@ export const ChatbotIframe = ({
229245

230246
useEventListener(EventListenerName.iframeError, handleIframeError);
231247

232-
useEffect(() => {
233-
if (iframeCommService.isConnectedToIframe) {
234-
iframeCommService.sendDatadogContext();
235-
}
236-
}, [location.pathname, location.search, location.hash]);
237-
238-
// Memoized computed values for performance
239248
const frameTitle = useMemo(() => {
240249
return projectId && chatbotHelperConfigMode[projectId] ? t("titles.projectStatus") : t("titles.aiAssistant");
241250
}, [projectId, chatbotHelperConfigMode, t]);
@@ -271,7 +280,6 @@ export const ChatbotIframe = ({
271280
<iframe
272281
className={className}
273282
height={height}
274-
key={chatbotUrlWithOrgId}
275283
onLoad={handleIframeElementLoad}
276284
ref={iframeRef}
277285
sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-storage-access-by-user-activation"

β€Žsrc/components/templates/descopeWrapper.tsxβ€Ž

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
import React from "react";
22

33
import { AuthProvider } from "@descope/react-sdk";
4-
import { useSearchParams } from "react-router-dom";
54

6-
import { descopeProjectId, isProduction } from "@constants";
5+
import { descopeProjectId } from "@constants";
76
import { useUserTracking } from "@hooks/useUserTracking";
87

98
import { DescopeMiddleware } from "@components/templates";
109

1110
export const DescopeWrapper = ({ children }: { children: React.ReactNode }) => {
12-
const [searchParams] = useSearchParams();
13-
const userAgent = navigator.userAgent.toLowerCase();
14-
const hasHeadless = userAgent.includes("headless");
15-
const isE2eTest = searchParams.get("e2e") === "true" || hasHeadless;
16-
useUserTracking(isProduction, isE2eTest);
11+
useUserTracking();
1712

1813
return (
1914
<AuthProvider projectId={descopeProjectId}>

β€Žsrc/constants/datadog.constants.tsβ€Ž

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import type { MatchOption, Site } from "@datadog/browser-core";
2-
import type { PropagatorType, TracingOption } from "@datadog/browser-rum";
1+
import type { Site } from "@datadog/browser-core";
2+
import type { MatchOption, TracingOption } from "@datadog/browser-rum";
33

44
import { isProduction } from "@constants/global.constants";
55
import { VersionService } from "@src/services/version.service";
@@ -15,11 +15,16 @@ const sessionSampleRate = isProduction ? 100 : 100;
1515
const sessionReplaySampleRate = isProduction ? 100 : 100;
1616

1717
const allowedTracingUrls = [
18-
{ match: /^https?:\/\/localhost:\d+\//, propagatorTypes: ["datadog" as PropagatorType] },
19-
{ match: /^https?:\/\/[^/]*\.autokitteh\.cloud\//, propagatorTypes: ["datadog" as PropagatorType] },
20-
] as Array<MatchOption | TracingOption> | undefined;
18+
{ match: "https://staging.autokitteh.cloud", propagatorTypes: ["tracecontext", "datadog"] },
19+
{ match: "https://staging-api.autokitteh.cloud", propagatorTypes: ["tracecontext", "datadog"] },
20+
{ match: "https://app.autokitteh.cloud", propagatorTypes: ["tracecontext", "datadog"] },
21+
{ match: "https://api.autokitteh.cloud", propagatorTypes: ["tracecontext", "datadog"] },
22+
{ match: "http://localhost:9980", propagatorTypes: ["tracecontext", "datadog"] },
23+
{ match: "http://localhost:3000", propagatorTypes: ["tracecontext", "datadog"] },
24+
{ match: "http://localhost:8000", propagatorTypes: ["tracecontext", "datadog"] },
25+
] as Array<MatchOption | TracingOption>;
2126

22-
const defaultPrivacyLevel = "allow";
27+
const defaultPrivacyLevel = "allow" as const;
2328

2429
export const datadogConstants = {
2530
applicationId,

0 commit comments

Comments
Β (0)