diff --git a/packages/solidstart/src/server/utils.ts b/packages/solidstart/src/server/utils.ts index 1560b254bd22..8276c32da9e0 100644 --- a/packages/solidstart/src/server/utils.ts +++ b/packages/solidstart/src/server/utils.ts @@ -17,25 +17,32 @@ export function isRedirect(error: unknown): boolean { return hasValidLocation && hasValidStatus; } +/** + * Filter function for low quality transactions + * + * Exported only for tests + */ +export function lowQualityTransactionsFilter(options: Options): EventProcessor { + return Object.assign( + (event => { + if (event.type !== 'transaction') { + return event; + } + // Filter out transactions for build assets + if (event.transaction?.match(/^GET \/_build\//)) { + options.debug && debug.log('SolidStartLowQualityTransactionsFilter filtered transaction', event.transaction); + return null; + } + return event; + }) satisfies EventProcessor, + { id: 'SolidStartLowQualityTransactionsFilter' }, + ); +} + /** * Adds an event processor to filter out low quality transactions, * e.g. to filter out transactions for build assets */ export function filterLowQualityTransactions(options: Options): void { - getGlobalScope().addEventProcessor( - Object.assign( - (event => { - if (event.type !== 'transaction') { - return event; - } - // Filter out transactions for build assets - if (event.transaction?.match(/^GET \/_build\//)) { - options.debug && debug.log('SolidStartLowQualityTransactionsFilter filtered transaction', event.transaction); - return null; - } - return event; - }) satisfies EventProcessor, - { id: 'SolidStartLowQualityTransactionsFilter' }, - ), - ); + getGlobalScope().addEventProcessor(lowQualityTransactionsFilter(options)); } diff --git a/packages/solidstart/test/server/sdk.test.ts b/packages/solidstart/test/server/sdk.test.ts index b700b43a067a..c5df698ed307 100644 --- a/packages/solidstart/test/server/sdk.test.ts +++ b/packages/solidstart/test/server/sdk.test.ts @@ -1,8 +1,9 @@ -import type { NodeClient } from '@sentry/node'; -import { SDK_VERSION } from '@sentry/node'; +import type { EventProcessor } from '@sentry/core'; +import { getGlobalScope, Scope, SDK_VERSION } from '@sentry/node'; import * as SentryNode from '@sentry/node'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { init as solidStartInit } from '../../src/server'; +import { lowQualityTransactionsFilter } from '../../src/server/utils'; const browserInit = vi.spyOn(SentryNode, 'init'); @@ -34,37 +35,52 @@ describe('Initialize Solid Start SDK', () => { expect(browserInit).toHaveBeenLastCalledWith(expect.objectContaining(expectedMetadata)); }); - it('filters out low quality transactions', async () => { - const beforeSendEvent = vi.fn(event => event); - const client = solidStartInit({ - dsn: 'https://public@dsn.ingest.sentry.io/1337', - }) as NodeClient; - client.on('beforeSendEvent', beforeSendEvent); + describe('lowQualityTransactionsFilter', () => { + const options = { debug: false }; + const filter = lowQualityTransactionsFilter(options); + + describe('filters out low quality transactions', () => { + it.each(['GET /_build/some_asset.js', 'GET /_build/app.js', 'GET /_build/assets/logo.png'])( + 'filters out low quality transaction: (%s)', + transaction => { + const event = { type: 'transaction' as const, transaction }; + expect(filter(event, {})).toBeNull(); + }, + ); + }); + + describe('keeps high quality transactions', () => { + it.each(['GET /', 'POST /_server'])('does not filter out route transactions (%s)', transaction => { + const event = { type: 'transaction' as const, transaction }; + expect(filter(event, {})).toEqual(event); + }); + }); - client.captureEvent({ type: 'transaction', transaction: 'GET /' }); - client.captureEvent({ type: 'transaction', transaction: 'GET /_build/some_asset.js' }); - client.captureEvent({ type: 'transaction', transaction: 'POST /_server' }); + it('does not filter non-transaction events', () => { + const event = { type: 'error' as const, transaction: 'GET /_build/app.js' } as any; + expect(filter(event, {})).toEqual(event); + }); + + it('handles events without transaction property', () => { + const event = { type: 'transaction' as const }; + expect(filter(event, {})).toEqual(event); + }); + }); - await client!.flush(); + it('registers an event processor', () => { + let passedEventProcessors: EventProcessor[] = []; + const addEventProcessor = vi + .spyOn(getGlobalScope(), 'addEventProcessor') + .mockImplementation((eventProcessor: EventProcessor) => { + passedEventProcessors = [...passedEventProcessors, eventProcessor]; + return new Scope(); + }); + + solidStartInit({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + }); - expect(beforeSendEvent).toHaveBeenCalledTimes(2); - expect(beforeSendEvent).toHaveBeenCalledWith( - expect.objectContaining({ - transaction: 'GET /', - }), - expect.any(Object), - ); - expect(beforeSendEvent).not.toHaveBeenCalledWith( - expect.objectContaining({ - transaction: 'GET /_build/some_asset.js', - }), - expect.any(Object), - ); - expect(beforeSendEvent).toHaveBeenCalledWith( - expect.objectContaining({ - transaction: 'POST /_server', - }), - expect.any(Object), - ); + expect(addEventProcessor).toHaveBeenCalledTimes(1); + expect(passedEventProcessors[0]?.id).toEqual('SolidStartLowQualityTransactionsFilter'); }); });