From 8f37530005a533574728cd0210894c6db4db58bf Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Thu, 30 Oct 2025 18:23:24 +0100 Subject: [PATCH] Improve Datadog Rum --- apps/main/src/App.tsx | 18 ++++---- .../useDatadogRumViewName.tsx} | 7 +-- apps/main/src/lib/rum.ts | 34 +++++++------- apps/main/src/main.tsx | 2 + .../src/providers/DatadogRumProvider.test.tsx | 44 ------------------- apps/main/src/providers/UserStoreProvider.tsx | 17 ++++++- 6 files changed, 45 insertions(+), 77 deletions(-) rename apps/main/src/{providers/DatadogRumProvider.tsx => hooks/useDatadogRumViewName.tsx} (84%) delete mode 100644 apps/main/src/providers/DatadogRumProvider.test.tsx diff --git a/apps/main/src/App.tsx b/apps/main/src/App.tsx index 349f443..929d533 100644 --- a/apps/main/src/App.tsx +++ b/apps/main/src/App.tsx @@ -6,10 +6,12 @@ import { publicRoutes } from "./lib/publicRoutes"; import { routes } from "./lib/routes"; import { supabase } from "./lib/supabase"; import { NotFoundPage } from "./pages/NotFoundPage"; -import { DatadogRumProvider } from "./providers/DatadogRumProvider"; import { UserStoreProvider } from "./providers/UserStoreProvider"; +import { useDatadogRumViewName } from "./hooks/useDatadogRumViewName"; + const Routes = () => { + useDatadogRumViewName(); const publicElement = useRoutes(publicRoutes); const appElement = useRoutes(routes); @@ -33,11 +35,10 @@ export const App = () => { - -
- - -
-
+ +
diff --git a/apps/main/src/providers/DatadogRumProvider.tsx b/apps/main/src/hooks/useDatadogRumViewName.tsx similarity index 84% rename from apps/main/src/providers/DatadogRumProvider.tsx rename to apps/main/src/hooks/useDatadogRumViewName.tsx index be3a1d1..2e846b8 100644 --- a/apps/main/src/providers/DatadogRumProvider.tsx +++ b/apps/main/src/hooks/useDatadogRumViewName.tsx @@ -2,7 +2,6 @@ import { datadogRum } from "@datadog/browser-rum"; import { useEffect } from "react"; import { matchRoutes, RouteMatch, useLocation } from "react-router-dom"; import { routes } from "../lib/routes"; -import { initRum } from "../lib/rum"; function computeViewName(routeMatches: RouteMatch[]) { let viewName = ""; @@ -26,11 +25,8 @@ function computeViewName(routeMatches: RouteMatch[]) { return viewName || "/"; } -export const DatadogRumProvider = ({ children }: { children: React.ReactNode }) => { +export const useDatadogRumViewName = () => { const location = useLocation(); - useEffect(() => { - initRum(); - }, []); useEffect(() => { const routeMatches = matchRoutes(routes, location.pathname); @@ -39,5 +35,4 @@ export const DatadogRumProvider = ({ children }: { children: React.ReactNode }) datadogRum.startView({ name: viewName }); } }, [location.pathname]); - return children; }; diff --git a/apps/main/src/lib/rum.ts b/apps/main/src/lib/rum.ts index 34e568c..7ade6a5 100644 --- a/apps/main/src/lib/rum.ts +++ b/apps/main/src/lib/rum.ts @@ -1,21 +1,21 @@ import { datadogRum } from "@datadog/browser-rum"; import { reactPlugin } from "@datadog/browser-rum-react"; -export const initRum = () => { - datadogRum.init({ - applicationId: "8e268e1a-1be0-44c6-b12a-978530d497c7", - clientToken: "pub1761af09ab04e215cc90d34da6ac576b", - site: "datadoghq.com", - service: "xtablo-ui", - env: import.meta.env.MODE, +datadogRum.init({ + applicationId: "8e268e1a-1be0-44c6-b12a-978530d497c7", + clientToken: "pub1761af09ab04e215cc90d34da6ac576b", + site: "datadoghq.com", + service: "xtablo-ui", + env: import.meta.env.MODE, - // Specify a version number to identify the deployed version of your application in Datadog - // version: '1.0.0', - sessionSampleRate: 100, - sessionReplaySampleRate: 80, - defaultPrivacyLevel: "mask-user-input", - plugins: [reactPlugin({ router: true })], - trackViewsManually: true, - startSessionReplayRecordingManually: false, - }); -}; + // Specify a version number to identify the deployed version of your application in Datadog + // version: '1.0.0', + sessionSampleRate: 100, + sessionReplaySampleRate: 80, + defaultPrivacyLevel: "mask-user-input", + plugins: [reactPlugin({ router: true })], + trackViewsManually: true, + startSessionReplayRecordingManually: false, +}); + +export default datadogRum; diff --git a/apps/main/src/main.tsx b/apps/main/src/main.tsx index 63d88b8..afc3b6f 100644 --- a/apps/main/src/main.tsx +++ b/apps/main/src/main.tsx @@ -4,6 +4,8 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import { App } from "./App"; +import "./lib/rum"; + import "./i18n"; import "stream-chat-react/dist/css/v2/index.css"; import "@xtablo/ui/styles/globals.css"; diff --git a/apps/main/src/providers/DatadogRumProvider.test.tsx b/apps/main/src/providers/DatadogRumProvider.test.tsx deleted file mode 100644 index 9471a24..0000000 --- a/apps/main/src/providers/DatadogRumProvider.test.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { render, screen } from "@testing-library/react"; -import { BrowserRouter } from "react-router-dom"; -import { describe, expect, it, vi } from "vitest"; -import { DatadogRumProvider } from "./DatadogRumProvider"; - -// Mock Datadog RUM -vi.mock("@datadog/browser-rum-react", () => ({ - DdRumReactIntegration: vi.fn(), -})); - -vi.mock("@datadog/browser-rum", () => ({ - datadogRum: { - init: vi.fn(), - startView: vi.fn(), - }, -})); - -vi.mock("../lib/rum", () => ({ - initRum: vi.fn(), -})); - -describe("DatadogRumProvider", () => { - it("renders children", () => { - render( - - -
Test Child
-
-
- ); - expect(screen.getByText("Test Child")).toBeInTheDocument(); - }); - - it("renders without crashing", () => { - const { container } = render( - - -
Content
-
-
- ); - expect(container).toBeInTheDocument(); - }); -}); diff --git a/apps/main/src/providers/UserStoreProvider.tsx b/apps/main/src/providers/UserStoreProvider.tsx index 7a16544..8e68824 100644 --- a/apps/main/src/providers/UserStoreProvider.tsx +++ b/apps/main/src/providers/UserStoreProvider.tsx @@ -1,10 +1,11 @@ import { useQuery } from "@tanstack/react-query"; import { useSession } from "@xtablo/shared/contexts/SessionContext"; import { Tables } from "@xtablo/shared/types/database.types"; -import React from "react"; +import React, { useEffect } from "react"; import { createStore, StoreApi, useStore } from "zustand"; import { LoadingSpinner } from "../components/LoadingSpinner"; import { api } from "../lib/api"; +import datadogRum from "../lib/rum"; export type User = Tables<"profiles"> & { streamToken: string | null; @@ -33,6 +34,20 @@ export const UserStoreProvider = ({ children }: { children: React.ReactNode }) = enabled: shouldFetchUser, }); + useEffect(() => { + if (user) { + datadogRum.setUser({ + id: user.id, + email: user.email ?? undefined, + name: + user.first_name && user.last_name ? `${user.first_name} ${user.last_name}` : undefined, + isReadOnly: user.is_temporary, + }); + } else { + datadogRum.clearUser(); + } + }, [user]); + if (isPending && shouldFetchUser) { return ; }