@personio/alerting
v0.2.5
Published
A package to report frontend errors on sentry
Downloads
1,497
Maintainers
Keywords
Readme
Alerting
An npm package for micro-frontends to report frontend errors to Sentry
About
This packages leverages the BrowserClient and Hub APIs to create a Sentry instance dedicated to the micro-frontend it is running on.
Unlike the Sentry.init
API, this ensures that in a webpage with multiple
micro-frontends, we can have multiple instances of Sentry each dedicated to one
micro-frontend. Behind the scenes, this package will ensure that only the errors
occurring from the micro-frontend bundle the Sentry instance is running on get
reported to the Sentry project this Sentry instance is tied to.
For example, a webpage with two micro-frontends MFE-A
and MFE-B
each having
their own Sentry instance Sentry-A
and Sentry-B
where MFE-A
throws an
error on a click event, the internal working of these Sentry instances will
ensure that Sentry-A
reports this event on the MFE-A
Sentry project while
Sentry-B
will simply ignore this error.
Installation
Install the package:
yarn add @personio/alerting
:warning: Note! :warning:
@personio/alerting
already comes with both @sentry/browser
and @sentry/cli
bundled as dependencies. There is no need to have them in your project, so feel
free to remove them if you do.
yarn remove @sentry/browser @sentry/cli
Minimal Usage
First, you need to add the crossorigin
attribute to your bundle's script
tag
and set its value to anonymous
. This is what allows us to detect which JS file
an error originated from.
For mFEs not in use on production:
<script src="<cdn>/my-mfe/8BADF00D.js" crossorigin="anonymous" defer></script>
For mFEs in use on production for at least one customer:
Note that we are adding a queryParam to the src of the script tag called
crossOriginCacheBuster
. We need to do this to make sure that when this code
goes on production, the cached JS file for the mFE is invalidated by the browser
and instead it is fetched from the CDN. This will ensure that the response from
CDN has the ACAO headers set correctly
<script
src="<cdn>/my-mfe/8BADF00D.js?crossOriginCacheBuster"
crossorigin="anonymous"
defer
></script>
Next, the minimal implementation is to wrap your application with the package's
SentryProvider
component, and pass the necessary Sentry config options via
props.
import { SentryProvider } from '@personio/alerting';
…
<SentryProvider
dsn={SENTRY_DSN}
env={ENV}
name={MICRO_FRONTEND_NAME}
version={MICRO_FRONTEND_VERSION}
enabled={IS_SENTRY_ENABLED}
>
<App />
</Sentryprovider>
Potential issues
if the webpack dev server is not setup properly, while consuming local instance of mFE from local Monolith the following error may appear:
Access to script at ... from origin ... has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
In order to resolve it, make sure that webpack dev server is configured in way so it works properly with CORS headers, which means that
build-utils/webpack.development.js
(or similar) file in the mFE must havedevServer.headers
conf section which includes'Access-Control-Allow-Origin': '*.dev.personio.de',
.
In what order should I deploy the changes in the monolith and my mFE
You should first merge the MR on the monolith with the newly added crossorigin
attribute
Once the monolioth deployment has finished, you can go ahead and deploy your mFE
Integration with Error Boundary
The package also provides aSentryErrorBoundary
component which you can use in
your MFE to automatically catch and report rendering errors to your Sentry
instance.
import { SentryErrorBoundary } from '@personio/alerting';
…
<SentryErrorBoundary errorComponent={<div>Something went wrong</div>}>
<TemperamentalComponent />
</SentryErrorBoundary>
If you wish to only use this as an ErrorBoundary and not have it report to
Sentry, you can pass false
to the reportRenderError
prop.
import { SentryErrorBoundary } from '@personio/alerting';
…
<SentryErrorBoundary
errorComponent={<div>Something went wrong</div>}
reportRenderError={false}
>
<TemperamentalComponent />
</SentryErrorBoundary>
Manually Capturing Exceptions
@personio/alerting
also exposes the internal method used to capture exceptions
through the Context, allowing you to manually capture your own exceptions where
needed. You can optionally pass extras
which will appear alongside your alert
in Sentry, with default environment
, mfe_name
, and mfe_version
values.
Note: this is preferred to using the Sentry Hub instance directly.
import { nanoid } from 'nanoid';
import { useSentry } from '@personio/alerting';
const PokemonDetails = () => {
const { capture } = useSentry();
const fetchPokemon = (id) => {
let data = {};
try {
const res = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`);
data = await res.json();
} catch (err) {
// `capture` checks if Sentry is enabled internally
capture(err, { uuid: nanoid() });
}
return data;
};
};
Accessing the Sentry Hub
We leverage React Context under-the-hood to store an instance of Sentry Hub and handle the reporting. This Hub and Context are available as an escape hatch, a means of directly reporting from custom locations, or to further enrich events with additional info.
The Hub (and your Sentry instance's enabled
status) is exposed through a
custom hook that can be consumed anywhere in your app that hooks can normally be
used.
Note: this is entirely optional and, typically, you will never use it.
import { nanoid } from 'nanoid';
import { useSentry } from '@personio/alerting';
const PokemonDetails = () => {
const { enabled, hub } = useSentry();
const fetchPokemon = (id) => {
let data = {};
try {
const res = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`);
data = await res.json();
} catch (err) {
if (enabled) {
hub.setTag('uuid', nanoid());
hub.captureException(err);
}
}
return data;
};
};