From 372efdbc924bf935e721e267d5139dea682c5f66 Mon Sep 17 00:00:00 2001 From: Kosty Maleyev Date: Thu, 22 Feb 2024 21:02:11 -0800 Subject: [PATCH 1/4] feat(core): simpler API for multiplexed transport Hoping to reduce complexity for setting up micro-frontends routing. --- packages/core/src/transports/multiplexed.ts | 24 +++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/packages/core/src/transports/multiplexed.ts b/packages/core/src/transports/multiplexed.ts index a496a8adcd6f..6982884f02a9 100644 --- a/packages/core/src/transports/multiplexed.ts +++ b/packages/core/src/transports/multiplexed.ts @@ -139,3 +139,27 @@ export function makeMultiplexedTransport( }; }; } + +export const MULTIPLEXED_TRANSPORT_EXTRA_KEY = "multiplexed_transport"; + +/** + * Creates a transport that will send events to all DSNs provided in event.extra["multiplexed_transport"] + * in the format of [{dsn: "__MY_DSN__", release: "__MY_RELEASE__"}, ...]. If no such key exists or list + * is empty event will be sent to main DSN provided in Sentry.init(). + */ +export function makeSimpleMultiplexedTransport( + createTransport: (options: TO) => Transport, +): (options: TO) => Transport { + return makeMultiplexedTransport(makeFetchTransport, (args) => { + const event = args.getEvent(); + if ( + event && + event.extra && + MULTIPLEXED_TRANSPORT_EXTRA_KEY in event.extra && + Array.isArray(event.extra[MULTIPLEXED_TRANSPORT_EXTRA_KEY]) + ) { + return event.extra[MULTIPLEXED_TRANSPORT_EXTRA_KEY]; + } + return []; + }); +} From 7cb4d48d04d89a86000423372de6385b791bd147 Mon Sep 17 00:00:00 2001 From: Kosty Maleyev Date: Thu, 22 Feb 2024 22:23:26 -0800 Subject: [PATCH 2/4] Update multiplexed.ts --- packages/core/src/transports/multiplexed.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/transports/multiplexed.ts b/packages/core/src/transports/multiplexed.ts index 6982884f02a9..292c18d5a358 100644 --- a/packages/core/src/transports/multiplexed.ts +++ b/packages/core/src/transports/multiplexed.ts @@ -140,7 +140,7 @@ export function makeMultiplexedTransport( }; } -export const MULTIPLEXED_TRANSPORT_EXTRA_KEY = "multiplexed_transport"; +export const MULTIPLEXED_TRANSPORT_EXTRA_KEY = "ROUTE_TO"; /** * Creates a transport that will send events to all DSNs provided in event.extra["multiplexed_transport"] From 82d889ef828bffcfd173b2b9facd3c103fbbd7ef Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Fri, 22 Mar 2024 08:48:34 +0000 Subject: [PATCH 3/4] Clean up and export --- packages/browser/src/index.ts | 2 ++ packages/core/src/index.ts | 6 +++++- packages/core/src/transports/multiplexed.ts | 19 ++++++++++--------- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts index 4b5248f91683..a07ea95b4040 100644 --- a/packages/browser/src/index.ts +++ b/packages/browser/src/index.ts @@ -75,6 +75,8 @@ export { getSpanStatusFromHttpCode, setHttpStatus, makeMultiplexedTransport, + makeSimpleMultiplexedTransport, + SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY, moduleMetadataIntegration, } from '@sentry/core'; export type { Span } from '@sentry/types'; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 217ae7273422..1066dd97104e 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -65,7 +65,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 { SDK_VERSION } from './version'; export { getIntegrationsToSetup, diff --git a/packages/core/src/transports/multiplexed.ts b/packages/core/src/transports/multiplexed.ts index a075baf17486..751429d94099 100644 --- a/packages/core/src/transports/multiplexed.ts +++ b/packages/core/src/transports/multiplexed.ts @@ -140,25 +140,26 @@ export function makeMultiplexedTransport( }; } -export const MULTIPLEXED_TRANSPORT_EXTRA_KEY = "ROUTE_TO"; +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["multiplexed_transport"] - * in the format of [{dsn: "__MY_DSN__", release: "__MY_RELEASE__"}, ...]. If no such key exists or list - * is empty event will be sent to main DSN provided in Sentry.init(). + * 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( - createTransport: (options: TO) => Transport, + transportGenerator: (options: TO) => Transport, ): (options: TO) => Transport { - return makeMultiplexedTransport(makeFetchTransport, (args) => { + return makeMultiplexedTransport(transportGenerator, args => { const event = args.getEvent(); if ( event && event.extra && - MULTIPLEXED_TRANSPORT_EXTRA_KEY in event.extra && - Array.isArray(event.extra[MULTIPLEXED_TRANSPORT_EXTRA_KEY]) + SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY in event.extra && + Array.isArray(event.extra[SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY]) ) { - return event.extra[MULTIPLEXED_TRANSPORT_EXTRA_KEY]; + return event.extra[SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY]; } return []; }); From e1b9dd83788a5502c30b116e00b26c4399eb7acf Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Fri, 22 Mar 2024 09:04:01 +0000 Subject: [PATCH 4/4] Add test --- .../test/lib/transports/multiplexed.test.ts | 85 ++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/packages/core/test/lib/transports/multiplexed.test.ts b/packages/core/test/lib/transports/multiplexed.test.ts index c2d0d2f1d318..e456e6a704a1 100644 --- a/packages/core/test/lib/transports/multiplexed.test.ts +++ b/packages/core/test/lib/transports/multiplexed.test.ts @@ -9,7 +9,11 @@ import type { import { createClientReportEnvelope, createEnvelope, dsnFromString, parseEnvelope } from '@sentry/utils'; import { createTransport, getEnvelopeEndpointWithUrlEncodedAuth, makeMultiplexedTransport } from '../../../src'; -import { eventFromEnvelope } from '../../../src/transports/multiplexed'; +import { + SIMPLE_MULTIPLEXED_TRANSPORT_EXTRA_ROUTING_KEY, + eventFromEnvelope, + makeSimpleMultiplexedTransport, +} from '../../../src/transports/multiplexed'; const DSN1 = 'https://1234@5678.ingest.sentry.io/4321'; const DSN1_URL = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(DSN1)!); @@ -221,3 +225,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); + }); +});