Skip to content

Commit 4065210

Browse files
authored
fix(apm): Set the transaction name for JavaScript transactions before they are flushed (#18822)
1 parent cd0a2a8 commit 4065210

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

src/sentry/static/sentry/app/bootstrap.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import ConfigStore from 'app/stores/configStore';
2626
import Main from 'app/main';
2727
import ajaxCsrfSetup from 'app/utils/ajaxCsrfSetup';
2828
import plugins from 'app/plugins';
29+
import routes from 'app/routes';
30+
import {normalizeTransactionName} from 'app/utils/apm';
2931

3032
function getSentryIntegrations(hasReplays: boolean = false) {
3133
const integrations = [
@@ -74,11 +76,16 @@ const tracesSampleRate = config ? config.apmSampling : 0;
7476
const hasReplays =
7577
window.__SENTRY__USER && window.__SENTRY__USER.isStaff && !!process.env.DISABLE_RR_WEB;
7678

79+
const appRoutes = Router.createRoutes(routes());
80+
7781
Sentry.init({
7882
...window.__SENTRY__OPTIONS,
7983
integrations: getSentryIntegrations(hasReplays),
8084
tracesSampleRate,
8185
_experiments: {useEnvelope: true},
86+
async beforeSend(event) {
87+
return normalizeTransactionName(appRoutes, event);
88+
},
8289
});
8390

8491
if (window.__SENTRY__USER) {

src/sentry/static/sentry/app/utils/apm.tsx

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
import * as Sentry from '@sentry/browser';
2+
import * as Router from 'react-router';
3+
import {createMemoryHistory} from 'history';
4+
import set from 'lodash/set';
5+
6+
import getRouteStringFromRoutes from 'app/utils/getRouteStringFromRoutes';
7+
8+
const createLocation = createMemoryHistory().createLocation;
29

310
/**
411
* Sets the transaction name
@@ -9,3 +16,61 @@ export function setTransactionName(name: string) {
916
scope.setTag('ui.route', name);
1017
});
1118
}
19+
20+
export async function normalizeTransactionName(
21+
appRoutes: Router.PlainRoute[],
22+
event: Sentry.Event
23+
): Promise<Sentry.Event> {
24+
if (event.type !== 'transaction') {
25+
return event;
26+
}
27+
28+
// For JavaScript transactions, translate the transaction name if it exists and doesn't start with /
29+
// using the app's react-router routes. If the transaction name doesn't exist, use the window.location.pathname
30+
// as the fallback.
31+
32+
let prevTransactionName = event.transaction;
33+
34+
if (typeof prevTransactionName === 'string') {
35+
if (prevTransactionName.startsWith('/')) {
36+
return event;
37+
}
38+
39+
set(event, ['tags', 'transaction.rename.source'], 'existing transaction name');
40+
} else {
41+
set(event, ['tags', 'transaction.rename.source'], 'window.location.pathname');
42+
43+
prevTransactionName = window.location.pathname;
44+
}
45+
46+
const transactionName: string | undefined = await new Promise(function(resolve) {
47+
Router.match(
48+
{
49+
routes: appRoutes,
50+
location: createLocation(prevTransactionName),
51+
},
52+
(error, _redirectLocation, renderProps) => {
53+
if (error) {
54+
set(event, ['tags', 'transaction.rename.react-router-match'], 'error');
55+
return resolve(undefined);
56+
}
57+
58+
set(event, ['tags', 'transaction.rename.react-router-match'], 'success');
59+
60+
const routePath = getRouteStringFromRoutes(renderProps.routes ?? []);
61+
return resolve(routePath);
62+
}
63+
);
64+
});
65+
66+
if (typeof transactionName === 'string' && transactionName.length) {
67+
event.transaction = transactionName;
68+
69+
set(event, ['tags', 'transaction.rename.before'], prevTransactionName);
70+
set(event, ['tags', 'transaction.rename.after'], transactionName);
71+
72+
set(event, ['tags', 'ui.route'], transactionName);
73+
}
74+
75+
return event;
76+
}

0 commit comments

Comments
 (0)