0.2.5 • Published 10 months ago

@personio/alerting v0.2.5

Weekly downloads
-
License
MIT
Repository
-
Last release
10 months ago

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 have devServer.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;
  };
};
0.2.5

10 months ago

0.2.4

2 years ago

0.2.1

2 years ago

0.2.0

2 years ago

0.2.3

2 years ago

0.2.2

2 years ago

0.1.8

2 years ago

0.1.7

2 years ago

0.1.9

2 years ago

0.1.4

2 years ago

0.1.3

2 years ago

0.1.6

2 years ago

0.1.2

3 years ago

0.1.0

3 years ago

0.0.1-alpha.4

3 years ago

0.0.1-alpha.2

3 years ago

0.0.1-alpha.3

3 years ago

0.0.1-alpha.1

3 years ago

0.0.1-alpha.0

3 years ago

0.0.1

3 years ago