Improve Datadog Rum

This commit is contained in:
Arthur Belleville 2025-10-30 18:23:24 +01:00
parent 3afd9b338d
commit 8f37530005
No known key found for this signature in database
6 changed files with 45 additions and 77 deletions

View file

@ -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 = () => {
<SessionProvider supabase={supabase}>
<Toaster />
<Router>
<DatadogRumProvider>
<div className="min-h-screen bg-background">
<Routes />
<style>
{`
<div className="min-h-screen bg-background">
<Routes />
<style>
{`
@keyframes slide {
0% { transform: translateX(-100vw); }
100% { transform: translateX(100vw); }
@ -46,9 +47,8 @@ export const App = () => {
animation: slide 24s linear infinite;
}
`}
</style>
</div>
</DatadogRumProvider>
</style>
</div>
</Router>
</SessionProvider>
</ThemeProvider>

View file

@ -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;
};

View file

@ -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;

View file

@ -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";

View file

@ -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(
<BrowserRouter>
<DatadogRumProvider>
<div>Test Child</div>
</DatadogRumProvider>
</BrowserRouter>
);
expect(screen.getByText("Test Child")).toBeInTheDocument();
});
it("renders without crashing", () => {
const { container } = render(
<BrowserRouter>
<DatadogRumProvider>
<div>Content</div>
</DatadogRumProvider>
</BrowserRouter>
);
expect(container).toBeInTheDocument();
});
});

View file

@ -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 <LoadingSpinner />;
}