Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@
"optimization": false,
"extractLicenses": false,
"sourceMap": true
},
"streamed": {
"fileReplacements": [
{
"replace": "src/trace-lifecycle.ts",
"with": "src/trace-lifecycle.streamed.ts"
}
]
}
},
"defaultConfiguration": "production"
Expand Down
14 changes: 13 additions & 1 deletion dev-packages/e2e-tests/test-applications/angular-19/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
"test": "playwright test",
"test:build": "pnpm install && pnpm build",
"test:assert": "playwright test",
"clean": "npx rimraf .angular node_modules pnpm-lock.yaml dist"
"clean": "npx rimraf .angular node_modules pnpm-lock.yaml dist",
"build:streamed": "ng build --configuration production,streamed",
"test:build:streamed": "pnpm install && pnpm build:streamed",
"test:assert:streamed": "E2E_TEST_TRACE_LIFECYCLE=stream playwright test"
},
"private": true,
"dependencies": {
Expand Down Expand Up @@ -47,5 +50,14 @@
},
"volta": {
"extends": "../../package.json"
},
"sentryTest": {
"variants": [
{
"label": "angular-19 (streamed)",
"build-command": "pnpm test:build:streamed",
"assert-command": "pnpm test:assert:streamed"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config';
import { TRACE_LIFECYCLE } from './trace-lifecycle';

import * as Sentry from '@sentry/angular';

Sentry.init({
traceLifecycle: 'static',
traceLifecycle: TRACE_LIFECYCLE,
// Cannot use process.env here, so we hardcode the DSN
dsn: 'https://3b6c388182fb435097f41d181be2b2ba@o4504321058471936.ingest.sentry.io/4504321066008576',
tracesSampleRate: 1.0,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Replaces `trace-lifecycle.ts` in the `streamed` build configuration. See `angular.json`.
export const TRACE_LIFECYCLE = 'stream' as 'static' | 'stream';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Swapped for `trace-lifecycle.streamed.ts` by the `streamed` build configuration in `angular.json`.
// Angular can't read `process.env` in the browser bundle, so the lifecycle is picked at build time.
export const TRACE_LIFECYCLE = 'static' as 'static' | 'stream';
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ test('sends an error', async ({ page }) => {
});

test('assigns the correct transaction value after a navigation', async ({ page }) => {
// Waits on a pageload transaction, which the streamed variant never emits.
test.skip(process.env.E2E_TEST_TRACE_LIFECYCLE === 'stream', 'transactions are not emitted with span streaming');

const pageloadTxnPromise = waitForTransaction('angular-19', async transactionEvent => {
return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload';
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { waitForTransaction } from '@sentry-internal/test-utils';
// Cannot use @sentry/angular here due to build stuff
import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';

// The `angular-19 (streamed)` variant builds the app with `traceLifecycle: 'stream'`, which emits
// spans instead of transactions. See `streamed-performance.test.ts` for that variant.
test.skip(process.env.E2E_TEST_TRACE_LIFECYCLE === 'stream', 'transactions are not emitted with span streaming');

test('sends a pageload transaction with a parameterized URL', async ({ page }) => {
const transactionPromise = waitForTransaction('angular-19', async transactionEvent => {
return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { expect, test } from '@playwright/test';
import { getSpanOp, waitForStreamedSpan } from '@sentry-internal/test-utils';

// Only the `angular-19 (streamed)` variant builds the app with `traceLifecycle: 'stream'`.
test.skip(process.env.E2E_TEST_TRACE_LIFECYCLE !== 'stream', 'requires the app built with span streaming');

test('names the routing span with the low cardinality fallback', async ({ page }) => {
const routingSpanPromise = waitForStreamedSpan('angular-19', span => getSpanOp(span) === 'router');

await page.goto('/');
await page.locator('#navLink').click();

const routingSpan = await routingSpanPromise;

// The routing span starts at `NavigationStart`, where only the raw URL (`/users/123`) is known.
// Angular resolves the parameterized route at `ResolveEnd` and applies it to the root span, so a
// streamed routing span has nothing low cardinality to use and takes the static fallback.
expect(routingSpan.name).toBe('Router');
expect(routingSpan.attributes['sentry.origin']).toEqual({ type: 'string', value: 'auto.ui.angular' });
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
"start": "vite preview --port 3030",
"test": "playwright test",
"test:build": "pnpm install && pnpm run build",
"test:assert": "pnpm run test"
"test:assert": "pnpm run test",
"test:build:streamed": "VITE_TRACE_LIFECYCLE=stream pnpm run test:build",
"test:assert:streamed": "E2E_TEST_TRACE_LIFECYCLE=stream pnpm run test"
},
"devDependencies": {
"@playwright/test": "~1.56.0",
Expand Down Expand Up @@ -42,5 +44,14 @@
},
"volta": {
"extends": "../../package.json"
},
"sentryTest": {
"variants": [
{
"label": "ember-strict-resolver (streamed)",
"build-command": "pnpm test:build:streamed",
"assert-command": "pnpm test:assert:streamed"
}
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import * as Sentry from '@sentry/ember';
// Initialize Sentry
Sentry.init({
dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0',
traceLifecycle: 'static',
// Set by the `ember-strict-resolver (streamed)` test variant, which rebuilds the app to cover
// span streaming. Vite inlines this at build time, so it can't be flipped at runtime.
traceLifecycle: import.meta.env.VITE_TRACE_LIFECYCLE === 'stream' ? 'stream' : 'static',
tracesSampleRate: 1.0,
tunnel: 'http://localhost:3031/', // proxy server
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ test('sends an error', async ({ page }) => {
});

test('assigns the correct transaction value after a navigation', async ({ page }) => {
// Waits on a pageload transaction, which the streamed variant never emits.
test.skip(process.env.E2E_TEST_TRACE_LIFECYCLE === 'stream', 'transactions are not emitted with span streaming');

const pageloadTxnPromise = waitForTransaction('ember-strict-resolver', async transactionEvent => {
return !!transactionEvent.transaction && transactionEvent.contexts?.trace?.op === 'pageload';
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { expect, test } from '@playwright/test';
import { waitForTransaction } from '@sentry-internal/test-utils';

// The `ember-strict-resolver (streamed)` variant builds the app with `traceLifecycle: 'stream'`,
// which emits spans instead of transactions. See `streamed-performance.test.ts` for that variant.
test.skip(process.env.E2E_TEST_TRACE_LIFECYCLE === 'stream', 'transactions are not emitted with span streaming');

test('sends a pageload transaction with a parameterized URL', async ({ page }) => {
const transactionPromise = waitForTransaction('ember-strict-resolver', async transactionEvent => {
return !!transactionEvent.transaction && transactionEvent.contexts?.trace?.op === 'pageload';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { expect, test } from '@playwright/test';
import { getSpanOp, waitForStreamedSpan } from '@sentry-internal/test-utils';

// Only the `ember-strict-resolver (streamed)` variant builds the app with `traceLifecycle: 'stream'`.
test.skip(process.env.E2E_TEST_TRACE_LIFECYCLE !== 'stream', 'requires the app built with span streaming');

test('names the transition span with the low cardinality fallback', async ({ page }) => {
const transitionSpanPromise = waitForStreamedSpan('ember-strict-resolver', span => getSpanOp(span) === 'router');

await page.goto('/');
await page.getByText('Tracing').click();

const transitionSpan = await transitionSpanPromise;

// The route pair (`route:index -> route:tracing`) is not one of the convention's name templates,
// so a streamed router span takes the static fallback instead.
expect(transitionSpan.name).toBe('Router');
expect(transitionSpan.attributes['sentry.origin']).toEqual({ type: 'string', value: 'auto.ui.ember' });
});
Loading