diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts index 15c5adee2cc4..9957e290acf5 100644 --- a/packages/browser/src/index.ts +++ b/packages/browser/src/index.ts @@ -79,9 +79,4 @@ export { export type { SpanStatusType } from '@sentry/core'; export type { Span } from '@sentry/types'; export { makeBrowserOfflineTransport } from './transports/offline'; -export { onProfilingStartRouteTransaction } from './profiling/hubextensions'; -export { - // eslint-disable-next-line deprecation/deprecation - BrowserProfilingIntegration, - browserProfilingIntegration, -} from './profiling/integration'; +export { browserProfilingIntegration } from './profiling/integration'; diff --git a/packages/browser/src/profiling/integration.ts b/packages/browser/src/profiling/integration.ts index f9b924d9102c..5b6137e10027 100644 --- a/packages/browser/src/profiling/integration.ts +++ b/packages/browser/src/profiling/integration.ts @@ -1,10 +1,10 @@ -import { convertIntegrationFnToClass, defineIntegration, getCurrentScope } from '@sentry/core'; -import type { Client, EventEnvelope, Integration, IntegrationClass, IntegrationFn, Transaction } from '@sentry/types'; +import { defineIntegration, getCurrentScope } from '@sentry/core'; +import type { EventEnvelope, IntegrationFn, Transaction } from '@sentry/types'; import type { Profile } from '@sentry/types/src/profiling'; import { logger } from '@sentry/utils'; import { DEBUG_BUILD } from '../debug-build'; -import { startProfileForTransaction } from './hubextensions'; +import { startProfileForTransaction } from './startProfileForTransaction'; import type { ProfiledEvent } from './utils'; import { addProfilesToEnvelope, @@ -97,22 +97,3 @@ const _browserProfilingIntegration = (() => { }) satisfies IntegrationFn; export const browserProfilingIntegration = defineIntegration(_browserProfilingIntegration); - -/** - * Browser profiling integration. Stores any event that has contexts["profile"]["profile_id"] - * This exists because we do not want to await async profiler.stop calls as transaction.finish is called - * in a synchronous context. Instead, we handle sending the profile async from the promise callback and - * rely on being able to pull the event from the cache when we need to construct the envelope. This makes the - * integration less reliable as we might be dropping profiles when the cache is full. - * - * @experimental - * @deprecated Use `browserProfilingIntegration()` instead. - */ -// eslint-disable-next-line deprecation/deprecation -export const BrowserProfilingIntegration = convertIntegrationFnToClass( - INTEGRATION_NAME, - browserProfilingIntegration, -) as IntegrationClass void }>; - -// eslint-disable-next-line deprecation/deprecation -export type BrowserProfilingIntegration = typeof BrowserProfilingIntegration; diff --git a/packages/browser/src/profiling/hubextensions.ts b/packages/browser/src/profiling/startProfileForTransaction.ts similarity index 89% rename from packages/browser/src/profiling/hubextensions.ts rename to packages/browser/src/profiling/startProfileForTransaction.ts index 9fd156a1b90b..7d62cd8b1c46 100644 --- a/packages/browser/src/profiling/hubextensions.ts +++ b/packages/browser/src/profiling/startProfileForTransaction.ts @@ -1,4 +1,3 @@ -/* eslint-disable complexity */ import { spanToJSON } from '@sentry/core'; import type { Transaction } from '@sentry/types'; import { logger, timestampInSeconds, uuid4 } from '@sentry/utils'; @@ -10,32 +9,9 @@ import { MAX_PROFILE_DURATION_MS, addProfileToGlobalCache, isAutomatedPageLoadTransaction, - shouldProfileTransaction, startJSSelfProfile, } from './utils'; -/** - * Safety wrapper for startTransaction for the unlikely case that transaction starts before tracing is imported - - * if that happens we want to avoid throwing an error from profiling code. - * see https://github.com/getsentry/sentry-javascript/issues/4731. - * - * @experimental - */ -export function onProfilingStartRouteTransaction(transaction: Transaction | undefined): Transaction | undefined { - if (!transaction) { - if (DEBUG_BUILD) { - logger.log('[Profiling] Transaction is undefined, skipping profiling'); - } - return transaction; - } - - if (shouldProfileTransaction(transaction)) { - return startProfileForTransaction(transaction); - } - - return transaction; -} - /** * Wraps startTransaction and stopTransaction with profiling related logic. * startProfileForTransaction is called after the call to startTransaction in order to avoid our own code from diff --git a/packages/browser/test/unit/profiling/hubextensions.test.ts b/packages/browser/test/unit/profiling/hubextensions.test.ts deleted file mode 100644 index 362379b3f224..000000000000 --- a/packages/browser/test/unit/profiling/hubextensions.test.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { TextDecoder, TextEncoder } from 'util'; -// @ts-expect-error patch the encoder on the window, else importing JSDOM fails (deleted in afterAll) -const patchedEncoder = (!global.window.TextEncoder && (global.window.TextEncoder = TextEncoder)) || true; -// @ts-expect-error patch the encoder on the window, else importing JSDOM fails (deleted in afterAll) -const patchedDecoder = (!global.window.TextDecoder && (global.window.TextDecoder = TextDecoder)) || true; - -import { setCurrentClient } from '@sentry/core'; -import type { Transaction } from '@sentry/types'; -import { JSDOM } from 'jsdom'; - -import { onProfilingStartRouteTransaction } from '../../../src'; - -// eslint-disable-next-line no-bitwise -const TraceFlagSampled = 0x1 << 0; - -// @ts-expect-error store a reference so we can reset it later -const globalDocument = global.document; -// @ts-expect-error store a reference so we can reset it later -const globalWindow = global.window; -// @ts-expect-error store a reference so we can reset it later -const globalLocation = global.location; - -describe('BrowserProfilingIntegration', () => { - beforeEach(() => { - const dom = new JSDOM(); - // @ts-expect-error need to override global document - global.document = dom.window.document; - // @ts-expect-error need to override global document - global.window = dom.window; - // @ts-expect-error need to override global document - global.location = dom.window.location; - - const client: any = { - getDsn() { - return {}; - }, - getTransport() { - return { - send() {}, - }; - }, - getOptions() { - return { - profilesSampleRate: 1, - }; - }, - }; - - setCurrentClient(client); - }); - - // Reset back to previous values - afterEach(() => { - // @ts-expect-error need to override global document - global.document = globalDocument; - // @ts-expect-error need to override global document - global.window = globalWindow; - // @ts-expect-error need to override global document - global.location = globalLocation; - }); - afterAll(() => { - // @ts-expect-error patch the encoder on the window, else importing JSDOM fails - patchedEncoder && delete global.window.TextEncoder; - // @ts-expect-error patch the encoder on the window, else importing JSDOM fails - patchedDecoder && delete global.window.TextDecoder; - }); - - it('does not throw if Profiler is not available', () => { - // @ts-expect-error force api to be undefined - global.window.Profiler = undefined; - // set sampled to true so that profiling does not early return - const mockTransaction = { - isRecording: () => true, - spanContext: () => ({ - traceId: '12345678901234567890123456789012', - spanId: '1234567890123456', - traceFlags: TraceFlagSampled, - }), - } as Transaction; - expect(() => onProfilingStartRouteTransaction(mockTransaction)).not.toThrow(); - }); - - it('does not throw if constructor throws', () => { - const spy = jest.fn(); - - class Profiler { - constructor() { - spy(); - throw new Error('Profiler constructor error'); - } - } - - // set sampled to true so that profiling does not early return - const mockTransaction = { - isRecording: () => true, - spanContext: () => ({ - traceId: '12345678901234567890123456789012', - spanId: '1234567890123456', - traceFlags: TraceFlagSampled, - }), - } as Transaction; - - // @ts-expect-error override with our own constructor - global.window.Profiler = Profiler; - expect(() => onProfilingStartRouteTransaction(mockTransaction)).not.toThrow(); - expect(spy).toHaveBeenCalled(); - }); -}); diff --git a/packages/browser/test/unit/profiling/integration.test.ts b/packages/browser/test/unit/profiling/integration.test.ts index 9394221b0e4b..fe95cd5ec83c 100644 --- a/packages/browser/test/unit/profiling/integration.test.ts +++ b/packages/browser/test/unit/profiling/integration.test.ts @@ -48,9 +48,9 @@ describe('BrowserProfilingIntegration', () => { const client = Sentry.getClient(); - // eslint-disable-next-line deprecation/deprecation - const currentTransaction = Sentry.getCurrentScope().getTransaction(); - expect(currentTransaction?.op).toBe('pageload'); + const currentTransaction = Sentry.getActiveSpan(); + expect(currentTransaction).toBeDefined(); + expect(Sentry.spanToJSON(currentTransaction!).op).toBe('pageload'); currentTransaction?.end(); await client?.flush(1000);