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 @@ -3,7 +3,6 @@ import * as Sentry from '@sentry/browser';
window.Sentry = Sentry;

Sentry.init({
traceLifecycle: 'static',
dsn: 'https://public@dsn.ingest.sentry.io/1337',
integrations: [Sentry.browserTracingIntegration()],
tracesSampleRate: 1,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { SENTRY_ORIGIN } from '@sentry/conventions/attributes';
import { expect } from '@playwright/test';
import type { Event as SentryEvent } from '@sentry/core';
import { sentryTest } from '../../../../utils/fixtures';
import { countEnvelopes, getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers';
import { hidePage, shouldSkipTracingTest } from '../../../../utils/helpers';
import { collectStreamedSpans, getSpanOp, waitForStreamedSpan } from '../../../../utils/spanUtils';

sentryTest('does not capture interaction spans without the integration', async ({ getLocalTestUrl, page }) => {
sentryTest.skip(shouldSkipTracingTest());

const spans = collectStreamedSpans(page);
const pageloadPromise = waitForStreamedSpan(page, span => span.is_segment && getSpanOp(span) === 'pageload');
const url = await getLocalTestUrl({ testDir: __dirname });

await page.goto(url);
await getFirstSentryEnvelopeRequest<SentryEvent>(page);

const countPromise = countEnvelopes(page, { envelopeType: 'transaction', timeout: 2000 });

await pageloadPromise;
await page.locator('[data-test-id=interaction-button]').click();
await hidePage(page);
await page.evaluate(() => (window as any).Sentry.flush());

expect(await countPromise).toBe(0);
expect(spans.filter(span => span.attributes[SENTRY_ORIGIN]?.value === 'auto.browser.interactions')).toHaveLength(0);
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { interactionsIntegration } from '@sentry/browser';
window.Sentry = Sentry;

Sentry.init({
traceLifecycle: 'static',
dsn: 'https://public@dsn.ingest.sentry.io/1337',
tracesSampleRate: 1,
integrations: [Sentry.browserTracingIntegration(), interactionsIntegration()],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,28 @@
import { expect } from '@playwright/test';
import { sentryTest } from '../../../../utils/fixtures';
import { envelopeRequestParser, shouldSkipTracingTest, waitForTransactionRequest } from '../../../../utils/helpers';

sentryTest(
'click-triggered navigation should produce a root navigation transaction',
async ({ getLocalTestUrl, page }) => {
if (shouldSkipTracingTest()) {
sentryTest.skip();
}

const url = await getLocalTestUrl({ testDir: __dirname });

await page.goto(url);
await waitForTransactionRequest(page); // "pageload" root span

const interactionRequestPromise = waitForTransactionRequest(
page,
evt => evt.contexts?.trace?.op === 'ui.action.click',
);
const navigationRequestPromise = waitForTransactionRequest(page, evt => evt.contexts?.trace?.op === 'navigation');

await page.locator('[data-test-id=navigate-button]').click();

const interactionEvent = envelopeRequestParser(await interactionRequestPromise);
const navigationEvent = envelopeRequestParser(await navigationRequestPromise);

// Navigation is root span, not a child span on the interaction
expect(interactionEvent.contexts?.trace?.op).toBe('ui.action.click');
expect(navigationEvent.contexts?.trace?.op).toBe('navigation');

expect(interactionEvent.contexts?.trace?.trace_id).not.toEqual(navigationEvent.contexts?.trace?.trace_id);

// does not contain a child navigation span
const interactionSpans = interactionEvent.spans || [];
const hasNavigationChild = interactionSpans.some(span => span.op === 'navigation' || span.op === 'http.server');
expect(hasNavigationChild).toBeFalsy();
},
);
import { shouldSkipTracingTest } from '../../../../utils/helpers';
import { collectStreamedSpans, getSpanOp, waitForStreamedSpan } from '../../../../utils/spanUtils';

sentryTest('starts a root navigation segment when a click triggers navigation', async ({ getLocalTestUrl, page }) => {
sentryTest.skip(shouldSkipTracingTest());
const spans = collectStreamedSpans(page);
const pageloadPromise = waitForStreamedSpan(page, span => span.is_segment && getSpanOp(span) === 'pageload');
const url = await getLocalTestUrl({ testDir: __dirname });
await page.goto(url);
await pageloadPromise;

const interactionPromise = waitForStreamedSpan(
page,
span => span.is_segment && getSpanOp(span) === 'ui.action.click',
);
const navigationPromise = waitForStreamedSpan(page, span => span.is_segment && getSpanOp(span) === 'navigation');
await page.locator('[data-test-id=navigate-button]').click();
const [interaction, navigation] = await Promise.all([interactionPromise, navigationPromise]);
await page.evaluate(() => (window as any).Sentry.flush());

expect(navigation.is_segment).toBe(true);
expect(navigation).not.toHaveProperty('parent_span_id');
expect(navigation.trace_id).not.toBe(interaction.trace_id);
const children = spans.filter(span => span.parent_span_id === interaction.span_id);
expect(children.filter(span => ['navigation', 'http.server'].includes(getSpanOp(span) ?? ''))).toHaveLength(0);
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ window.Sentry = Sentry;

Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
integrations: [Sentry.browserTracingIntegration(), interactionsIntegration(), Sentry.spanStreamingIntegration()],
integrations: [Sentry.browserTracingIntegration(), interactionsIntegration()],
tracesSampleRate: 1,
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { expect } from '@playwright/test';
import { SDK_VERSION } from '@sentry/core';
import {
SENTRY_IS_LOCALHOST,
CULTURE_CALENDAR,
CULTURE_LOCALE,
CULTURE_TIMEZONE,
URL_FULL,
BROWSER_WEB_VITAL_INP_TARGET,
SENTRY_IDLE_SPAN_FINISH_REASON,
SENTRY_SEGMENT_ID,
SENTRY_SEGMENT_NAME,
Expand All @@ -17,16 +23,18 @@ import {
} from '@sentry/conventions/attributes';
import { sentryTest } from '../../../../utils/fixtures';
import { shouldSkipTracingTest } from '../../../../utils/helpers';
import { getSpanOp, waitForStreamedSpan, waitForStreamedSpans } from '../../../../utils/spanUtils';
import { collectStreamedSpans, getSpanOp, waitForStreamedSpan } from '../../../../utils/spanUtils';

sentryTest('captures streamed interaction span tree. @firefox', async ({ browserName, getLocalTestUrl, page }) => {
const supportedBrowsers = ['chromium', 'firefox'];

sentryTest.skip(shouldSkipTracingTest() || !supportedBrowsers.includes(browserName));
const url = await getLocalTestUrl({ testDir: __dirname });

const interactionSpansPromise = waitForStreamedSpans(page, spans =>
spans.some(span => getSpanOp(span) === 'ui.action.click'),
const spans = collectStreamedSpans(page);
const interactionPromise = waitForStreamedSpan(
page,
span => span.is_segment && getSpanOp(span) === 'ui.action.click',
);

const pageloadSpanPromise = waitForStreamedSpan(page, span => getSpanOp(span) === 'pageload');
Expand All @@ -39,34 +47,38 @@ sentryTest('captures streamed interaction span tree. @firefox', async ({ browser
await page.locator('[data-test-id=interaction-button]').click();
await page.locator('.clicked[data-test-id=interaction-button]').isVisible();

const interactionSpanTree = await interactionSpansPromise;

const interactionSegmentSpan = interactionSpanTree.find(span => !!span.is_segment);
const interactionSegmentSpan = await interactionPromise;
await page.evaluate(() => (window as any).Sentry.flush());
const interactionSpanTree = spans.filter(
span =>
span.span_id === interactionSegmentSpan.span_id ||
span.attributes[SENTRY_SEGMENT_ID]?.value === interactionSegmentSpan.span_id,
);

expect(interactionSegmentSpan).toEqual({
attributes: {
'sentry.is_localhost': { value: false, type: 'boolean' },
[SENTRY_IS_LOCALHOST]: { value: false, type: 'boolean' },
[SENTRY_TRACE_LIFECYCLE]: {
type: 'string',
value: 'stream',
},
'culture.calendar': {
[CULTURE_CALENDAR]: {
type: 'string',
value: expect.any(String),
},
'culture.locale': {
[CULTURE_LOCALE]: {
type: 'string',
value: expect.any(String),
},
'culture.timezone': {
[CULTURE_TIMEZONE]: {
type: 'string',
value: expect.any(String),
},
[USER_AGENT_ORIGINAL]: {
type: 'string',
value: expect.any(String),
},
'url.full': {
[URL_FULL]: {
type: 'string',
value: expect.any(String),
},
Expand Down Expand Up @@ -130,7 +142,7 @@ sentryTest('captures streamed interaction span tree. @firefox', async ({ browser
const interactionSpan = interactionSpanTree.find(span => getSpanOp(span) === 'ui.interaction.click');
expect(interactionSpan).toEqual({
attributes: {
'sentry.is_localhost': { value: false, type: 'boolean' },
[SENTRY_IS_LOCALHOST]: { value: false, type: 'boolean' },
[SENTRY_TRACE_LIFECYCLE]: {
type: 'string',
value: 'stream',
Expand Down Expand Up @@ -167,7 +179,7 @@ sentryTest('captures streamed interaction span tree. @firefox', async ({ browser
type: 'string',
value: 'production',
},
'browser.web_vital.inp.target': {
[BROWSER_WEB_VITAL_INP_TARGET]: {
type: 'string',
value: 'body > button.clicked',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import * as Sentry from '@sentry/browser';
window.Sentry = Sentry;

Sentry.init({
traceLifecycle: 'static',
dsn: 'https://public@dsn.ingest.sentry.io/1337',
integrations: [
Sentry.browserTracingIntegration({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,24 @@
import { expect } from '@playwright/test';
import type { Event } from '@sentry/core';
import { sentryTest } from '../../../../utils/fixtures';
import { envelopeRequestParser, shouldSkipTracingTest, waitForTransactionRequest } from '../../../../utils/helpers';
import { shouldSkipTracingTest } from '../../../../utils/helpers';
import { waitForStreamedSpanAndTraceHeaderOnUrl } from '../../../../utils/spanUtils';
import {
BROWSER_WEB_VITAL_FCP_VALUE,
BROWSER_WEB_VITAL_TTFB_VALUE,
NETWORK_CONNECTION_RTT,
} from '@sentry/conventions/attributes';

sentryTest.beforeEach(({ browserName }) => {
if (shouldSkipTracingTest() || browserName !== 'chromium') {
sentryTest.skip();
}
});

// `connection.rtt` is recorded as a measurement, which is only flushed on the pageload
// transaction. It must not leak onto navigation transactions.
sentryTest(
'records `connection.rtt` as a measurement on pageload but not on navigation transactions',
async ({ getLocalTestUrl, page }) => {
const pageloadRequestPromise = waitForTransactionRequest(page, event => event.contexts?.trace?.op === 'pageload');
'records connection RTT on pageload and navigation spans',
async ({ getLocalTestUrl, page, browserName }) => {
sentryTest.skip(shouldSkipTracingTest() || browserName !== 'chromium');
const url = await getLocalTestUrl({ testDir: __dirname });
await page.goto(url);

const pageloadRequest = envelopeRequestParser(await pageloadRequestPromise) as Event;

const navigationRequestPromise = waitForTransactionRequest(
page,
event => event.contexts?.trace?.op === 'navigation',
);
await page.goto(`${url}#foo`);

const navigationRequest = envelopeRequestParser(await navigationRequestPromise) as Event;

expect(pageloadRequest.contexts?.trace?.op).toBe('pageload');
expect(navigationRequest.contexts?.trace?.op).toBe('navigation');
const [pageload] = await waitForStreamedSpanAndTraceHeaderOnUrl(page, url);
const [navigation] = await waitForStreamedSpanAndTraceHeaderOnUrl(page, `${url}#foo`);

expect(pageloadRequest.measurements?.['connection.rtt']?.value).toBeDefined();
expect(navigationRequest.measurements?.['connection.rtt']).toBeUndefined();
expect(pageload.attributes[NETWORK_CONNECTION_RTT]).toEqual({ type: 'integer', value: 0 });
expect(navigation.attributes[NETWORK_CONNECTION_RTT]).toEqual(pageload.attributes[NETWORK_CONNECTION_RTT]);
expect(navigation.attributes[BROWSER_WEB_VITAL_FCP_VALUE]).toBeUndefined();
expect(navigation.attributes[BROWSER_WEB_VITAL_TTFB_VALUE]).toBeUndefined();
},
);
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { Page } from '@playwright/test';
import { expect } from '@playwright/test';
import type { Event } from '@sentry/core';
import { sentryTest } from '../../../../utils/fixtures';
import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers';
import { shouldSkipTracingTest } from '../../../../utils/helpers';
import { waitForStreamedSpanAndTraceHeaderOnUrl } from '../../../../utils/spanUtils';
import { NETWORK_CONNECTION_RTT } from '@sentry/conventions/attributes';

sentryTest.beforeEach(({ browserName }) => {
if (shouldSkipTracingTest() || browserName !== 'chromium') {
Expand All @@ -22,55 +23,42 @@ async function createSessionWithLatency(page: Page, latency: number) {
return session;
}

sentryTest('should capture a `connection.rtt` metric. xxx', async ({ getLocalTestUrl, page }) => {
sentryTest('captures connection RTT without emulation', async ({ getLocalTestUrl, page }) => {
const url = await getLocalTestUrl({ testDir: __dirname });
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
const eventData = await waitForStreamedSpanAndTraceHeaderOnUrl(page, url).then(([span]) => span);

expect(eventData.measurements).toBeDefined();
expect(eventData.measurements?.['connection.rtt']?.value).toBe(0);
expect(eventData.attributes[NETWORK_CONNECTION_RTT]?.value).toBe(0);
});

sentryTest(
'should capture a `connection.rtt` metric with emulated value 200ms on Chromium.',
async ({ getLocalTestUrl, page }) => {
const session = await createSessionWithLatency(page, 200);
sentryTest('captures connection RTT with emulated value 200ms on Chromium.', async ({ getLocalTestUrl, page }) => {
const session = await createSessionWithLatency(page, 200);

const url = await getLocalTestUrl({ testDir: __dirname });
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
const url = await getLocalTestUrl({ testDir: __dirname });
const eventData = await waitForStreamedSpanAndTraceHeaderOnUrl(page, url).then(([span]) => span);

await session.detach();
await session.detach();

expect(eventData.measurements).toBeDefined();
expect(eventData.measurements?.['connection.rtt']?.value).toBe(200);
},
);
expect(eventData.attributes[NETWORK_CONNECTION_RTT]?.value).toBe(200);
});

sentryTest(
'should capture a `connection.rtt` metric with emulated value 100ms on Chromium.',
async ({ getLocalTestUrl, page }) => {
const session = await createSessionWithLatency(page, 100);
sentryTest('captures connection RTT with emulated value 100ms on Chromium.', async ({ getLocalTestUrl, page }) => {
const session = await createSessionWithLatency(page, 100);

const url = await getLocalTestUrl({ testDir: __dirname });
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
const url = await getLocalTestUrl({ testDir: __dirname });
const eventData = await waitForStreamedSpanAndTraceHeaderOnUrl(page, url).then(([span]) => span);

await session.detach();
await session.detach();

expect(eventData.measurements).toBeDefined();
expect(eventData.measurements?.['connection.rtt']?.value).toBe(100);
},
);
expect(eventData.attributes[NETWORK_CONNECTION_RTT]?.value).toBe(100);
});

sentryTest(
'should capture a `connection.rtt` metric with emulated value 50ms on Chromium.',
async ({ getLocalTestUrl, page }) => {
const session = await createSessionWithLatency(page, 50);
sentryTest('captures connection RTT with emulated value 50ms on Chromium.', async ({ getLocalTestUrl, page }) => {
const session = await createSessionWithLatency(page, 50);

const url = await getLocalTestUrl({ testDir: __dirname });
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
const url = await getLocalTestUrl({ testDir: __dirname });
const eventData = await waitForStreamedSpanAndTraceHeaderOnUrl(page, url).then(([span]) => span);

await session.detach();
await session.detach();

expect(eventData.measurements).toBeDefined();
expect(eventData.measurements?.['connection.rtt']?.value).toBe(50);
},
);
expect(eventData.attributes[NETWORK_CONNECTION_RTT]?.value).toBe(50);
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import * as Sentry from '@sentry/browser';
window.Sentry = Sentry;

Sentry.init({
traceLifecycle: 'static',
debug: true,
dsn: 'https://public@dsn.ingest.sentry.io/1337',
integrations: [Sentry.browserTracingIntegration(), Sentry.elementTimingIntegration()],
Expand Down
Loading
Loading