diff --git a/packages/angular/src/errorhandler.ts b/packages/angular/src/errorhandler.ts index ec7a735ab559..b22536307e9a 100644 --- a/packages/angular/src/errorhandler.ts +++ b/packages/angular/src/errorhandler.ts @@ -118,7 +118,7 @@ class SentryErrorHandler implements AngularErrorHandler { if (this._options.showDialog) { const client = Sentry.getClient(); - if (client && client.on && !this._registeredAfterSendEventHandler) { + if (client && !this._registeredAfterSendEventHandler) { client.on('afterSendEvent', (event: Event) => { if (!event.type) { // eslint-disable-next-line deprecation/deprecation @@ -128,7 +128,7 @@ class SentryErrorHandler implements AngularErrorHandler { // We only want to register this hook once in the lifetime of the error handler this._registeredAfterSendEventHandler = true; - } else if (!client || !client.on) { + } else if (!client) { Sentry.showReportDialog({ ...this._options.dialogOptions, eventId }); } } diff --git a/packages/browser/src/integrations/breadcrumbs.ts b/packages/browser/src/integrations/breadcrumbs.ts index 1cbd8321346e..0fb305767414 100644 --- a/packages/browser/src/integrations/breadcrumbs.ts +++ b/packages/browser/src/integrations/breadcrumbs.ts @@ -88,7 +88,7 @@ const _breadcrumbsIntegration = ((options: Partial = {}) => if (_options.history) { addHistoryInstrumentationHandler(_getHistoryBreadcrumbHandler(client)); } - if (_options.sentry && client.on) { + if (_options.sentry) { client.on('beforeSendEvent', _getSentryBreadcrumbHandler(client)); } }, diff --git a/packages/browser/src/profiling/integration.ts b/packages/browser/src/profiling/integration.ts index bf8e56a626b5..1c076e09b17d 100644 --- a/packages/browser/src/profiling/integration.ts +++ b/packages/browser/src/profiling/integration.ts @@ -35,11 +35,6 @@ const _browserProfilingIntegration = (() => { } } - if (typeof client.on !== 'function') { - logger.warn('[Profiling] Client does not support hooks, profiling will be disabled'); - return; - } - client.on('startTransaction', (transaction: Transaction) => { if (shouldProfileTransaction(transaction)) { startProfileForTransaction(transaction); diff --git a/packages/core/src/hub.ts b/packages/core/src/hub.ts index 6c46e7c427fa..329e0c957a77 100644 --- a/packages/core/src/hub.ts +++ b/packages/core/src/hub.ts @@ -419,9 +419,7 @@ export class Hub implements HubInterface { if (finalBreadcrumb === null) return; - if (client.emit) { - client.emit('beforeAddBreadcrumb', finalBreadcrumb, hint); - } + client.emit('beforeAddBreadcrumb', finalBreadcrumb, hint); // TODO(v8): I know this comment doesn't make much sense because the hub will be deprecated but I still wanted to // write it down. In theory, we would have to add the breadcrumbs to the isolation scope here, however, that would diff --git a/packages/core/src/integration.ts b/packages/core/src/integration.ts index 8a91fa10e303..c95dce4b2f79 100644 --- a/packages/core/src/integration.ts +++ b/packages/core/src/integration.ts @@ -140,7 +140,7 @@ export function setupIntegration(client: Client, integration: Integration, integ integration.setup(client); } - if (client.on && typeof integration.preprocessEvent === 'function') { + if (typeof integration.preprocessEvent === 'function') { const callback = integration.preprocessEvent.bind(integration) as typeof integration.preprocessEvent; client.on('preprocessEvent', (event, hint) => callback(event, hint, client)); } diff --git a/packages/core/src/integrations/metadata.ts b/packages/core/src/integrations/metadata.ts index d4e48620d726..3d5b89e07d2e 100644 --- a/packages/core/src/integrations/metadata.ts +++ b/packages/core/src/integrations/metadata.ts @@ -12,10 +12,6 @@ const _moduleMetadataIntegration = (() => { // TODO v8: Remove this setupOnce() {}, // eslint-disable-line @typescript-eslint/no-empty-function setup(client) { - if (typeof client.on !== 'function') { - return; - } - // We need to strip metadata from stack frames before sending them to Sentry since these are client side only. client.on('beforeEnvelope', envelope => { forEachEnvelopeItem(envelope, (item, type) => { diff --git a/packages/core/src/tracing/dynamicSamplingContext.ts b/packages/core/src/tracing/dynamicSamplingContext.ts index 93acfe77d10a..d7fe3872b42f 100644 --- a/packages/core/src/tracing/dynamicSamplingContext.ts +++ b/packages/core/src/tracing/dynamicSamplingContext.ts @@ -23,7 +23,7 @@ export function getDynamicSamplingContextFromClient(trace_id: string, client: Cl trace_id, }) as DynamicSamplingContext; - client.emit && client.emit('createDsc', dsc); + client.emit('createDsc', dsc); return dsc; } @@ -81,7 +81,7 @@ export function getDynamicSamplingContextFromSpan(span: Span): Readonly { traceId: '86f39e84263a4de99c326acab3bfe3bd', } as Transaction; - client.on?.('startTransaction', transaction => { + client.on('startTransaction', transaction => { expect(transaction).toEqual(mockTransaction); }); - client.emit?.('startTransaction', mockTransaction); + client.emit('startTransaction', mockTransaction); }); it('should call a beforeEnvelope hook', () => { @@ -1974,11 +1974,11 @@ describe('BaseClient', () => { {}, ] as Envelope; - client.on?.('beforeEnvelope', envelope => { + client.on('beforeEnvelope', envelope => { expect(envelope).toEqual(mockEnvelope); }); - client.emit?.('beforeEnvelope', mockEnvelope); + client.emit('beforeEnvelope', mockEnvelope); }); }); }); diff --git a/packages/feedback/src/util/prepareFeedbackEvent.ts b/packages/feedback/src/util/prepareFeedbackEvent.ts index cb48efeaf89d..312b6252a9e0 100644 --- a/packages/feedback/src/util/prepareFeedbackEvent.ts +++ b/packages/feedback/src/util/prepareFeedbackEvent.ts @@ -17,9 +17,7 @@ export async function prepareFeedbackEvent({ event, }: PrepareFeedbackEventParams): Promise { const eventHint = {}; - if (client.emit) { - client.emit('preprocessEvent', event, eventHint); - } + client.emit('preprocessEvent', event, eventHint); const preparedEvent = (await prepareEvent( client.getOptions(), diff --git a/packages/feedback/src/util/sendFeedbackRequest.ts b/packages/feedback/src/util/sendFeedbackRequest.ts index f1629a00670a..d8f3a880ba2c 100644 --- a/packages/feedback/src/util/sendFeedbackRequest.ts +++ b/packages/feedback/src/util/sendFeedbackRequest.ts @@ -51,9 +51,7 @@ export async function sendFeedbackRequest( return; } - if (client.emit) { - client.emit('beforeSendFeedback', feedbackEvent, { includeReplay: Boolean(includeReplay) }); - } + client.emit('beforeSendFeedback', feedbackEvent, { includeReplay: Boolean(includeReplay) }); const envelope = createEventEnvelope(feedbackEvent, dsn, client.getOptions()._metadata, client.getOptions().tunnel); diff --git a/packages/integrations/src/debug.ts b/packages/integrations/src/debug.ts index 3e76353688d3..7c23cba9ae57 100644 --- a/packages/integrations/src/debug.ts +++ b/packages/integrations/src/debug.ts @@ -23,10 +23,6 @@ const _debugIntegration = ((options: DebugOptions = {}) => { // TODO v8: Remove this setupOnce() {}, // eslint-disable-line @typescript-eslint/no-empty-function setup(client) { - if (!client.on) { - return; - } - client.on('beforeSendEvent', (event: Event, hint?: EventHint) => { if (_options.debugger) { // eslint-disable-next-line no-debugger diff --git a/packages/node-experimental/src/sdk/api.ts b/packages/node-experimental/src/sdk/api.ts index 83685fe6d987..c4b0c397ea43 100644 --- a/packages/node-experimental/src/sdk/api.ts +++ b/packages/node-experimental/src/sdk/api.ts @@ -134,9 +134,7 @@ export function addBreadcrumb(breadcrumb: Breadcrumb, hint?: BreadcrumbHint): vo if (finalBreadcrumb === null) return; - if (client.emit) { - client.emit('beforeAddBreadcrumb', finalBreadcrumb, hint); - } + client.emit('beforeAddBreadcrumb', finalBreadcrumb, hint); getIsolationScope().addBreadcrumb(finalBreadcrumb, maxBreadcrumbs); } diff --git a/packages/node/src/integrations/spotlight.ts b/packages/node/src/integrations/spotlight.ts index 52b8941daa71..bf72f653f58c 100644 --- a/packages/node/src/integrations/spotlight.ts +++ b/packages/node/src/integrations/spotlight.ts @@ -65,11 +65,6 @@ function connectToSpotlight(client: Client, options: Required { if (failedRequests > 3) { logger.warn('[Spotlight] Disabled Sentry -> Spotlight integration due to too many failed requests'); diff --git a/packages/node/test/integrations/spotlight.test.ts b/packages/node/test/integrations/spotlight.test.ts index 756170d89518..a892677d0dd0 100644 --- a/packages/node/test/integrations/spotlight.test.ts +++ b/packages/node/test/integrations/spotlight.test.ts @@ -120,16 +120,6 @@ describe('Spotlight', () => { integration.setup!(client); expect(loggerSpy).toHaveBeenCalledWith(expect.stringContaining('Invalid sidecar URL: invalid-url')); }); - - it("the client doesn't support life cycle hooks", () => { - const integration = spotlightIntegration({ sidecarUrl: 'http://mylocalhost:8969' }); - const clientWithoutHooks = { ...client }; - // @ts-expect-error - this is fine in tests - delete client.on; - // @ts-expect-error - this is fine in tests - integration.setup(clientWithoutHooks); - expect(loggerSpy).toHaveBeenCalledWith(expect.stringContaining(' missing method on SDK client (`client.on`)')); - }); }); it('warns if the NODE_ENV variable doesn\'t equal "development"', () => { diff --git a/packages/opentelemetry-node/src/spanprocessor.ts b/packages/opentelemetry-node/src/spanprocessor.ts index d14d77010422..9996fc73111f 100644 --- a/packages/opentelemetry-node/src/spanprocessor.ts +++ b/packages/opentelemetry-node/src/spanprocessor.ts @@ -114,7 +114,7 @@ export class SentrySpanProcessor implements OtelSpanProcessor { const client = getClient(); const mutableOptions = { drop: false }; - client && client.emit && client?.emit('otelSpanEnd', otelSpan, mutableOptions); + client && client.emit('otelSpanEnd', otelSpan, mutableOptions); if (mutableOptions.drop) { clearSpan(otelSpanId); diff --git a/packages/opentelemetry-node/test/propagator.test.ts b/packages/opentelemetry-node/test/propagator.test.ts index 494b3aff7f07..c723b5bc6f0b 100644 --- a/packages/opentelemetry-node/test/propagator.test.ts +++ b/packages/opentelemetry-node/test/propagator.test.ts @@ -45,6 +45,7 @@ describe('SentryPropagator', () => { getDsn: () => ({ publicKey: 'abc', }), + emit: () => {}, }; // @ts-expect-error Use mock client for unit tests // eslint-disable-next-line deprecation/deprecation diff --git a/packages/opentelemetry/src/custom/transaction.ts b/packages/opentelemetry/src/custom/transaction.ts index ceb950bc610d..31b2efe31d03 100644 --- a/packages/opentelemetry/src/custom/transaction.ts +++ b/packages/opentelemetry/src/custom/transaction.ts @@ -17,7 +17,7 @@ export function startTransaction(hub: HubInterface, transactionContext: Transact // Any sampling decision happens in OpenTelemetry's sampler transaction.initSpanRecorder(options._experiments && (options._experiments.maxSpans as number)); - if (client && client.emit) { + if (client) { client.emit('startTransaction', transaction); } return transaction; diff --git a/packages/opentelemetry/test/propagator.test.ts b/packages/opentelemetry/test/propagator.test.ts index 012542d47e35..fc67f4bb3030 100644 --- a/packages/opentelemetry/test/propagator.test.ts +++ b/packages/opentelemetry/test/propagator.test.ts @@ -39,6 +39,7 @@ describe('SentryPropagator', () => { getDsn: () => ({ publicKey: 'abc', }), + emit: () => {}, }; // @ts-expect-error Use mock client for unit tests diff --git a/packages/react/src/errorboundary.tsx b/packages/react/src/errorboundary.tsx index d120c9b44dfb..c521c0204393 100644 --- a/packages/react/src/errorboundary.tsx +++ b/packages/react/src/errorboundary.tsx @@ -108,7 +108,7 @@ class ErrorBoundary extends React.Component { if (!event.type && this._lastEventId && event.event_id === this._lastEventId) { diff --git a/packages/replay/src/coreHandlers/handleBreadcrumbs.ts b/packages/replay/src/coreHandlers/handleBreadcrumbs.ts index 416bca4efb15..034e5cdb05af 100644 --- a/packages/replay/src/coreHandlers/handleBreadcrumbs.ts +++ b/packages/replay/src/coreHandlers/handleBreadcrumbs.ts @@ -16,7 +16,7 @@ type BreadcrumbWithCategory = Required>; export function handleBreadcrumbs(replay: ReplayContainer): void { const client = getClient(); - if (!client || !client.on) { + if (!client) { return; } diff --git a/packages/replay/src/coreHandlers/handleFetch.ts b/packages/replay/src/coreHandlers/handleFetch.ts deleted file mode 100644 index 54681c2871c0..000000000000 --- a/packages/replay/src/coreHandlers/handleFetch.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { HandlerDataFetch } from '@sentry/types'; - -import type { NetworkRequestData, ReplayContainer, ReplayPerformanceEntry } from '../types'; -import { addNetworkBreadcrumb } from './util/addNetworkBreadcrumb'; - -/** only exported for tests */ -export function handleFetch(handlerData: HandlerDataFetch): null | ReplayPerformanceEntry { - const { startTimestamp, endTimestamp, fetchData, response } = handlerData; - - if (!endTimestamp) { - return null; - } - - // This is only used as a fallback, so we know the body sizes are never set here - const { method, url } = fetchData; - - return { - type: 'resource.fetch', - start: startTimestamp / 1000, - end: endTimestamp / 1000, - name: url, - data: { - method, - statusCode: response ? (response as Response).status : undefined, - }, - }; -} - -/** - * Returns a listener to be added to `addFetchInstrumentationHandler(listener)`. - */ -export function handleFetchSpanListener(replay: ReplayContainer): (handlerData: HandlerDataFetch) => void { - return (handlerData: HandlerDataFetch) => { - if (!replay.isEnabled()) { - return; - } - - const result = handleFetch(handlerData); - - addNetworkBreadcrumb(replay, result); - }; -} diff --git a/packages/replay/src/coreHandlers/handleGlobalEvent.ts b/packages/replay/src/coreHandlers/handleGlobalEvent.ts index 39983a85d72e..88651d449fe6 100644 --- a/packages/replay/src/coreHandlers/handleGlobalEvent.ts +++ b/packages/replay/src/coreHandlers/handleGlobalEvent.ts @@ -5,19 +5,13 @@ import { DEBUG_BUILD } from '../debug-build'; import type { ReplayContainer } from '../types'; import { isErrorEvent, isFeedbackEvent, isReplayEvent, isTransactionEvent } from '../util/eventUtils'; import { isRrwebError } from '../util/isRrwebError'; -import { handleAfterSendEvent } from './handleAfterSendEvent'; import { addFeedbackBreadcrumb } from './util/addFeedbackBreadcrumb'; import { shouldSampleForBufferEvent } from './util/shouldSampleForBufferEvent'; /** * Returns a listener to be added to `addEventProcessor(listener)`. */ -export function handleGlobalEventListener( - replay: ReplayContainer, - includeAfterSendEventHandling = false, -): (event: Event, hint: EventHint) => Event | null { - const afterSendHandler = includeAfterSendEventHandling ? handleAfterSendEvent(replay) : undefined; - +export function handleGlobalEventListener(replay: ReplayContainer): (event: Event, hint: EventHint) => Event | null { return Object.assign( (event: Event, hint: EventHint) => { // Do nothing if replay has been disabled @@ -73,13 +67,6 @@ export function handleGlobalEventListener( event.tags = { ...event.tags, replayId: replay.getSessionId() }; } - // In cases where a custom client is used that does not support the new hooks (yet), - // we manually call this hook method here - if (afterSendHandler) { - // Pretend the error had a 200 response so we always capture it - afterSendHandler(event, { statusCode: 200 }); - } - return event; }, { id: 'Replay' }, diff --git a/packages/replay/src/coreHandlers/handleNetworkBreadcrumbs.ts b/packages/replay/src/coreHandlers/handleNetworkBreadcrumbs.ts index 4a201ae9b65e..4acafd5ca207 100644 --- a/packages/replay/src/coreHandlers/handleNetworkBreadcrumbs.ts +++ b/packages/replay/src/coreHandlers/handleNetworkBreadcrumbs.ts @@ -6,12 +6,10 @@ import type { TextEncoderInternal, XhrBreadcrumbData, } from '@sentry/types'; -import { addFetchInstrumentationHandler, addXhrInstrumentationHandler, logger } from '@sentry/utils'; +import { logger } from '@sentry/utils'; import { DEBUG_BUILD } from '../debug-build'; import type { FetchHint, ReplayContainer, ReplayNetworkOptions, XhrHint } from '../types'; -import { handleFetchSpanListener } from './handleFetch'; -import { handleXhrSpanListener } from './handleXhr'; import { captureFetchBreadcrumbToReplay, enrichFetchBreadcrumb } from './util/fetchUtils'; import { captureXhrBreadcrumbToReplay, enrichXhrBreadcrumb } from './util/xhrUtils'; @@ -50,12 +48,8 @@ export function handleNetworkBreadcrumbs(replay: ReplayContainer): void { networkResponseHeaders, }; - if (client && client.on) { + if (client) { client.on('beforeAddBreadcrumb', (breadcrumb, hint) => beforeAddNetworkBreadcrumb(options, breadcrumb, hint)); - } else { - // Fallback behavior - addFetchInstrumentationHandler(handleFetchSpanListener(replay)); - addXhrInstrumentationHandler(handleXhrSpanListener(replay)); } } catch { // Do nothing diff --git a/packages/replay/src/coreHandlers/handleXhr.ts b/packages/replay/src/coreHandlers/handleXhr.ts deleted file mode 100644 index afe76411bdcf..000000000000 --- a/packages/replay/src/coreHandlers/handleXhr.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { HandlerDataXhr } from '@sentry/types'; -import { SENTRY_XHR_DATA_KEY } from '@sentry/utils'; - -import type { NetworkRequestData, ReplayContainer, ReplayPerformanceEntry } from '../types'; -import { addNetworkBreadcrumb } from './util/addNetworkBreadcrumb'; - -/** only exported for tests */ -export function handleXhr(handlerData: HandlerDataXhr): ReplayPerformanceEntry | null { - const { startTimestamp, endTimestamp, xhr } = handlerData; - - const sentryXhrData = xhr[SENTRY_XHR_DATA_KEY]; - - if (!startTimestamp || !endTimestamp || !sentryXhrData) { - return null; - } - - // This is only used as a fallback, so we know the body sizes are never set here - const { method, url, status_code: statusCode } = sentryXhrData; - - if (url === undefined) { - return null; - } - - return { - type: 'resource.xhr', - name: url, - start: startTimestamp / 1000, - end: endTimestamp / 1000, - data: { - method, - statusCode, - }, - }; -} - -/** - * Returns a listener to be added to `addXhrInstrumentationHandler(listener)`. - */ -export function handleXhrSpanListener(replay: ReplayContainer): (handlerData: HandlerDataXhr) => void { - return (handlerData: HandlerDataXhr) => { - if (!replay.isEnabled()) { - return; - } - - const result = handleXhr(handlerData); - - addNetworkBreadcrumb(replay, result); - }; -} diff --git a/packages/replay/src/util/addGlobalListeners.ts b/packages/replay/src/util/addGlobalListeners.ts index b3373924e1fa..797a6c3cfa96 100644 --- a/packages/replay/src/util/addGlobalListeners.ts +++ b/packages/replay/src/util/addGlobalListeners.ts @@ -1,6 +1,5 @@ -import type { BaseClient } from '@sentry/core'; import { addEventProcessor, getClient } from '@sentry/core'; -import type { Client, DynamicSamplingContext } from '@sentry/types'; +import type { DynamicSamplingContext } from '@sentry/types'; import { addClickKeypressInstrumentationHandler, addHistoryInstrumentationHandler } from '@sentry/utils'; import { handleAfterSendEvent } from '../coreHandlers/handleAfterSendEvent'; @@ -26,7 +25,7 @@ export function addGlobalListeners(replay: ReplayContainer): void { // Tag all (non replay) events that get sent to Sentry with the current // replay ID so that we can reference them later in the UI - const eventProcessor = handleGlobalEventListener(replay, !hasHooks(client)); + const eventProcessor = handleGlobalEventListener(replay); if (client && client.addEventProcessor) { client.addEventProcessor(eventProcessor); } else { @@ -34,7 +33,7 @@ export function addGlobalListeners(replay: ReplayContainer): void { } // If a custom client has no hooks yet, we continue to use the "old" implementation - if (hasHooks(client)) { + if (client) { client.on('beforeSendEvent', handleBeforeSendEvent(replay)); client.on('afterSendEvent', handleAfterSendEvent(replay)); client.on('createDsc', (dsc: DynamicSamplingContext) => { @@ -73,8 +72,3 @@ export function addGlobalListeners(replay: ReplayContainer): void { }); } } - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function hasHooks(client: Client | undefined): client is BaseClient { - return !!(client && client.on); -} diff --git a/packages/replay/src/util/prepareReplayEvent.ts b/packages/replay/src/util/prepareReplayEvent.ts index 65e190d29551..e564f0509326 100644 --- a/packages/replay/src/util/prepareReplayEvent.ts +++ b/packages/replay/src/util/prepareReplayEvent.ts @@ -24,9 +24,7 @@ export async function prepareReplayEvent({ const eventHint: EventHint = { event_id, integrations }; - if (client.emit) { - client.emit('preprocessEvent', event, eventHint); - } + client.emit('preprocessEvent', event, eventHint); const preparedEvent = (await prepareEvent( client.getOptions(), diff --git a/packages/replay/test/integration/coreHandlers/handleGlobalEvent.test.ts b/packages/replay/test/integration/coreHandlers/handleGlobalEvent.test.ts index a1ca45a8d76a..c383bc57dc83 100644 --- a/packages/replay/test/integration/coreHandlers/handleGlobalEvent.test.ts +++ b/packages/replay/test/integration/coreHandlers/handleGlobalEvent.test.ts @@ -146,7 +146,7 @@ describe('Integration | coreHandlers | handleGlobalEvent', () => { ); }); - it('does not collect errorIds when hooks are available', async () => { + it('does not collect errorIds', async () => { const error1 = Error({ event_id: 'err1' }); const error2 = Error({ event_id: 'err2' }); const error3 = Error({ event_id: 'err3' }); @@ -160,21 +160,7 @@ describe('Integration | coreHandlers | handleGlobalEvent', () => { expect(Array.from(replay.getContext().errorIds)).toEqual([]); }); - it('collects errorIds when hooks are not available', async () => { - const error1 = Error({ event_id: 'err1' }); - const error2 = Error({ event_id: 'err2' }); - const error3 = Error({ event_id: 'err3' }); - - const handler = handleGlobalEventListener(replay, true); - - handler(error1, {}); - handler(error2, {}); - handler(error3, {}); - - expect(Array.from(replay.getContext().errorIds)).toEqual(['err1', 'err2', 'err3']); - }); - - it('does not collect traceIds when hooks are available', async () => { + it('does not collect traceIds', async () => { const transaction1 = Transaction('tr1'); const transaction2 = Transaction('tr2'); const transaction3 = Transaction('tr3'); @@ -188,33 +174,16 @@ describe('Integration | coreHandlers | handleGlobalEvent', () => { expect(Array.from(replay.getContext().traceIds)).toEqual([]); }); - it('collects traceIds when hooks are not available', async () => { - const transaction1 = Transaction('tr1'); - const transaction2 = Transaction('tr2'); - const transaction3 = Transaction('tr3'); - - const handler = handleGlobalEventListener(replay, true); - - handler(transaction1, {}); - handler(transaction2, {}); - handler(transaction3, {}); - - expect(Array.from(replay.getContext().traceIds)).toEqual(['tr1', 'tr2', 'tr3']); - }); - it('ignores profile & replay events', async () => { const profileEvent: Event = { type: 'profile' }; const replayEvent: Event = { type: 'replay_event' }; const handler = handleGlobalEventListener(replay); - const handler2 = handleGlobalEventListener(replay, true); expect(replay.recordingMode).toBe('buffer'); handler(profileEvent, {}); handler(replayEvent, {}); - handler2(profileEvent, {}); - handler2(replayEvent, {}); expect(Array.from(replay.getContext().traceIds)).toEqual([]); expect(Array.from(replay.getContext().errorIds)).toEqual([]); diff --git a/packages/replay/test/unit/coreHandlers/handleFetch.test.ts b/packages/replay/test/unit/coreHandlers/handleFetch.test.ts deleted file mode 100644 index 3938b351d796..000000000000 --- a/packages/replay/test/unit/coreHandlers/handleFetch.test.ts +++ /dev/null @@ -1,64 +0,0 @@ -import type { HandlerDataFetch } from '@sentry/types'; - -import { handleFetch } from '../../../src/coreHandlers/handleFetch'; - -const DEFAULT_DATA: HandlerDataFetch = { - args: ['/api/0/organizations/sentry/', { method: 'GET', headers: {}, credentials: 'include' }] as Parameters< - typeof fetch - >, - endTimestamp: 15000, - fetchData: { - method: 'GET', - url: '/api/0/organizations/sentry/', - }, - response: { - type: 'basic', - url: '', - redirected: false, - status: 200, - ok: true, - } as Response, - startTimestamp: 10000, -}; - -describe('Unit | coreHandlers | handleFetch', () => { - it('formats fetch calls from core SDK to replay breadcrumbs', function () { - expect(handleFetch(DEFAULT_DATA)).toEqual({ - type: 'resource.fetch', - name: '/api/0/organizations/sentry/', - start: 10, - end: 15, - data: { - method: 'GET', - statusCode: 200, - }, - }); - }); - - it('ignores fetches that have not completed yet', function () { - const data = { - ...DEFAULT_DATA, - endTimestamp: undefined, - response: undefined, - }; - - expect(handleFetch(data)).toEqual(null); - }); - - // This cannot happen as of now, this test just shows the expected behavior - it('ignores request/response sizes', function () { - const data = { - ...DEFAULT_DATA, - fetchData: { - ...DEFAULT_DATA.fetchData, - request_body_size: 123, - response_body_size: 456, - }, - }; - - expect(handleFetch(data)?.data).toEqual({ - method: 'GET', - statusCode: 200, - }); - }); -}); diff --git a/packages/replay/test/unit/coreHandlers/handleXhr.test.ts b/packages/replay/test/unit/coreHandlers/handleXhr.test.ts deleted file mode 100644 index 84fdf2facfdf..000000000000 --- a/packages/replay/test/unit/coreHandlers/handleXhr.test.ts +++ /dev/null @@ -1,62 +0,0 @@ -import type { HandlerDataXhr, SentryWrappedXMLHttpRequest, SentryXhrData } from '@sentry/types'; -import { SENTRY_XHR_DATA_KEY } from '@sentry/utils'; - -import { handleXhr } from '../../../src/coreHandlers/handleXhr'; - -const DEFAULT_DATA: HandlerDataXhr = { - args: ['GET', '/api/0/organizations/sentry/'], - xhr: { - [SENTRY_XHR_DATA_KEY]: { - method: 'GET', - url: '/api/0/organizations/sentry/', - status_code: 200, - request_headers: {}, - }, - } as SentryWrappedXMLHttpRequest, - startTimestamp: 10000, - endTimestamp: 15000, -}; - -describe('Unit | coreHandlers | handleXhr', () => { - it('formats fetch calls from core SDK to replay breadcrumbs', function () { - expect(handleXhr(DEFAULT_DATA)).toEqual({ - type: 'resource.xhr', - name: '/api/0/organizations/sentry/', - start: 10, - end: 15, - data: { - method: 'GET', - statusCode: 200, - }, - }); - }); - - it('ignores xhr that have not completed yet', function () { - const data = { - ...DEFAULT_DATA, - endTimestamp: undefined, - }; - - expect(handleXhr(data)).toEqual(null); - }); - - // This cannot happen as of now, this test just shows the expected behavior - it('ignores request/response sizes', function () { - const data: HandlerDataXhr = { - ...DEFAULT_DATA, - xhr: { - ...DEFAULT_DATA.xhr, - [SENTRY_XHR_DATA_KEY]: { - ...(DEFAULT_DATA.xhr[SENTRY_XHR_DATA_KEY] as SentryXhrData), - request_body_size: 123, - response_body_size: 456, - }, - }, - }; - - expect(handleXhr(data)?.data).toEqual({ - method: 'GET', - statusCode: 200, - }); - }); -}); diff --git a/packages/sveltekit/test/client/browserTracingIntegration.test.ts b/packages/sveltekit/test/client/browserTracingIntegration.test.ts index 83984c0b19f5..0fcd8f3f1e46 100644 --- a/packages/sveltekit/test/client/browserTracingIntegration.test.ts +++ b/packages/sveltekit/test/client/browserTracingIntegration.test.ts @@ -58,7 +58,7 @@ describe('browserTracingIntegration', () => { }; }); - const fakeClient = { getOptions: () => undefined }; + const fakeClient = { getOptions: () => undefined, on: () => {} }; const mockedRoutingSpan = { end: () => {}, diff --git a/packages/tracing-internal/src/browser/browserTracingIntegration.ts b/packages/tracing-internal/src/browser/browserTracingIntegration.ts index 31660eff00a7..a521933c420e 100644 --- a/packages/tracing-internal/src/browser/browserTracingIntegration.ts +++ b/packages/tracing-internal/src/browser/browserTracingIntegration.ts @@ -309,27 +309,25 @@ export const browserTracingIntegration = ((_options: Partial { - if (activeSpan) { - DEBUG_BUILD && logger.log(`[Tracing] Finishing current transaction with op: ${spanToJSON(activeSpan).op}`); - // If there's an open transaction on the scope, we need to finish it before creating an new one. - activeSpan.end(); - } - activeSpan = _createRouteTransaction(context); - }); + client.on('startNavigationSpan', (context: StartSpanOptions) => { + if (activeSpan) { + DEBUG_BUILD && logger.log(`[Tracing] Finishing current transaction with op: ${spanToJSON(activeSpan).op}`); + // If there's an open transaction on the scope, we need to finish it before creating an new one. + activeSpan.end(); + } + activeSpan = _createRouteTransaction(context); + }); - client.on('startPageLoadSpan', (context: StartSpanOptions) => { - if (activeSpan) { - DEBUG_BUILD && logger.log(`[Tracing] Finishing current transaction with op: ${spanToJSON(activeSpan).op}`); - // If there's an open transaction on the scope, we need to finish it before creating an new one. - activeSpan.end(); - } - activeSpan = _createRouteTransaction(context); - }); - } + client.on('startPageLoadSpan', (context: StartSpanOptions) => { + if (activeSpan) { + DEBUG_BUILD && logger.log(`[Tracing] Finishing current transaction with op: ${spanToJSON(activeSpan).op}`); + // If there's an open transaction on the scope, we need to finish it before creating an new one. + activeSpan.end(); + } + activeSpan = _createRouteTransaction(context); + }); - if (options.instrumentPageLoad && client.emit) { + if (options.instrumentPageLoad) { const context: StartSpanOptions = { name: WINDOW.location.pathname, // pageload should always start at timeOrigin (and needs to be in s, not ms) @@ -343,7 +341,7 @@ export const browserTracingIntegration = ((_options: Partial { /** * This early return is there to account for some cases where a navigation transaction starts right after @@ -402,10 +400,6 @@ export const browserTracingIntegration = ((_options: Partial { * Register a callback for transaction start. * Receives the transaction as argument. */ - on?(hook: 'startTransaction', callback: (transaction: Transaction) => void): void; + on(hook: 'startTransaction', callback: (transaction: Transaction) => void): void; /** * Register a callback for transaction finish. * Receives the transaction as argument. */ - on?(hook: 'finishTransaction', callback: (transaction: Transaction) => void): void; + on(hook: 'finishTransaction', callback: (transaction: Transaction) => void): void; /** * Register a callback for transaction start and finish. */ - on?(hook: 'beforeEnvelope', callback: (envelope: Envelope) => void): void; + on(hook: 'beforeEnvelope', callback: (envelope: Envelope) => void): void; /** * Register a callback for before sending an event. * This is called right before an event is sent and should not be used to mutate the event. * Receives an Event & EventHint as arguments. */ - on?(hook: 'beforeSendEvent', callback: (event: Event, hint?: EventHint | undefined) => void): void; + on(hook: 'beforeSendEvent', callback: (event: Event, hint?: EventHint | undefined) => void): void; /** * Register a callback for preprocessing an event, * before it is passed to (global) event processors. * Receives an Event & EventHint as arguments. */ - on?(hook: 'preprocessEvent', callback: (event: Event, hint?: EventHint | undefined) => void): void; + on(hook: 'preprocessEvent', callback: (event: Event, hint?: EventHint | undefined) => void): void; /** * Register a callback for when an event has been sent. */ - on?( - hook: 'afterSendEvent', - callback: (event: Event, sendResponse: TransportMakeRequestResponse | void) => void, - ): void; + on(hook: 'afterSendEvent', callback: (event: Event, sendResponse: TransportMakeRequestResponse | void) => void): void; /** * Register a callback before a breadcrumb is added. */ - on?(hook: 'beforeAddBreadcrumb', callback: (breadcrumb: Breadcrumb, hint?: BreadcrumbHint) => void): void; + on(hook: 'beforeAddBreadcrumb', callback: (breadcrumb: Breadcrumb, hint?: BreadcrumbHint) => void): void; /** * Register a callback when a DSC (Dynamic Sampling Context) is created. */ - on?(hook: 'createDsc', callback: (dsc: DynamicSamplingContext) => void): void; + on(hook: 'createDsc', callback: (dsc: DynamicSamplingContext) => void): void; /** * Register a callback when an OpenTelemetry span is ended (in @sentry/opentelemetry-node). * The option argument may be mutated to drop the span. */ - on?(hook: 'otelSpanEnd', callback: (otelSpan: unknown, mutableOptions: { drop: boolean }) => void): void; + on(hook: 'otelSpanEnd', callback: (otelSpan: unknown, mutableOptions: { drop: boolean }) => void): void; /** * Register a callback when a Feedback event has been prepared. * This should be used to mutate the event. The options argument can hint * about what kind of mutation it expects. */ - on?( + on( hook: 'beforeSendFeedback', callback: (feedback: FeedbackEvent, options?: { includeReplay?: boolean }) => void, ): void; @@ -265,83 +262,83 @@ export interface Client { /** * A hook for BrowserTracing to trigger a span start for a page load. */ - on?(hook: 'startPageLoadSpan', callback: (options: StartSpanOptions) => void): void; + on(hook: 'startPageLoadSpan', callback: (options: StartSpanOptions) => void): void; /** * A hook for BrowserTracing to trigger a span for a navigation. */ - on?(hook: 'startNavigationSpan', callback: (options: StartSpanOptions) => void): void; + on(hook: 'startNavigationSpan', callback: (options: StartSpanOptions) => void): void; /** * Fire a hook event for transaction start. * Expects to be given a transaction as the second argument. */ - emit?(hook: 'startTransaction', transaction: Transaction): void; + emit(hook: 'startTransaction', transaction: Transaction): void; /** * Fire a hook event for transaction finish. * Expects to be given a transaction as the second argument. */ - emit?(hook: 'finishTransaction', transaction: Transaction): void; + emit(hook: 'finishTransaction', transaction: Transaction): void; /* * Fire a hook event for envelope creation and sending. Expects to be given an envelope as the * second argument. */ - emit?(hook: 'beforeEnvelope', envelope: Envelope): void; + emit(hook: 'beforeEnvelope', envelope: Envelope): void; /** * Fire a hook event before sending an event. * This is called right before an event is sent and should not be used to mutate the event. * Expects to be given an Event & EventHint as the second/third argument. */ - emit?(hook: 'beforeSendEvent', event: Event, hint?: EventHint): void; + emit(hook: 'beforeSendEvent', event: Event, hint?: EventHint): void; /** * Fire a hook event to process events before they are passed to (global) event processors. * Expects to be given an Event & EventHint as the second/third argument. */ - emit?(hook: 'preprocessEvent', event: Event, hint?: EventHint): void; + emit(hook: 'preprocessEvent', event: Event, hint?: EventHint): void; /* * Fire a hook event after sending an event. Expects to be given an Event as the * second argument. */ - emit?(hook: 'afterSendEvent', event: Event, sendResponse: TransportMakeRequestResponse | void): void; + emit(hook: 'afterSendEvent', event: Event, sendResponse: TransportMakeRequestResponse | void): void; /** * Fire a hook for when a breadcrumb is added. Expects the breadcrumb as second argument. */ - emit?(hook: 'beforeAddBreadcrumb', breadcrumb: Breadcrumb, hint?: BreadcrumbHint): void; + emit(hook: 'beforeAddBreadcrumb', breadcrumb: Breadcrumb, hint?: BreadcrumbHint): void; /** * Fire a hook for when a DSC (Dynamic Sampling Context) is created. Expects the DSC as second argument. */ - emit?(hook: 'createDsc', dsc: DynamicSamplingContext): void; + emit(hook: 'createDsc', dsc: DynamicSamplingContext): void; /** * Fire a hook for when an OpenTelemetry span is ended (in @sentry/opentelemetry-node). * Expects the OTEL span & as second argument, and an option object as third argument. * The option argument may be mutated to drop the span. */ - emit?(hook: 'otelSpanEnd', otelSpan: unknown, mutableOptions: { drop: boolean }): void; + emit(hook: 'otelSpanEnd', otelSpan: unknown, mutableOptions: { drop: boolean }): void; /** * Fire a hook event for after preparing a feedback event. Events to be given * a feedback event as the second argument, and an optional options object as * third argument. */ - emit?(hook: 'beforeSendFeedback', feedback: FeedbackEvent, options?: { includeReplay?: boolean }): void; + emit(hook: 'beforeSendFeedback', feedback: FeedbackEvent, options?: { includeReplay?: boolean }): void; /** * Emit a hook event for BrowserTracing to trigger a span start for a page load. */ - emit?(hook: 'startPageLoadSpan', options: StartSpanOptions): void; + emit(hook: 'startPageLoadSpan', options: StartSpanOptions): void; /** * Emit a hook event for BrowserTracing to trigger a span for a navigation. */ - emit?(hook: 'startNavigationSpan', options: StartSpanOptions): void; + emit(hook: 'startNavigationSpan', options: StartSpanOptions): void; /* eslint-enable @typescript-eslint/unified-signatures */ }