diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework/app/routes.ts b/dev-packages/e2e-tests/test-applications/react-router-7-framework/app/routes.ts index c1aacf4e5ce2..b412893def52 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework/app/routes.ts +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework/app/routes.ts @@ -16,5 +16,6 @@ export default [ route('with/:param', 'routes/performance/dynamic-param.tsx'), route('static', 'routes/performance/static.tsx'), route('server-loader', 'routes/performance/server-loader.tsx'), + route('server-action', 'routes/performance/server-action.tsx'), ]), ] satisfies RouteConfig; diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework/app/routes/performance/server-action.tsx b/dev-packages/e2e-tests/test-applications/react-router-7-framework/app/routes/performance/server-action.tsx new file mode 100644 index 000000000000..462fc6fbf54c --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework/app/routes/performance/server-action.tsx @@ -0,0 +1,24 @@ +import { Form } from 'react-router'; +import type { Route } from './+types/server-action'; + +export async function action({ request }: Route.ActionArgs) { + let formData = await request.formData(); + let name = formData.get('name'); + await new Promise(resolve => setTimeout(resolve, 1000)); + return { + greeting: `Hola ${name}`, + }; +} + +export default function Project({ actionData }: Route.ComponentProps) { + return ( +
+

Server action page

+
+ + +
+ {actionData ?

{actionData.greeting}

: null} +
+ ); +} diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework/tests/performance/performance.server.test.ts b/dev-packages/e2e-tests/test-applications/react-router-7-framework/tests/performance/performance.server.test.ts index 36e37f1ff288..b747719b5ff2 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework/tests/performance/performance.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework/tests/performance/performance.server.test.ts @@ -132,4 +132,31 @@ test.describe('servery - performance', () => { origin: 'auto.http.react-router', }); }); + + test('should automatically instrument server action', async ({ page }) => { + const txPromise = waitForTransaction(APP_NAME, async transactionEvent => { + return transactionEvent.transaction === 'POST /performance/server-action.data'; + }); + + await page.goto(`/performance/server-action`); + await page.getByRole('button', { name: 'Submit' }).click(); // this will trigger a .data request + + const transaction = await txPromise; + + expect(transaction?.spans?.[transaction.spans?.length - 1]).toMatchObject({ + span_id: expect.any(String), + trace_id: expect.any(String), + data: { + 'sentry.origin': 'auto.http.react-router', + 'sentry.op': 'function.react-router.action', + }, + description: 'Executing Server Action', + parent_span_id: expect.any(String), + start_timestamp: expect.any(Number), + timestamp: expect.any(Number), + status: 'ok', + op: 'function.react-router.action', + origin: 'auto.http.react-router', + }); + }); }); diff --git a/packages/react-router/src/server/sdk.ts b/packages/react-router/src/server/sdk.ts index b0ca0e79bd49..6d77011dc636 100644 --- a/packages/react-router/src/server/sdk.ts +++ b/packages/react-router/src/server/sdk.ts @@ -45,7 +45,7 @@ export function init(options: NodeOptions): NodeClient | undefined { const overwrite = event.contexts?.trace?.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OVERWRITE]; if ( event.type === 'transaction' && - event.transaction === 'GET *' && + (event.transaction === 'GET *' || event.transaction === 'POST *') && event.contexts?.trace?.data?.[ATTR_HTTP_ROUTE] === '*' && overwrite ) {