diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts index e6f57c13fe6b..400a1c68f3ca 100644 --- a/packages/browser/src/index.ts +++ b/packages/browser/src/index.ts @@ -60,6 +60,8 @@ export { getSpanStatusFromHttpCode, setHttpStatus, makeMultiplexedTransport, + makeSimpleMultiplexedTransport, + SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY, moduleMetadataIntegration, zodErrorsIntegration, thirdPartyErrorFilterIntegration, diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 77259d2434d4..27734bc12238 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -57,7 +57,11 @@ export { ServerRuntimeClient } from './server-runtime-client'; export { initAndBind, setCurrentClient } from './sdk'; export { createTransport } from './transports/base'; export { makeOfflineTransport } from './transports/offline'; -export { makeMultiplexedTransport } from './transports/multiplexed'; +export { + makeMultiplexedTransport, + SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY, + makeSimpleMultiplexedTransport, +} from './transports/multiplexed'; export { getIntegrationsToSetup, addIntegration, diff --git a/packages/core/src/transports/multiplexed.ts b/packages/core/src/transports/multiplexed.ts index 29534fd13d9b..b316e87c6ac6 100644 --- a/packages/core/src/transports/multiplexed.ts +++ b/packages/core/src/transports/multiplexed.ts @@ -158,3 +158,28 @@ export function makeMultiplexedTransport( }; }; } + +export const SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY = 'SIMPLE_MULTIPLEXED_TRANSPORT_ROUTE_TO'; + +/** + * Creates a transport that will send events to all DSNs provided in `event.extra[SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY]`, + * which should contain values in the format of `Array<{ dsn: string;, release: string; }>`. + * + * If the value is `undefined` or `[]`, the event will be sent to the `dsn` value provided in your Sentry SDK initialization options as a fallback mechanism. + */ +export function makeSimpleMultiplexedTransport( + transportGenerator: (options: TO) => Transport, +): (options: TO) => Transport { + return makeMultiplexedTransport(transportGenerator, args => { + const event = args.getEvent(); + if ( + event && + event.extra && + SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY in event.extra && + Array.isArray(event.extra[SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY]) + ) { + return event.extra[SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY]; + } + return []; + }); +} diff --git a/packages/core/test/lib/transports/multiplexed.test.ts b/packages/core/test/lib/transports/multiplexed.test.ts index 647acbdc856e..68c24b02fd70 100644 --- a/packages/core/test/lib/transports/multiplexed.test.ts +++ b/packages/core/test/lib/transports/multiplexed.test.ts @@ -1,23 +1,24 @@ -import type { - BaseTransportOptions, - ClientReport, - Envelope, - EventEnvelope, - EventItem, - TransactionEvent, - Transport, -} from '../../../src/types-hoist'; - import { + SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY, createClientReportEnvelope, createEnvelope, createTransport, dsnFromString, getEnvelopeEndpointWithUrlEncodedAuth, makeMultiplexedTransport, + makeSimpleMultiplexedTransport, parseEnvelope, } from '../../../src'; import { eventFromEnvelope } from '../../../src/transports/multiplexed'; +import type { + BaseTransportOptions, + ClientReport, + Envelope, + EventEnvelope, + EventItem, + TransactionEvent, + Transport, +} from '../../../src/types-hoist'; const DSN1 = 'https://1234@5678.ingest.sentry.io/4321'; const DSN1_URL = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(DSN1)!); @@ -247,3 +248,82 @@ describe('makeMultiplexedTransport', () => { await transport.send(TRANSACTION_ENVELOPE); }); }); + +describe('makeSimpleMultiplexedTransport()', () => { + it('sends events to targets provided in event.extra[SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY]', async () => { + expect.assertions(2); + + const makeTransport = makeSimpleMultiplexedTransport( + createTestTransport( + url => { + expect(url).toBe(DSN1_URL); + }, + url => { + expect(url).toBe(DSN2_URL); + }, + ), + ); + + const envelope = createEnvelope({ event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', sent_at: '123' }, [ + [ + { type: 'event' }, + { + event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', + extra: { + [SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY]: [DSN1, DSN2], + }, + }, + ] as EventItem, + ]); + + const transport = makeTransport({ url: DSN1_URL, ...transportOptions }); + await transport.send(envelope); + }); + + it('sends events to default DSN if event.extra[SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY] is not set', async () => { + expect.assertions(1); + + const makeTransport = makeSimpleMultiplexedTransport( + createTestTransport(url => { + expect(url).toBe(DSN1_URL); + }), + ); + + const envelope = createEnvelope({ event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', sent_at: '123' }, [ + [ + { type: 'event' }, + { + event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', + }, + ] as EventItem, + ]); + + const transport = makeTransport({ url: DSN1_URL, ...transportOptions }); + await transport.send(envelope); + }); + + it('sends events to default DSN if event.extra[SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY] is an empty array', async () => { + expect.assertions(1); + + const makeTransport = makeSimpleMultiplexedTransport( + createTestTransport(url => { + expect(url).toBe(DSN1_URL); + }), + ); + + const envelope = createEnvelope({ event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', sent_at: '123' }, [ + [ + { type: 'event' }, + { + event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', + extra: { + [SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY]: [], + }, + }, + ] as EventItem, + ]); + + const transport = makeTransport({ url: DSN1_URL, ...transportOptions }); + await transport.send(envelope); + }); +});