Skip to content

Commit 1b3fb8b

Browse files
authored
feat(nextjs): Add transactionName to isolation scope for Next.js server side features (#11782)
1 parent 427602e commit 1b3fb8b

13 files changed

+25
-2
lines changed

dev-packages/e2e-tests/test-applications/nextjs-14/tests/generation-functions.test.ts

+6
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ test('Should send a transaction and an error event for a faulty generateMetadata
4040
const errorEvent = await errorEventPromise;
4141
const transactionEvent = await transactionPromise;
4242

43+
expect(errorEvent.transaction).toBe('Page.generateMetadata (/generation-functions)');
44+
4345
// Assert that isolation scope works properly
4446
expect(errorEvent.tags?.['my-isolated-tag']).toBe(true);
4547
expect(errorEvent.tags?.['my-global-scope-isolated-tag']).not.toBeDefined();
@@ -82,6 +84,10 @@ test('Should send a transaction and an error event for a faulty generateViewport
8284

8385
expect(await transactionPromise).toBeDefined();
8486
expect(await errorEventPromise).toBeDefined();
87+
88+
const errorEvent = await errorEventPromise;
89+
90+
expect(errorEvent.transaction).toBe('Page.generateViewport (/generation-functions)');
8591
});
8692

8793
test('Should send a transaction event with correct status for a generateMetadata() function invokation with redirect()', async ({

dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/edge-route.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,6 @@ test('Should record exceptions for faulty edge routes', async ({ request }) => {
6060
// Assert that isolation scope works properly
6161
expect(errorEvent.tags?.['my-isolated-tag']).toBe(true);
6262
expect(errorEvent.tags?.['my-global-scope-isolated-tag']).not.toBeDefined();
63+
64+
expect(errorEvent.transaction).toBe('GET /api/error-edge-endpoint');
6365
});

dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/edge.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ test('Should record exceptions for faulty edge server components', async ({ page
1515
// Assert that isolation scope works properly
1616
expect(errorEvent.tags?.['my-isolated-tag']).toBe(true);
1717
expect(errorEvent.tags?.['my-global-scope-isolated-tag']).not.toBeDefined();
18+
19+
expect(errorEvent.transaction).toBe(`Page Server Component (/edge-server-components/error)`);
1820
});
1921

2022
test('Should record transaction for edge server components', async ({ page }) => {

dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/middleware.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ test('Records exceptions happening in middleware', async ({ request }) => {
5252
// Assert that isolation scope works properly
5353
expect(errorEvent.tags?.['my-isolated-tag']).toBe(true);
5454
expect(errorEvent.tags?.['my-global-scope-isolated-tag']).not.toBeDefined();
55+
expect(errorEvent.transaction).toBe('middleware');
5556
});
5657

5758
test('Should trace outgoing fetch requests inside middleware and create breadcrumbs for it', async ({ request }) => {

dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/route-handlers.test.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ test('Should record exceptions and transactions for faulty route handlers', asyn
5959
expect(routehandlerTransaction.contexts?.trace?.origin).toBe('auto.function.nextjs');
6060

6161
expect(routehandlerError.exception?.values?.[0].value).toBe('route-handler-error');
62-
// TODO: Uncomment once we update the scope transaction name on the server side
63-
// expect(routehandlerError.transaction).toBe('PUT /route-handlers/[param]/error');
62+
63+
expect(routehandlerError.transaction).toBe('PUT /route-handlers/[param]/error');
6464
});
6565

6666
test.describe('Edge runtime', () => {
@@ -106,6 +106,8 @@ test.describe('Edge runtime', () => {
106106

107107
expect(routehandlerError.exception?.values?.[0].value).toBe('route-handler-edge-error');
108108
expect(routehandlerError.contexts?.runtime?.name).toBe('vercel-edge');
109+
110+
expect(routehandlerError.transaction).toBe('DELETE /route-handlers/[param]/edge');
109111
});
110112
});
111113

dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/server-components.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ test('Should capture an error and transaction with correct status for a faulty s
9898

9999
expect(transactionEvent.contexts?.trace?.status).toBe('internal_error');
100100

101+
expect(errorEvent.transaction).toBe(`Page Server Component (/server-component/faulty)`);
102+
101103
expect(errorEvent.tags?.['my-isolated-tag']).toBe(true);
102104
expect(errorEvent.tags?.['my-global-scope-isolated-tag']).not.toBeDefined();
103105
expect(transactionEvent.tags?.['my-isolated-tag']).toBe(true);

packages/nextjs/src/common/utils/edgeWrapperUtils.ts

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ export function withEdgeWrapping<H extends EdgeRouteHandler>(
3838
});
3939
}
4040

41+
isolationScope.setTransactionName(options.spanDescription);
42+
4143
return continueTrace(
4244
{
4345
sentryTrace,

packages/nextjs/src/common/utils/wrapperUtils.ts

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export function withTracedServerSideDataFetcher<F extends (...args: any[]) => Pr
9393
return escapeNextjsTracing(() => {
9494
const isolationScope = commonObjectToIsolationScope(req);
9595
return withIsolationScope(isolationScope, () => {
96+
isolationScope.setTransactionName(`${options.dataFetchingMethodName} (${options.dataFetcherRouteName})`);
9697
isolationScope.setSDKProcessingMetadata({
9798
request: req,
9899
});

packages/nextjs/src/common/withServerActionInstrumentation.ts

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ async function withServerActionInstrumentationImplementation<A extends (...args:
7575
);
7676
}
7777

78+
isolationScope.setTransactionName(`serverAction/${serverActionName}`);
7879
isolationScope.setSDKProcessingMetadata({
7980
request: {
8081
headers: fullHeadersObject,

packages/nextjs/src/common/wrapGenerationFunctionWithSentry.ts

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export function wrapGenerationFunctionWithSentry<F extends (...args: any[]) => a
5959
const propagationContext = commonObjectToPropagationContext(headers, incomingPropagationContext);
6060

6161
return withIsolationScope(isolationScope, () => {
62+
isolationScope.setTransactionName(`${componentType}.${generationFunctionIdentifier} (${componentRoute})`);
6263
isolationScope.setSDKProcessingMetadata({
6364
request: {
6465
headers: headers ? winterCGHeadersToDict(headers) : undefined,

packages/nextjs/src/common/wrapRouteHandlerWithSentry.ts

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export function wrapRouteHandlerWithSentry<F extends (...args: any[]) => any>(
5252
const propagationContext = commonObjectToPropagationContext(headers, incomingPropagationContext);
5353

5454
return withIsolationScope(isolationScope, async () => {
55+
isolationScope.setTransactionName(`${method} ${parameterizedRoute}`);
5556
getCurrentScope().setPropagationContext(propagationContext);
5657
try {
5758
return startSpan(

packages/nextjs/src/common/wrapServerComponentWithSentry.ts

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export function wrapServerComponentWithSentry<F extends (...args: any[]) => any>
5555
const propagationContext = commonObjectToPropagationContext(context.headers, incomingPropagationContext);
5656

5757
return withIsolationScope(isolationScope, () => {
58+
isolationScope.setTransactionName(`${componentType} Server Component (${componentRoute})`);
5859
getCurrentScope().setPropagationContext(propagationContext);
5960
return startSpanManual(
6061
{

packages/nextjs/test/integration/test/server/errorServerSideProps.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ describe('Error Server-side Props', () => {
1111
});
1212

1313
expect(envelope[2]).toMatchObject({
14+
transaction: `getServerSideProps (/withErrorServerSideProps)`,
1415
exception: {
1516
values: [
1617
{

0 commit comments

Comments
 (0)