|
| 1 | +--- |
| 2 | +title: Micro Frontend Support |
| 3 | +sidebar_order: 200 |
| 4 | +description: '' |
| 5 | +keywords: ['micro frontend', 'multiplexed transport'] |
| 6 | +--- |
| 7 | + |
| 8 | +The recommended way to use the Sentry SDK with Micro Frontend is to set up a multiplexed transport when calling `Sentry.init`. The multiplexed transport will send events to different Sentry projects based on the attributes on that event, which is how you can isolate events from a specific micro-frontend to a specific Sentry project. |
| 9 | + |
| 10 | +Requires SDK version `7.50.0` or higher. |
| 11 | + |
| 12 | +The example below uses the `feature` tag to determine which Sentry project to send the event to by using different DSNs. If the event does not have a `feature` tag, we send it to the fallback DSN defined in `Sentry.init`. |
| 13 | + |
| 14 | +```typescript |
| 15 | +import { makeMultiplexedTransport } from '@sentry/core'; |
| 16 | +import { init, captureException, makeFetchTransport } from '@sentry/browser'; |
| 17 | + |
| 18 | +function dsnFromFeature({ getEvent }) { |
| 19 | + const event = getEvent(); |
| 20 | + switch(event?.tags?.feature) { |
| 21 | + case 'cart': |
| 22 | + return ['__CART_DSN__']; |
| 23 | + case 'gallery': |
| 24 | + return ['__GALLERY_DSN__']; |
| 25 | + } |
| 26 | + return [] |
| 27 | +} |
| 28 | + |
| 29 | +init({ |
| 30 | + dsn: '__FALLBACK_DSN__', |
| 31 | + transport: makeMultiplexedTransport(makeFetchTransport, dsnFromFeature) |
| 32 | +}); |
| 33 | + |
| 34 | +captureException(new Error('oh no!', scope => { |
| 35 | + scope.addTag('feature', 'cart'); |
| 36 | + return scope; |
| 37 | +}); |
| 38 | +``` |
| 39 | +
|
| 40 | +You can then set tags/contexts on events in individual micro-frontends to decide which Sentry project to send the event to. |
| 41 | +
|
| 42 | +<Alert level="warning" title="Note"> |
| 43 | +
|
| 44 | +Currently, there is no way to isolate tags/contexts/breadcrumbs/spans to events sent to a specific Sentry project. This is because browsers do not have support for async contexts, which is required for this functionality to work. Once the [tc39 Async Context](https://github.com/tc39/proposal-async-context) proposal is implemented in all browsers, we will be able to add this functionality. |
| 45 | +
|
| 46 | +</Alert> |
| 47 | +
|
| 48 | +## `makeMultiplexedTransport` API |
| 49 | +
|
| 50 | +`makeMultiplexedTransport` takes an instance of a transport (we recommend `makeFetchTransport`) and a matcher function that returns an array of DSNs. |
| 51 | +
|
| 52 | +```typescript |
| 53 | +type EnvelopeItemType = |
| 54 | + | 'client_report' |
| 55 | + | 'user_report' |
| 56 | + | 'session' |
| 57 | + | 'sessions' |
| 58 | + | 'transaction' |
| 59 | + | 'attachment' |
| 60 | + | 'event' |
| 61 | + | 'profile' |
| 62 | + | 'replay_event' |
| 63 | + | 'replay_recording' |
| 64 | + | 'check_in'; |
| 65 | + |
| 66 | +interface MatchParam { |
| 67 | + /** The envelope to be sent */ |
| 68 | + envelope: Envelope; |
| 69 | + /** |
| 70 | + * A function that returns an event from the envelope if one exists. You can optionally pass an array of envelope item |
| 71 | + * types to filter by - only envelopes matching the given types will be multiplexed. |
| 72 | + * |
| 73 | + * @param types Defaults to ['event'] (only error events will be matched) |
| 74 | + */ |
| 75 | + getEvent(types?: EnvelopeItemType[]): Event | undefined; |
| 76 | +} |
| 77 | + |
| 78 | +type Matcher = (param: MatchParam) => string[]; |
| 79 | + |
| 80 | +declare function makeMultiplexedTransport( |
| 81 | + transport: (options: TransportOptions) => Transport, |
| 82 | + matcher: Matcher |
| 83 | +): (options: TransportOptions) => Transport; |
| 84 | +``` |
| 85 | +
|
| 86 | +The matcher function runs after all client processing (`beforeSend` option, event processors from integrations). |
| 87 | +
|
| 88 | +## Examples |
| 89 | +
|
| 90 | +### Allowing Individual Micro Frontends to Add Their Own DSNs |
| 91 | +
|
| 92 | +The example below gives a list of DSNs and tags. It uses the `tags` attribute on the event to determine which Sentry project to send the event to by using different DSNs. If the event does not have a `tags` attribute, we send it to the fallback DSN defined in `Sentry.init`. Individual micro-frontends can then mutate the `myDsns` variable to add their own DSNs and tags. |
| 93 | +
|
| 94 | +```typescript |
| 95 | +const myDsns = [ |
| 96 | + { dsn: 'https://...', tag: 'my-tag' }, |
| 97 | + { dsn: 'https://...', tag: 'other-tag' }, |
| 98 | +]; |
| 99 | + |
| 100 | +function dsnFromTag({ getEvent }) { |
| 101 | + const event = getEvent(); |
| 102 | + const opt = myDsns.find(({tag} => event?.tags?.includes(tag)); |
| 103 | + return opt ? [opt.dsn] : []; |
| 104 | +} |
| 105 | + |
| 106 | +init({ |
| 107 | + dsn: '__FALLBACK_DSN__', |
| 108 | + transport: makeMultiplexedTransport(makeFetchTransport, dsnFromTag) |
| 109 | +}); |
| 110 | +``` |
| 111 | +
|
| 112 | +### Sending the Same Event to Multiple DSNs |
| 113 | +
|
| 114 | +Since the matcher returns an array, you can enforce that an event is sent to multiple DSNs. |
| 115 | +
|
| 116 | +```typescript |
| 117 | +import {makeMultiplexedTransport} from '@sentry/core'; |
| 118 | +import {init, makeFetchTransport} from '@sentry/browser'; |
| 119 | + |
| 120 | +const DSN1 = '__DSN1__'; |
| 121 | +const DSN2 = '__DSN2__'; |
| 122 | + |
| 123 | +init({ |
| 124 | + dsn: DSN1, // <- init dsn never gets used but need to be valid |
| 125 | + transport: makeMultiplexedTransport(makeFetchTransport, () => [DSN1, DSN2]), |
| 126 | +}); |
| 127 | +``` |
0 commit comments