Skip to content

Commit c8bd41b

Browse files
committed
fix: Translate the urls for Datadog
https://harperdb.atlassian.net/browse/STUDIO-381
1 parent 5a94ec5 commit c8bd41b

File tree

3 files changed

+93
-5
lines changed

3 files changed

+93
-5
lines changed

src/integrations/datadog/datadog.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { isLocalStudio } from '@/config/constants';
22
import { useOverallAuth } from '@/hooks/useAuth';
3+
import { translateUrlForDatadog } from '@/integrations/datadog/translateUrlForDatadog';
34
import { excludeFalsy } from '@/lib/arrays/excludeFalsy';
45
import { isLocalUser } from '@/lib/types/isLocalUser';
5-
import { currentUrlAfterHash } from '@/lib/urls/currentUrlAfterHash';
66
import { datadogRum } from '@datadog/browser-rum';
77
import { reactPlugin } from '@datadog/browser-rum-react';
8-
import { useLocation } from '@tanstack/react-router';
9-
import { useEffect } from 'react';
8+
import { useLocation, useParams } from '@tanstack/react-router';
9+
import { useEffect, useMemo } from 'react';
1010

1111
let initialized = false;
1212
const enabled = !import.meta.env.DEV && !isLocalStudio;
@@ -42,6 +42,8 @@ export function useDatadog() {
4242
export function useOnRouteLoadTracker() {
4343
const location = useLocation();
4444
const { user } = useOverallAuth();
45+
const params = useParams({ strict: false });
46+
const name = useMemo(() => translateUrlForDatadog(location.href, params), [location.href, params]);
4547

4648
useEffect(() => {
4749
if (!enabled) {
@@ -50,9 +52,9 @@ export function useOnRouteLoadTracker() {
5052
datadogRum.startView({
5153
service: 'studio',
5254
version: import.meta.env.VITE_STUDIO_VERSION,
53-
name: currentUrlAfterHash(),
55+
name,
5456
});
55-
}, [location.href]);
57+
}, [name]);
5658

5759
useEffect(() => {
5860
if (!enabled) {
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { describe, expect, it } from 'vitest';
2+
import { translateUrlForDatadog } from './translateUrlForDatadog';
3+
4+
describe('translateUrlForDatadog', () => {
5+
it('removes query string parameters and ensures trailing slash', () => {
6+
const href = '/orgs/acme/clu-123/browse/data/Users?like=this&and=that';
7+
const params = {
8+
organizationId: 'acme',
9+
clusterId: 'clu-123',
10+
databaseName: 'data',
11+
tableName: 'Users',
12+
};
13+
const result = translateUrlForDatadog(href, params);
14+
expect(result).toBe('/orgs/$organizationId/$clusterId/browse/$databaseName/$tableName/');
15+
});
16+
17+
it('adds a trailing slash if missing', () => {
18+
const href = '/orgs/acme/';
19+
const result = translateUrlForDatadog(href, {});
20+
expect(result).toBe('/orgs/acme/');
21+
22+
const href2 = '/orgs/acme';
23+
const result2 = translateUrlForDatadog(href2, {});
24+
expect(result2).toBe('/orgs/acme/');
25+
});
26+
27+
it('replaces multiple parameters in the path', () => {
28+
const href = '/orgs/org-1/clu-2/instances/ins-3/';
29+
const params = {
30+
organizationId: 'org-1',
31+
clusterId: 'clu-2',
32+
instanceId: 'ins-3',
33+
};
34+
const result = translateUrlForDatadog(href, params);
35+
expect(result).toBe('/orgs/$organizationId/$clusterId/instances/$instanceId/');
36+
});
37+
38+
it('does not replace when param value not present', () => {
39+
const href = '/orgs/org-1/other/';
40+
const params = {
41+
organizationId: 'org-2',
42+
};
43+
const result = translateUrlForDatadog(href, params);
44+
expect(result).toBe('/orgs/org-1/other/');
45+
});
46+
47+
it('only replaces whole path segments bounded by slashes', () => {
48+
const href = '/files/my-org-1-file/';
49+
const params = {
50+
organizationId: 'org-1',
51+
};
52+
const result = translateUrlForDatadog(href, params);
53+
expect(result).toBe('/files/my-org-1-file/');
54+
});
55+
56+
it('handles URL without trailing slash but parameters at end', () => {
57+
const href = '/dbs/data/tables/Users';
58+
const params = {
59+
databaseName: 'data',
60+
tableName: 'Users',
61+
};
62+
const result = translateUrlForDatadog(href, params);
63+
expect(result).toBe('/dbs/$databaseName/tables/$tableName/');
64+
});
65+
66+
it('works with hash fragments and query strings in full href', () => {
67+
const href = 'https://example.com/app#/orgs/org-1/clu-2?x=1&y=2';
68+
const params = {
69+
organizationId: 'org-1',
70+
clusterId: 'clu-2',
71+
};
72+
// The function simply splits on '?', so the query is dropped; the rest remains intact, including protocol and host.
73+
const result = translateUrlForDatadog(href, params);
74+
expect(result).toBe('https://example.com/app#/orgs/$organizationId/$clusterId/');
75+
});
76+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export function translateUrlForDatadog(href: string, params: Record<string, string>): string {
2+
let translated = href.split('?')[0];
3+
if (!translated.endsWith('/')) {
4+
translated = translated + '/';
5+
}
6+
for (const key in params) {
7+
translated = translated.replace(`/${params[key]}/`, `/$${key}/`);
8+
}
9+
return translated;
10+
}

0 commit comments

Comments
 (0)