From aa6147eb88442e5538fdfba143ae8a57bc6a1bce Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Mon, 4 Mar 2024 17:04:38 +0000 Subject: [PATCH] feat(core): Use serialized spans in transaction event Previously, we passed the span instance, which is a) tricky because it keeps references etc, and b) doesn't work with the new span schema anyhow (because nothing is readable off the spans). --- .../suites/public-api/startSpan/basic/test.ts | 6 ++-- .../startTransaction/basic_usage/test.ts | 6 ++-- .../http-timings/test.ts | 4 +-- .../long-tasks-disabled/test.ts | 4 +-- .../long-tasks-enabled/test.ts | 4 +-- .../pageloadWithHeartbeatTimeout/test.ts | 4 +-- .../metrics/pageload-browser-spans/test.ts | 4 +-- .../metrics/pageload-resource-spans/test.ts | 4 +-- .../tracing/metrics/web-vitals-fid/test.ts | 4 +-- .../tracing/metrics/web-vitals-fp-fcp/test.ts | 6 ++-- .../suites/tracing/request/fetch/test.ts | 4 +-- .../suites/tracing/request/xhr/test.ts | 4 +-- .../angular-17/event-proxy-server.ts | 18 +++++----- .../event-proxy-server.ts | 18 +++++----- .../sveltekit-2/event-proxy-server.ts | 18 +++++----- .../sveltekit/event-proxy-server.ts | 10 +++--- .../vue-3/event-proxy-server.ts | 18 +++++----- packages/core/src/tracing/transaction.ts | 3 +- packages/core/src/utils/prepareEvent.ts | 15 ++++---- packages/core/test/lib/base.test.ts | 26 +++++++------- packages/core/test/lib/tracing/trace.test.ts | 6 ++-- packages/ember/tests/helpers/utils.ts | 8 ++--- .../test/integration/transactions.test.ts | 6 ++-- packages/node/test/handlers.test.ts | 2 +- packages/node/test/performance.test.ts | 5 ++- .../test/integration/transactions.test.ts | 5 ++- packages/opentelemetry/test/trace.test.ts | 7 ++-- packages/svelte/test/performance.test.ts | 36 ++++++++----------- packages/types/src/event.ts | 15 ++------ packages/types/src/index.ts | 2 +- 30 files changed, 122 insertions(+), 150 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/public-api/startSpan/basic/test.ts b/dev-packages/browser-integration-tests/suites/public-api/startSpan/basic/test.ts index 2567f5c018d3..71637c9294f1 100644 --- a/dev-packages/browser-integration-tests/suites/public-api/startSpan/basic/test.ts +++ b/dev-packages/browser-integration-tests/suites/public-api/startSpan/basic/test.ts @@ -1,5 +1,5 @@ import { expect } from '@playwright/test'; -import type { SerializedEvent } from '@sentry/types'; +import type { Event } from '@sentry/types'; import { sentryTest } from '../../../../utils/fixtures'; import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers'; @@ -10,7 +10,7 @@ sentryTest('should send a transaction in an envelope', async ({ getLocalTestPath } const url = await getLocalTestPath({ testDir: __dirname }); - const transaction = await getFirstSentryEnvelopeRequest(page, url); + const transaction = await getFirstSentryEnvelopeRequest(page, url); expect(transaction.transaction).toBe('parent_span'); expect(transaction.spans).toBeDefined(); @@ -22,7 +22,7 @@ sentryTest('should report finished spans as children of the root transaction', a } const url = await getLocalTestPath({ testDir: __dirname }); - const transaction = await getFirstSentryEnvelopeRequest(page, url); + const transaction = await getFirstSentryEnvelopeRequest(page, url); expect(transaction.spans).toHaveLength(1); diff --git a/dev-packages/browser-integration-tests/suites/public-api/startTransaction/basic_usage/test.ts b/dev-packages/browser-integration-tests/suites/public-api/startTransaction/basic_usage/test.ts index 1f9897d2e680..0624ff3f7dad 100644 --- a/dev-packages/browser-integration-tests/suites/public-api/startTransaction/basic_usage/test.ts +++ b/dev-packages/browser-integration-tests/suites/public-api/startTransaction/basic_usage/test.ts @@ -1,5 +1,5 @@ import { expect } from '@playwright/test'; -import type { SerializedEvent } from '@sentry/types'; +import type { Event } from '@sentry/types'; import { sentryTest } from '../../../../utils/fixtures'; import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers'; @@ -10,7 +10,7 @@ sentryTest('should report a transaction in an envelope', async ({ getLocalTestPa } const url = await getLocalTestPath({ testDir: __dirname }); - const transaction = await getFirstSentryEnvelopeRequest(page, url); + const transaction = await getFirstSentryEnvelopeRequest(page, url); expect(transaction.transaction).toBe('root_span'); expect(transaction.spans).toBeDefined(); @@ -22,7 +22,7 @@ sentryTest('should report finished spans as children of the root span', async ({ } const url = await getLocalTestPath({ testDir: __dirname }); - const transaction = await getFirstSentryEnvelopeRequest(page, url); + const transaction = await getFirstSentryEnvelopeRequest(page, url); const rootSpanId = transaction?.contexts?.trace?.span_id; diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/http-timings/test.ts b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/http-timings/test.ts index 467507fa6f75..a8e7f9eec335 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/http-timings/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/http-timings/test.ts @@ -1,5 +1,5 @@ import { expect } from '@playwright/test'; -import type { SerializedEvent } from '@sentry/types'; +import type { Event } from '@sentry/types'; import { sentryTest } from '../../../../utils/fixtures'; import { getMultipleSentryEnvelopeRequests, shouldSkipTracingTest } from '../../../../utils/helpers'; @@ -23,7 +23,7 @@ sentryTest('should create fetch spans with http timing @firefox', async ({ brows const url = await getLocalTestPath({ testDir: __dirname }); - const envelopes = await getMultipleSentryEnvelopeRequests(page, 2, { url, timeout: 10000 }); + const envelopes = await getMultipleSentryEnvelopeRequests(page, 2, { url, timeout: 10000 }); const tracingEvent = envelopes[envelopes.length - 1]; // last envelope contains tracing data on all browsers const requestSpans = tracingEvent.spans?.filter(({ op }) => op === 'http.client'); diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/long-tasks-disabled/test.ts b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/long-tasks-disabled/test.ts index d460d2883afd..6dab208d1c4e 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/long-tasks-disabled/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/long-tasks-disabled/test.ts @@ -1,6 +1,6 @@ import type { Route } from '@playwright/test'; import { expect } from '@playwright/test'; -import type { SerializedEvent } from '@sentry/types'; +import type { Event } from '@sentry/types'; import { sentryTest } from '../../../../utils/fixtures'; import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers'; @@ -15,7 +15,7 @@ sentryTest('should not capture long task when flag is disabled.', async ({ brows const url = await getLocalTestPath({ testDir: __dirname }); - const eventData = await getFirstSentryEnvelopeRequest(page, url); + const eventData = await getFirstSentryEnvelopeRequest(page, url); const uiSpans = eventData.spans?.filter(({ op }) => op?.startsWith('ui')); expect(uiSpans?.length).toBe(0); diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/long-tasks-enabled/test.ts b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/long-tasks-enabled/test.ts index 1ed0bcda2a89..6189758c0340 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/long-tasks-enabled/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/long-tasks-enabled/test.ts @@ -1,6 +1,6 @@ import type { Route } from '@playwright/test'; import { expect } from '@playwright/test'; -import type { SerializedEvent } from '@sentry/types'; +import type { Event } from '@sentry/types'; import { sentryTest } from '../../../../utils/fixtures'; import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers'; @@ -15,7 +15,7 @@ sentryTest('should capture long task.', async ({ browserName, getLocalTestPath, const url = await getLocalTestPath({ testDir: __dirname }); - const eventData = await getFirstSentryEnvelopeRequest(page, url); + const eventData = await getFirstSentryEnvelopeRequest(page, url); const uiSpans = eventData.spans?.filter(({ op }) => op?.startsWith('ui')); expect(uiSpans?.length).toBeGreaterThan(0); diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageloadWithHeartbeatTimeout/test.ts b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageloadWithHeartbeatTimeout/test.ts index ead37d6f8662..f96495a69925 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageloadWithHeartbeatTimeout/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageloadWithHeartbeatTimeout/test.ts @@ -1,5 +1,5 @@ import { expect } from '@playwright/test'; -import type { SerializedEvent } from '@sentry/types'; +import type { Event } from '@sentry/types'; import { sentryTest } from '../../../../utils/fixtures'; import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers'; @@ -16,7 +16,7 @@ sentryTest( const url = await getLocalTestPath({ testDir: __dirname }); - const eventData = await getFirstSentryEnvelopeRequest(page, url); + const eventData = await getFirstSentryEnvelopeRequest(page, url); expect(eventData.contexts?.trace?.op).toBe('pageload'); expect( diff --git a/dev-packages/browser-integration-tests/suites/tracing/metrics/pageload-browser-spans/test.ts b/dev-packages/browser-integration-tests/suites/tracing/metrics/pageload-browser-spans/test.ts index 0730d2ba4645..b60cdce9703b 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/metrics/pageload-browser-spans/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/metrics/pageload-browser-spans/test.ts @@ -1,5 +1,5 @@ import { expect } from '@playwright/test'; -import type { SerializedEvent } from '@sentry/types'; +import type { Event } from '@sentry/types'; import { sentryTest } from '../../../../utils/fixtures'; import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers'; @@ -11,7 +11,7 @@ sentryTest('should add browser-related spans to pageload transaction', async ({ const url = await getLocalTestPath({ testDir: __dirname }); - const eventData = await getFirstSentryEnvelopeRequest(page, url); + const eventData = await getFirstSentryEnvelopeRequest(page, url); const browserSpans = eventData.spans?.filter(({ op }) => op === 'browser'); // Spans `connect`, `cache` and `DNS` are not always inside `pageload` transaction. diff --git a/dev-packages/browser-integration-tests/suites/tracing/metrics/pageload-resource-spans/test.ts b/dev-packages/browser-integration-tests/suites/tracing/metrics/pageload-resource-spans/test.ts index 40159d39ea25..e98cb5b3d9b2 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/metrics/pageload-resource-spans/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/metrics/pageload-resource-spans/test.ts @@ -1,6 +1,6 @@ import type { Route } from '@playwright/test'; import { expect } from '@playwright/test'; -import type { SerializedEvent } from '@sentry/types'; +import type { Event } from '@sentry/types'; import { sentryTest } from '../../../../utils/fixtures'; import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers'; @@ -17,7 +17,7 @@ sentryTest('should add resource spans to pageload transaction', async ({ getLoca const url = await getLocalTestPath({ testDir: __dirname }); - const eventData = await getFirstSentryEnvelopeRequest(page, url); + const eventData = await getFirstSentryEnvelopeRequest(page, url); const resourceSpans = eventData.spans?.filter(({ op }) => op?.startsWith('resource')); // Webkit 16.0 (which is linked to Playwright 1.27.1) consistently creates 2 consectutive spans for `css`, diff --git a/dev-packages/browser-integration-tests/suites/tracing/metrics/web-vitals-fid/test.ts b/dev-packages/browser-integration-tests/suites/tracing/metrics/web-vitals-fid/test.ts index 94402e4f6ab3..e70247230b15 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/metrics/web-vitals-fid/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/metrics/web-vitals-fid/test.ts @@ -1,5 +1,5 @@ import { expect } from '@playwright/test'; -import type { SerializedEvent } from '@sentry/types'; +import type { Event } from '@sentry/types'; import { sentryTest } from '../../../../utils/fixtures'; import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers'; @@ -16,7 +16,7 @@ sentryTest('should capture a FID vital.', async ({ browserName, getLocalTestPath // To trigger FID await page.locator('#fid-btn').click(); - const eventData = await getFirstSentryEnvelopeRequest(page); + const eventData = await getFirstSentryEnvelopeRequest(page); expect(eventData.measurements).toBeDefined(); expect(eventData.measurements?.fid?.value).toBeDefined(); diff --git a/dev-packages/browser-integration-tests/suites/tracing/metrics/web-vitals-fp-fcp/test.ts b/dev-packages/browser-integration-tests/suites/tracing/metrics/web-vitals-fp-fcp/test.ts index 2ba417a84c18..70a9fd689e6e 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/metrics/web-vitals-fp-fcp/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/metrics/web-vitals-fp-fcp/test.ts @@ -1,5 +1,5 @@ import { expect } from '@playwright/test'; -import type { SerializedEvent } from '@sentry/types'; +import type { Event } from '@sentry/types'; import { sentryTest } from '../../../../utils/fixtures'; import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers'; @@ -11,7 +11,7 @@ sentryTest('should capture FP vital.', async ({ browserName, getLocalTestPath, p } const url = await getLocalTestPath({ testDir: __dirname }); - const eventData = await getFirstSentryEnvelopeRequest(page, url); + const eventData = await getFirstSentryEnvelopeRequest(page, url); expect(eventData.measurements).toBeDefined(); expect(eventData.measurements?.fp?.value).toBeDefined(); @@ -29,7 +29,7 @@ sentryTest('should capture FCP vital.', async ({ getLocalTestPath, page }) => { } const url = await getLocalTestPath({ testDir: __dirname }); - const eventData = await getFirstSentryEnvelopeRequest(page, url); + const eventData = await getFirstSentryEnvelopeRequest(page, url); expect(eventData.measurements).toBeDefined(); expect(eventData.measurements?.fcp?.value).toBeDefined(); diff --git a/dev-packages/browser-integration-tests/suites/tracing/request/fetch/test.ts b/dev-packages/browser-integration-tests/suites/tracing/request/fetch/test.ts index ab4c29906f5c..4308491f2d7f 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/request/fetch/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/request/fetch/test.ts @@ -1,5 +1,5 @@ import { expect } from '@playwright/test'; -import type { SerializedEvent } from '@sentry/types'; +import type { Event } from '@sentry/types'; import { sentryTest } from '../../../../utils/fixtures'; import { getMultipleSentryEnvelopeRequests, shouldSkipTracingTest } from '../../../../utils/helpers'; @@ -21,7 +21,7 @@ sentryTest('should create spans for multiple fetch requests', async ({ getLocalT // If we are on FF or webkit: // 1st envelope contains CORS error // 2nd envelope contains the tracing data we want to check here - const envelopes = await getMultipleSentryEnvelopeRequests(page, 2, { url, timeout: 10000 }); + const envelopes = await getMultipleSentryEnvelopeRequests(page, 2, { url, timeout: 10000 }); const tracingEvent = envelopes[envelopes.length - 1]; // last envelope contains tracing data on all browsers const requestSpans = tracingEvent.spans?.filter(({ op }) => op === 'http.client'); diff --git a/dev-packages/browser-integration-tests/suites/tracing/request/xhr/test.ts b/dev-packages/browser-integration-tests/suites/tracing/request/xhr/test.ts index bd4ee0bbb003..3d329c9c5c6d 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/request/xhr/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/request/xhr/test.ts @@ -1,5 +1,5 @@ import { expect } from '@playwright/test'; -import type { SerializedEvent } from '@sentry/types'; +import type { Event } from '@sentry/types'; import { sentryTest } from '../../../../utils/fixtures'; import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers'; @@ -11,7 +11,7 @@ sentryTest('should create spans for multiple XHR requests', async ({ getLocalTes const url = await getLocalTestPath({ testDir: __dirname }); - const eventData = await getFirstSentryEnvelopeRequest(page, url); + const eventData = await getFirstSentryEnvelopeRequest(page, url); const requestSpans = eventData.spans?.filter(({ op }) => op === 'http.client'); expect(requestSpans).toHaveLength(3); diff --git a/dev-packages/e2e-tests/test-applications/angular-17/event-proxy-server.ts b/dev-packages/e2e-tests/test-applications/angular-17/event-proxy-server.ts index 2a4dc2b525d9..d14ca5cb5e72 100644 --- a/dev-packages/e2e-tests/test-applications/angular-17/event-proxy-server.ts +++ b/dev-packages/e2e-tests/test-applications/angular-17/event-proxy-server.ts @@ -6,7 +6,7 @@ import * as os from 'os'; import * as path from 'path'; import * as util from 'util'; import * as zlib from 'zlib'; -import type { Envelope, EnvelopeItem, SerializedEvent } from '@sentry/types'; +import type { Envelope, EnvelopeItem, Event } from '@sentry/types'; import { parseEnvelope } from '@sentry/utils'; const readFile = util.promisify(fs.readFile); @@ -210,13 +210,13 @@ export function waitForEnvelopeItem( export function waitForError( proxyServerName: string, - callback: (transactionEvent: SerializedEvent) => Promise | boolean, -): Promise { + callback: (transactionEvent: Event) => Promise | boolean, +): Promise { return new Promise((resolve, reject) => { waitForEnvelopeItem(proxyServerName, async envelopeItem => { const [envelopeItemHeader, envelopeItemBody] = envelopeItem; - if (envelopeItemHeader.type === 'event' && (await callback(envelopeItemBody as SerializedEvent))) { - resolve(envelopeItemBody as SerializedEvent); + if (envelopeItemHeader.type === 'event' && (await callback(envelopeItemBody as Event))) { + resolve(envelopeItemBody as Event); return true; } return false; @@ -226,13 +226,13 @@ export function waitForError( export function waitForTransaction( proxyServerName: string, - callback: (transactionEvent: SerializedEvent) => Promise | boolean, -): Promise { + callback: (transactionEvent: Event) => Promise | boolean, +): Promise { return new Promise((resolve, reject) => { waitForEnvelopeItem(proxyServerName, async envelopeItem => { const [envelopeItemHeader, envelopeItemBody] = envelopeItem; - if (envelopeItemHeader.type === 'transaction' && (await callback(envelopeItemBody as SerializedEvent))) { - resolve(envelopeItemBody as SerializedEvent); + if (envelopeItemHeader.type === 'transaction' && (await callback(envelopeItemBody as Event))) { + resolve(envelopeItemBody as Event); return true; } return false; diff --git a/dev-packages/e2e-tests/test-applications/node-experimental-fastify-app/event-proxy-server.ts b/dev-packages/e2e-tests/test-applications/node-experimental-fastify-app/event-proxy-server.ts index 2a4dc2b525d9..d14ca5cb5e72 100644 --- a/dev-packages/e2e-tests/test-applications/node-experimental-fastify-app/event-proxy-server.ts +++ b/dev-packages/e2e-tests/test-applications/node-experimental-fastify-app/event-proxy-server.ts @@ -6,7 +6,7 @@ import * as os from 'os'; import * as path from 'path'; import * as util from 'util'; import * as zlib from 'zlib'; -import type { Envelope, EnvelopeItem, SerializedEvent } from '@sentry/types'; +import type { Envelope, EnvelopeItem, Event } from '@sentry/types'; import { parseEnvelope } from '@sentry/utils'; const readFile = util.promisify(fs.readFile); @@ -210,13 +210,13 @@ export function waitForEnvelopeItem( export function waitForError( proxyServerName: string, - callback: (transactionEvent: SerializedEvent) => Promise | boolean, -): Promise { + callback: (transactionEvent: Event) => Promise | boolean, +): Promise { return new Promise((resolve, reject) => { waitForEnvelopeItem(proxyServerName, async envelopeItem => { const [envelopeItemHeader, envelopeItemBody] = envelopeItem; - if (envelopeItemHeader.type === 'event' && (await callback(envelopeItemBody as SerializedEvent))) { - resolve(envelopeItemBody as SerializedEvent); + if (envelopeItemHeader.type === 'event' && (await callback(envelopeItemBody as Event))) { + resolve(envelopeItemBody as Event); return true; } return false; @@ -226,13 +226,13 @@ export function waitForError( export function waitForTransaction( proxyServerName: string, - callback: (transactionEvent: SerializedEvent) => Promise | boolean, -): Promise { + callback: (transactionEvent: Event) => Promise | boolean, +): Promise { return new Promise((resolve, reject) => { waitForEnvelopeItem(proxyServerName, async envelopeItem => { const [envelopeItemHeader, envelopeItemBody] = envelopeItem; - if (envelopeItemHeader.type === 'transaction' && (await callback(envelopeItemBody as SerializedEvent))) { - resolve(envelopeItemBody as SerializedEvent); + if (envelopeItemHeader.type === 'transaction' && (await callback(envelopeItemBody as Event))) { + resolve(envelopeItemBody as Event); return true; } return false; diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/event-proxy-server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/event-proxy-server.ts index 2a4dc2b525d9..d14ca5cb5e72 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/event-proxy-server.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/event-proxy-server.ts @@ -6,7 +6,7 @@ import * as os from 'os'; import * as path from 'path'; import * as util from 'util'; import * as zlib from 'zlib'; -import type { Envelope, EnvelopeItem, SerializedEvent } from '@sentry/types'; +import type { Envelope, EnvelopeItem, Event } from '@sentry/types'; import { parseEnvelope } from '@sentry/utils'; const readFile = util.promisify(fs.readFile); @@ -210,13 +210,13 @@ export function waitForEnvelopeItem( export function waitForError( proxyServerName: string, - callback: (transactionEvent: SerializedEvent) => Promise | boolean, -): Promise { + callback: (transactionEvent: Event) => Promise | boolean, +): Promise { return new Promise((resolve, reject) => { waitForEnvelopeItem(proxyServerName, async envelopeItem => { const [envelopeItemHeader, envelopeItemBody] = envelopeItem; - if (envelopeItemHeader.type === 'event' && (await callback(envelopeItemBody as SerializedEvent))) { - resolve(envelopeItemBody as SerializedEvent); + if (envelopeItemHeader.type === 'event' && (await callback(envelopeItemBody as Event))) { + resolve(envelopeItemBody as Event); return true; } return false; @@ -226,13 +226,13 @@ export function waitForError( export function waitForTransaction( proxyServerName: string, - callback: (transactionEvent: SerializedEvent) => Promise | boolean, -): Promise { + callback: (transactionEvent: Event) => Promise | boolean, +): Promise { return new Promise((resolve, reject) => { waitForEnvelopeItem(proxyServerName, async envelopeItem => { const [envelopeItemHeader, envelopeItemBody] = envelopeItem; - if (envelopeItemHeader.type === 'transaction' && (await callback(envelopeItemBody as SerializedEvent))) { - resolve(envelopeItemBody as SerializedEvent); + if (envelopeItemHeader.type === 'transaction' && (await callback(envelopeItemBody as Event))) { + resolve(envelopeItemBody as Event); return true; } return false; diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/event-proxy-server.ts b/dev-packages/e2e-tests/test-applications/sveltekit/event-proxy-server.ts index 11f00b4a2426..eba9ffef8682 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/event-proxy-server.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/event-proxy-server.ts @@ -6,7 +6,7 @@ import * as os from 'os'; import * as path from 'path'; import * as util from 'util'; import * as zlib from 'zlib'; -import type { Envelope, EnvelopeItem, Event, SerializedEvent } from '@sentry/types'; +import type { Envelope, EnvelopeItem, Event } from '@sentry/types'; import { parseEnvelope } from '@sentry/utils'; const readFile = util.promisify(fs.readFile); @@ -226,13 +226,13 @@ export function waitForError( export function waitForTransaction( proxyServerName: string, - callback: (transactionEvent: SerializedEvent) => Promise | boolean, -): Promise { + callback: (transactionEvent: Event) => Promise | boolean, +): Promise { return new Promise((resolve, reject) => { waitForEnvelopeItem(proxyServerName, async envelopeItem => { const [envelopeItemHeader, envelopeItemBody] = envelopeItem; - if (envelopeItemHeader.type === 'transaction' && (await callback(envelopeItemBody as SerializedEvent))) { - resolve(envelopeItemBody as SerializedEvent); + if (envelopeItemHeader.type === 'transaction' && (await callback(envelopeItemBody as Event))) { + resolve(envelopeItemBody as Event); return true; } return false; diff --git a/dev-packages/e2e-tests/test-applications/vue-3/event-proxy-server.ts b/dev-packages/e2e-tests/test-applications/vue-3/event-proxy-server.ts index 2a4dc2b525d9..d14ca5cb5e72 100644 --- a/dev-packages/e2e-tests/test-applications/vue-3/event-proxy-server.ts +++ b/dev-packages/e2e-tests/test-applications/vue-3/event-proxy-server.ts @@ -6,7 +6,7 @@ import * as os from 'os'; import * as path from 'path'; import * as util from 'util'; import * as zlib from 'zlib'; -import type { Envelope, EnvelopeItem, SerializedEvent } from '@sentry/types'; +import type { Envelope, EnvelopeItem, Event } from '@sentry/types'; import { parseEnvelope } from '@sentry/utils'; const readFile = util.promisify(fs.readFile); @@ -210,13 +210,13 @@ export function waitForEnvelopeItem( export function waitForError( proxyServerName: string, - callback: (transactionEvent: SerializedEvent) => Promise | boolean, -): Promise { + callback: (transactionEvent: Event) => Promise | boolean, +): Promise { return new Promise((resolve, reject) => { waitForEnvelopeItem(proxyServerName, async envelopeItem => { const [envelopeItemHeader, envelopeItemBody] = envelopeItem; - if (envelopeItemHeader.type === 'event' && (await callback(envelopeItemBody as SerializedEvent))) { - resolve(envelopeItemBody as SerializedEvent); + if (envelopeItemHeader.type === 'event' && (await callback(envelopeItemBody as Event))) { + resolve(envelopeItemBody as Event); return true; } return false; @@ -226,13 +226,13 @@ export function waitForError( export function waitForTransaction( proxyServerName: string, - callback: (transactionEvent: SerializedEvent) => Promise | boolean, -): Promise { + callback: (transactionEvent: Event) => Promise | boolean, +): Promise { return new Promise((resolve, reject) => { waitForEnvelopeItem(proxyServerName, async envelopeItem => { const [envelopeItemHeader, envelopeItemBody] = envelopeItem; - if (envelopeItemHeader.type === 'transaction' && (await callback(envelopeItemBody as SerializedEvent))) { - resolve(envelopeItemBody as SerializedEvent); + if (envelopeItemHeader.type === 'transaction' && (await callback(envelopeItemBody as Event))) { + resolve(envelopeItemBody as Event); return true; } return false; diff --git a/packages/core/src/tracing/transaction.ts b/packages/core/src/tracing/transaction.ts index 3c0c114f1061..9f4194681338 100644 --- a/packages/core/src/tracing/transaction.ts +++ b/packages/core/src/tracing/transaction.ts @@ -276,8 +276,7 @@ export class Transaction extends SentrySpan implements TransactionInterface { // We don't want to override trace context trace: spanToTraceContext(this), }, - // TODO: Pass spans serialized via `spanToJSON()` here instead in v8. - spans: finishedSpans, + spans: finishedSpans.map(span => spanToJSON(span)), start_timestamp: this._startTime, // eslint-disable-next-line deprecation/deprecation tags: this.tags, diff --git a/packages/core/src/utils/prepareEvent.ts b/packages/core/src/utils/prepareEvent.ts index 006ef75a5f13..92cc5ffa65fa 100644 --- a/packages/core/src/utils/prepareEvent.ts +++ b/packages/core/src/utils/prepareEvent.ts @@ -16,7 +16,6 @@ import { getGlobalScope } from '../currentScopes'; import { getGlobalEventProcessors, notifyEventProcessors } from '../eventProcessors'; import { Scope } from '../scope'; import { applyScopeDataToEvent, mergeScopeData } from './applyScopeDataToEvent'; -import { spanToJSON } from './spanUtils'; /** * This type makes sure that we get either a CaptureContext, OR an EventHint. @@ -328,14 +327,12 @@ function normalizeEvent(event: Event | null, depth: number, maxBreadth: number): // event.spans[].data may contain circular/dangerous data so we need to normalize it if (event.spans) { normalized.spans = event.spans.map(span => { - const data = spanToJSON(span).data; - - if (data) { - // This is a bit weird, as we generally have `Span` instances here, but to be safe we do not assume so - span.setAttributes(normalize(data, depth, maxBreadth)); - } - - return span; + return { + ...span, + ...(span.data && { + data: normalize(span.data, depth, maxBreadth), + }), + }; }); } diff --git a/packages/core/test/lib/base.test.ts b/packages/core/test/lib/base.test.ts index b48d3b0e5eec..7b097d1b8115 100644 --- a/packages/core/test/lib/base.test.ts +++ b/packages/core/test/lib/base.test.ts @@ -1,4 +1,4 @@ -import type { Client, Envelope, Event, Span, Transaction } from '@sentry/types'; +import type { Client, Envelope, Event, Transaction } from '@sentry/types'; import { SentryError, SyncPromise, dsnToString, logger } from '@sentry/utils'; import { @@ -897,22 +897,22 @@ describe('BaseClient', () => { { data: { _sentry_extra_metrics: { M1: { value: 1 }, M2: { value: 2 } } }, description: 'first-paint', - endTimestamp: 1591603196.637835, + timestamp: 1591603196.637835, op: 'paint', - parentSpanId: 'a3df84a60c2e4e76', - spanId: '9e15bf99fbe4bc80', - startTimestamp: 1591603196.637835, - traceId: '86f39e84263a4de99c326acab3bfe3bd', - } as unknown as Span, + parent_span_id: 'a3df84a60c2e4e76', + span_id: '9e15bf99fbe4bc80', + start_timestamp: 1591603196.637835, + trace_id: '86f39e84263a4de99c326acab3bfe3bd', + }, { description: 'first-contentful-paint', - endTimestamp: 1591603196.637835, + timestamp: 1591603196.637835, op: 'paint', - parentSpanId: 'a3df84a60c2e4e76', - spanId: 'aa554c1f506b0783', - startTimestamp: 1591603196.637835, - traceId: '86f39e84263a4de99c326acab3bfe3bd', - } as any as Span, + parent_span_id: 'a3df84a60c2e4e76', + span_id: 'aa554c1f506b0783', + start_timestamp: 1591603196.637835, + trace_id: '86f39e84263a4de99c326acab3bfe3bd', + }, ], start_timestamp: 1591603196.614865, timestamp: 1591603196.728485, diff --git a/packages/core/test/lib/tracing/trace.test.ts b/packages/core/test/lib/tracing/trace.test.ts index 7c4c92ccc8c8..37b72193d2be 100644 --- a/packages/core/test/lib/tracing/trace.test.ts +++ b/packages/core/test/lib/tracing/trace.test.ts @@ -324,7 +324,7 @@ describe('startSpan', () => { const normalizedTransactionEvents = transactionEvents.map(event => { return { ...event, - spans: event.spans?.map(span => ({ name: spanToJSON(span).description, id: span.spanContext().spanId })), + spans: event.spans?.map(span => ({ name: span.description, id: span.span_id })), sdkProcessingMetadata: { dynamicSamplingContext: event.sdkProcessingMetadata?.dynamicSamplingContext, }, @@ -603,7 +603,7 @@ describe('startSpanManual', () => { const normalizedTransactionEvents = transactionEvents.map(event => { return { ...event, - spans: event.spans?.map(span => ({ name: spanToJSON(span).description, id: span.spanContext().spanId })), + spans: event.spans?.map(span => ({ name: span.description, id: span.span_id })), sdkProcessingMetadata: { dynamicSamplingContext: event.sdkProcessingMetadata?.dynamicSamplingContext, }, @@ -810,7 +810,7 @@ describe('startInactiveSpan', () => { const normalizedTransactionEvents = transactionEvents.map(event => { return { ...event, - spans: event.spans?.map(span => ({ name: spanToJSON(span).description, id: span.spanContext().spanId })), + spans: event.spans?.map(span => ({ name: span.description, id: span.span_id })), sdkProcessingMetadata: { dynamicSamplingContext: event.sdkProcessingMetadata?.dynamicSamplingContext, }, diff --git a/packages/ember/tests/helpers/utils.ts b/packages/ember/tests/helpers/utils.ts index 0833e80b0d8b..77ac48ebb516 100644 --- a/packages/ember/tests/helpers/utils.ts +++ b/packages/ember/tests/helpers/utils.ts @@ -1,4 +1,3 @@ -import { spanToJSON } from '@sentry/core'; import type { Event } from '@sentry/types'; const defaultAssertOptions = { @@ -68,16 +67,15 @@ export function assertSentryTransactions( // Also we ignore ui.long-task spans, as they are brittle and may or may not appear const filteredSpans = spans .filter(span => { - const op = spanToJSON(span).op; + const op = span.op; return !op?.startsWith('ui.ember.runloop.') && !op?.startsWith('ui.long-task'); }) - .map(s => { - const spanJson = spanToJSON(s); + .map(spanJson => { return `${spanJson.op} | ${spanJson.description}`; }); assert.true( - spans.some(span => spanToJSON(span).op?.startsWith('ui.ember.runloop.')), + spans.some(span => span.op?.startsWith('ui.ember.runloop.')), 'it captures runloop spans', ); assert.deepEqual(filteredSpans, options.spans, 'Has correct spans'); diff --git a/packages/node-experimental/test/integration/transactions.test.ts b/packages/node-experimental/test/integration/transactions.test.ts index fee0ed9b9072..aedde492cd63 100644 --- a/packages/node-experimental/test/integration/transactions.test.ts +++ b/packages/node-experimental/test/integration/transactions.test.ts @@ -1,6 +1,6 @@ import { TraceFlags, context, trace } from '@opentelemetry/api'; import type { SpanProcessor } from '@opentelemetry/sdk-trace-base'; -import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, spanToJSON } from '@sentry/core'; +import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core'; import { SentrySpanProcessor } from '@sentry/opentelemetry'; import type { TransactionEvent } from '@sentry/types'; import { logger } from '@sentry/utils'; @@ -141,7 +141,7 @@ describe('Integration | Transactions', () => { // note: Currently, spans do not have any context/span added to them // This is the same behavior as for the "regular" SDKs - expect(spans.map(span => spanToJSON(span))).toEqual([ + expect(spans).toEqual([ { data: { 'otel.kind': 'INTERNAL', @@ -559,7 +559,7 @@ describe('Integration | Transactions', () => { // note: Currently, spans do not have any context/span added to them // This is the same behavior as for the "regular" SDKs - expect(spans.map(span => spanToJSON(span))).toEqual([ + expect(spans).toEqual([ { data: { 'otel.kind': 'INTERNAL', diff --git a/packages/node/test/handlers.test.ts b/packages/node/test/handlers.test.ts index 3e65922faae1..861cfdf13259 100644 --- a/packages/node/test/handlers.test.ts +++ b/packages/node/test/handlers.test.ts @@ -487,7 +487,7 @@ describe('tracingHandler', () => { expect(finishTransaction).toHaveBeenCalled(); expect(spanToJSON(span).timestamp).toBeLessThanOrEqual(spanToJSON(transaction).timestamp!); expect(sentEvent.spans?.length).toEqual(1); - expect(sentEvent.spans?.[0].spanContext().spanId).toEqual(span.spanContext().spanId); + expect(sentEvent.spans?.[0].span_id).toEqual(span.spanContext().spanId); done(); }); }); diff --git a/packages/node/test/performance.test.ts b/packages/node/test/performance.test.ts index 3ae10bb1f4a3..0d528e37f7e2 100644 --- a/packages/node/test/performance.test.ts +++ b/packages/node/test/performance.test.ts @@ -1,7 +1,6 @@ import { setAsyncContextStrategy, setCurrentClient, - spanToJSON, startInactiveSpan, startSpan, startSpanManual, @@ -82,7 +81,7 @@ describe('startSpan()', () => { const transactionEvent = await transactionEventPromise; - expect(spanToJSON(transactionEvent.spans?.[0] as any).description).toBe('second'); + expect(transactionEvent.spans?.[0].description).toBe('second'); }); }); @@ -154,7 +153,7 @@ describe('startSpanManual()', () => { const transactionEvent = await transactionEventPromise; - expect(spanToJSON(transactionEvent.spans?.[0] as any).description).toBe('second'); + expect(transactionEvent.spans?.[0].description).toBe('second'); }); it('should use the scopes at time of creation instead of the scopes at time of termination', async () => { diff --git a/packages/opentelemetry/test/integration/transactions.test.ts b/packages/opentelemetry/test/integration/transactions.test.ts index bbcbf7afa35e..99d46abad4f9 100644 --- a/packages/opentelemetry/test/integration/transactions.test.ts +++ b/packages/opentelemetry/test/integration/transactions.test.ts @@ -7,7 +7,6 @@ import type { Event, TransactionEvent } from '@sentry/types'; import { logger } from '@sentry/utils'; import { TraceState } from '@opentelemetry/core'; -import { spanToJSON } from '@sentry/core'; import { SENTRY_TRACE_STATE_DSC } from '../../src/constants'; import { SentrySpanProcessor } from '../../src/spanProcessor'; import { startInactiveSpan, startSpan } from '../../src/trace'; @@ -145,7 +144,7 @@ describe('Integration | Transactions', () => { // note: Currently, spans do not have any context/span added to them // This is the same behavior as for the "regular" SDKs - expect(spans.map(span => spanToJSON(span))).toEqual([ + expect(spans).toEqual([ { data: { 'otel.kind': 'INTERNAL', @@ -406,7 +405,7 @@ describe('Integration | Transactions', () => { // note: Currently, spans do not have any context/span added to them // This is the same behavior as for the "regular" SDKs - expect(spans.map(span => spanToJSON(span))).toEqual([ + expect(spans).toEqual([ { data: { 'otel.kind': 'INTERNAL', diff --git a/packages/opentelemetry/test/trace.test.ts b/packages/opentelemetry/test/trace.test.ts index b71a5a15064e..2a6b9f6c3426 100644 --- a/packages/opentelemetry/test/trace.test.ts +++ b/packages/opentelemetry/test/trace.test.ts @@ -11,7 +11,6 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, getClient, getCurrentScope, - spanToJSON, withScope, } from '@sentry/core'; import type { Event, Scope } from '@sentry/types'; @@ -337,7 +336,7 @@ describe('trace', () => { const normalizedTransactionEvents = transactionEvents.map(event => { return { ...event, - spans: event.spans?.map(span => ({ name: spanToJSON(span).description, id: span.spanContext().spanId })), + spans: event.spans?.map(span => ({ name: span.description, id: span.span_id })), }; }); @@ -579,7 +578,7 @@ describe('trace', () => { const normalizedTransactionEvents = transactionEvents.map(event => { return { ...event, - spans: event.spans?.map(span => ({ name: spanToJSON(span).description, id: span.spanContext().spanId })), + spans: event.spans?.map(span => ({ name: span.description, id: span.span_id })), }; }); @@ -850,7 +849,7 @@ describe('trace', () => { const normalizedTransactionEvents = transactionEvents.map(event => { return { ...event, - spans: event.spans?.map(span => ({ name: spanToJSON(span).description, id: span.spanContext().spanId })), + spans: event.spans?.map(span => ({ name: span.description, id: span.span_id })), }; }); diff --git a/packages/svelte/test/performance.test.ts b/packages/svelte/test/performance.test.ts index 8e7357da044e..dd8baea00637 100644 --- a/packages/svelte/test/performance.test.ts +++ b/packages/svelte/test/performance.test.ts @@ -1,13 +1,5 @@ import { act, render } from '@testing-library/svelte'; -import { - addTracingExtensions, - getClient, - getCurrentScope, - getIsolationScope, - init, - spanToJSON, - startSpan, -} from '../src'; +import { addTracingExtensions, getClient, getCurrentScope, getIsolationScope, init, startSpan } from '../src'; import type { TransactionEvent } from '@sentry/types'; import { vi } from 'vitest'; @@ -56,9 +48,9 @@ describe('Sentry.trackComponent()', () => { const rootSpanId = transaction.contexts?.trace?.span_id; expect(rootSpanId).toBeDefined(); - const initSpanId = transaction.spans![0].spanContext().spanId; + const initSpanId = transaction.spans![0].span_id; - expect(spanToJSON(transaction.spans![0])).toEqual({ + expect(transaction.spans![0]).toEqual({ data: { 'sentry.op': 'ui.svelte.init', 'sentry.origin': 'auto.ui.svelte', @@ -73,7 +65,7 @@ describe('Sentry.trackComponent()', () => { trace_id: expect.any(String), }); - expect(spanToJSON(transaction.spans![1])).toEqual({ + expect(transaction.spans![1]).toEqual({ data: { 'sentry.op': 'ui.svelte.update', 'sentry.origin': 'auto.ui.svelte', @@ -111,9 +103,9 @@ describe('Sentry.trackComponent()', () => { const rootSpanId = transaction.contexts?.trace?.span_id; expect(rootSpanId).toBeDefined(); - const initSpanId = transaction.spans![0].spanContext().spanId; + const initSpanId = transaction.spans![0].span_id; - expect(spanToJSON(transaction.spans![0])).toEqual({ + expect(transaction.spans![0]).toEqual({ data: { 'sentry.op': 'ui.svelte.init', 'sentry.origin': 'auto.ui.svelte', @@ -128,7 +120,7 @@ describe('Sentry.trackComponent()', () => { trace_id: expect.any(String), }); - expect(spanToJSON(transaction.spans![1])).toEqual({ + expect(transaction.spans![1]).toEqual({ data: { 'sentry.op': 'ui.svelte.update', 'sentry.origin': 'auto.ui.svelte', @@ -143,7 +135,7 @@ describe('Sentry.trackComponent()', () => { trace_id: expect.any(String), }); - expect(spanToJSON(transaction.spans![2])).toEqual({ + expect(transaction.spans![2]).toEqual({ data: { 'sentry.op': 'ui.svelte.update', 'sentry.origin': 'auto.ui.svelte', @@ -172,7 +164,7 @@ describe('Sentry.trackComponent()', () => { const transaction = transactions[0]; expect(transaction.spans).toHaveLength(1); - expect(spanToJSON(transaction.spans![0]).op).toEqual('ui.svelte.init'); + expect(transaction.spans![0].op).toEqual('ui.svelte.init'); }); it('only creates update spans if trackInit is deactivated', async () => { @@ -188,7 +180,7 @@ describe('Sentry.trackComponent()', () => { const transaction = transactions[0]; expect(transaction.spans).toHaveLength(1); - expect(spanToJSON(transaction.spans![0]).op).toEqual('ui.svelte.update'); + expect(transaction.spans![0].op).toEqual('ui.svelte.update'); }); it('creates no spans if trackInit and trackUpdates are deactivated', async () => { @@ -220,8 +212,8 @@ describe('Sentry.trackComponent()', () => { const transaction = transactions[0]; expect(transaction.spans).toHaveLength(2); - expect(spanToJSON(transaction.spans![0]).description).toEqual(''); - expect(spanToJSON(transaction.spans![1]).description).toEqual(''); + expect(transaction.spans![0].description).toEqual(''); + expect(transaction.spans![1].description).toEqual(''); }); it("doesn't do anything, if there's no ongoing transaction", async () => { @@ -253,7 +245,7 @@ describe('Sentry.trackComponent()', () => { // One update span is triggered by the initial rendering, but the second one is not captured expect(transaction.spans).toHaveLength(2); - expect(spanToJSON(transaction.spans![0]).op).toEqual('ui.svelte.init'); - expect(spanToJSON(transaction.spans![1]).op).toEqual('ui.svelte.update'); + expect(transaction.spans![0].op).toEqual('ui.svelte.init'); + expect(transaction.spans![1].op).toEqual('ui.svelte.update'); }); }); diff --git a/packages/types/src/event.ts b/packages/types/src/event.ts index b64a9e4b1ef4..37146c674f52 100644 --- a/packages/types/src/event.ts +++ b/packages/types/src/event.ts @@ -11,7 +11,7 @@ import type { Request } from './request'; import type { CaptureContext } from './scope'; import type { SdkInfo } from './sdkinfo'; import type { SeverityLevel } from './severity'; -import type { MetricSummary, Span, SpanJSON } from './span'; +import type { MetricSummary, SpanJSON } from './span'; import type { Thread } from './thread'; import type { TransactionSource } from './transaction'; import type { User } from './user'; @@ -47,7 +47,7 @@ export interface Event { extra?: Extras; user?: User; type?: EventType; - spans?: Span[]; + spans?: Partial[]; measurements?: Measurements; debug_meta?: DebugMeta; // A place to stash data which is needed at some point in the SDK's event processing pipeline but which shouldn't get sent to Sentry @@ -86,14 +86,3 @@ export interface EventHint { data?: any; integrations?: string[]; } - -/** - * Represents the event that's sent in an event envelope, omitting interfaces that are no longer representative after - * event serialization. - */ -export interface SerializedEvent extends Omit { - /** - * POJO objects of spans belonging to this event. - */ - spans?: SpanJSON[]; -} diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 0034935e7201..6a2216587a7f 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -47,7 +47,7 @@ export type { ProfileItem, } from './envelope'; export type { ExtendedError } from './error'; -export type { Event, EventHint, EventType, ErrorEvent, TransactionEvent, SerializedEvent } from './event'; +export type { Event, EventHint, EventType, ErrorEvent, TransactionEvent } from './event'; export type { EventProcessor } from './eventprocessor'; export type { Exception } from './exception'; export type { Extra, Extras } from './extra';