diff --git a/dev-packages/e2e-tests/test-applications/angular-17/src/app/user/user.component.ts b/dev-packages/e2e-tests/test-applications/angular-17/src/app/user/user.component.ts index 087a33a4a2f1..db02568d395f 100644 --- a/dev-packages/e2e-tests/test-applications/angular-17/src/app/user/user.component.ts +++ b/dev-packages/e2e-tests/test-applications/angular-17/src/app/user/user.component.ts @@ -8,7 +8,8 @@ import { Observable, map } from 'rxjs'; standalone: true, imports: [AsyncPipe], template: ` -

Hello User {{ userId$ | async }}

+

Hello User {{ userId$ | async }}

+ `, }) export class UserComponent { @@ -17,4 +18,8 @@ export class UserComponent { constructor(private route: ActivatedRoute) { this.userId$ = this.route.paramMap.pipe(map(params => params.get('id') || 'UNKNOWN USER')); } + + throwError() { + throw new Error('Error thrown from user page'); + } } diff --git a/dev-packages/e2e-tests/test-applications/angular-17/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/angular-17/tests/errors.test.ts index e4d687ca3199..4666893b1882 100644 --- a/dev-packages/e2e-tests/test-applications/angular-17/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/angular-17/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '../event-proxy-server'; +import { waitForError, waitForTransaction } from '../event-proxy-server'; test('sends an error', async ({ page }) => { const errorPromise = waitForError('angular-17', async errorEvent => { @@ -25,5 +25,41 @@ test('sends an error', async ({ page }) => { }, ], }, + transaction: '/home/', + }); +}); + +test('assigns the correct transaction value after a navigation', async ({ page }) => { + const pageloadTxnPromise = waitForTransaction('angular-17', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; + }); + + const errorPromise = waitForError('angular-17', async errorEvent => { + return !errorEvent.type; + }); + + await page.goto(`/`); + await pageloadTxnPromise; + + await page.waitForTimeout(5000); + + await page.locator('#navLink').click(); + + const [_, error] = await Promise.all([page.locator('#userErrorBtn').click(), errorPromise]); + + expect(error).toMatchObject({ + exception: { + values: [ + { + type: 'Error', + value: 'Error thrown from user page', + mechanism: { + type: 'angular', + handled: false, + }, + }, + ], + }, + transaction: '/users/:id/', }); }); diff --git a/packages/angular/src/tracing.ts b/packages/angular/src/tracing.ts index bea704930d43..8b9b833ca3b8 100644 --- a/packages/angular/src/tracing.ts +++ b/packages/angular/src/tracing.ts @@ -143,10 +143,13 @@ export class TraceService implements OnDestroy { (event.state as unknown as RouterState & { root: ActivatedRouteSnapshot }).root, ); + if (route) { + getCurrentScope().setTransactionName(route); + } + const activeSpan = getActiveSpan(); const rootSpan = activeSpan && getRootSpan(activeSpan); - // TODO (v8 / #5416): revisit the source condition. Do we want to make the parameterized route the default? _updateSpanAttributesForParametrizedUrl(route, rootSpan); }), );