[Part 2] A proactive approach to handling application errors
Tags: devops, javascript, webdev, react
Published: 2021-10-11 08:30:43

<b>NOTE: You will need to create a sentry account for this tutorial.</b>

This is the second part in a 3 part series on how to proactively handle errors in your applications across the stack.

Issues on the front-end are more easily noticeable. In a lot of applications this is beautifully handled by having an error boundary. I have seen people create Error Boundaries that react differently to different kind of errors and provide a really good experience even in the face of an error.

While this certainly helps calm the user down in the spur of the moment, having the ability to proactively be informed about these issues would be a blessing. This allows us to root cause and fix issues before they escalate into a PR problem.

Sentry is an Error Monitoring and reporting solution that integrates well with frontend applications.

This tutorial assumes that you are familiar with
- [React](https://reactjs.org/)
- [Error Boundaries in React](https://reactjs.org/docs/error-boundaries.html)

In this tutorial we will

- Create an account with Sentry
- Integrate sentry into the application
- Add support for source-maps
- Test your integration and source maps

## Create an account with Sentry

### Step 1
Go to [https://sentry.io/](https://sentry.io/) and click on <b>GET STARTED</b>
![615d7ad09c9ba70eb9614511_Screen Shot 2021-08-24 at 3.59.09 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qtffbv8nhgaodimpbdxq.png)

### Step 2
Add in your details and click <b>CREATE YOUR ACCOUNT</b>
![615d7ae9fbb2462c0fdffdd0_Screen Shot 2021-08-24 at 3.59.37 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8tknng7w7xvqn1xbcxmz.png)

### Step 3
You will be redirected to the onboarding screen as shown below. Click on <b>I'm Ready</b>
![615d7b03fbb24685aae0002d_Screen Shot 2021-08-24 at 4.00.48 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/snri2cydr178z5zk7bfc.png)

### Step 4
Select <b>React</b>, choose a suitable project name and click <b>Create Project</b>
![615d7b1b9fac621964c9fa88_Screen Shot 2021-08-24 at 4.21.02 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/88atvohngz3npewitwqg.png)

### Step 5 
You will be redirected to the <b>"Configure React"</b> page. Copy the dsn value.
![615d7b2e7d1e6496fab8e961_Screen Shot 2021-08-24 at 4.48.45 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/17bjl0wts8visgr03vgb.png)

## Integrate sentry into the application
We will now send sentry errors from the ErrorBoundary component

### Step 1
Clone this repo: [https://github.com/wednesday-solutions/react-template](https://github.com/wednesday-solutions/react-template)

### Step 2
Install the dependencies
```
yarn add @sentry/react @sentry/tracing
```

### Step 3
Copy the dsn from the 1st project and add it in the .env.development and in the .env file
```
SENTRY_DSN=XYZ
```

### Step 4
Create a sentry service.
```
vi app/services/sentry.js
```
Copy the snippet below in the `sentry.js` file
```
import * as Sentry from '@sentry/react';
import { Integrations } from "@sentry/tracing";
import { isLocal } from '@utils';

export function initSentry () {
	if (!isLocal()) {
	  Sentry.init({
      environment: process.env.ENVIRONMENT_NAME,
	    dsn: process.env.SENTRY_DSN,
	    integrations: [new Integrations.BrowserTracing()],
	    tracesSampleRate: 1.0
	  });
	}
}
```

### Step 5
Add the snippet below in the `app/app.js`
```
...
import { initSentry } from '@services/sentry';
...
initSentry();
// Chunked polyfill for browsers without Intl support
if (!window.Intl) {
  ...
} else {
  ...
}
...
```
In order to test your integration locally, temporarily make a small change in the if condition of the initSentry function
```
...
if (true || !isLocal() {
  ...
}
...
```

### Step 6
```
yarn start
```

Go to [http://localhost:3000](http://localhost:3000) and you open the developer tools. Go to the network tab.

You should see an outgoing request to the sentry servers.
![615d7b53bb23c23d2a1e9cfb_Screen Shot 2021-08-24 at 6.26.50 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8r7gqggvzzqkjo5pnppd.png)
<b>Congratulations! Sentry has been setup.</b>

### Step 7
Now let's integrate sentry in the ErrorBoundary so that we can report back to sentry whenever there is an error.

Copy this snippet into the `app/services/sentry.js`
```
...
export function reportError(error, errorInfo) {
  Sentry.captureException(error, { extra: errorInfo }, );
}
```

Copy this snippet into the `app/components/ErrorBoundary/index.js`


```
import { reportError } from '@services/sentry';
...
  componentDidCatch(error, errorInfo) {
    console.error(error, errorInfo);
    reportError(error, errorInfo);
  }
...
```

### Step 8

Test your integration by adding this snippet in the `app/app.js` file

```
...
} else {
  render(translationMessages);
}
const a = null;
console.log(a.abc);
// Install ServiceWorker and AppCache in the end since
...
```
Navigate to your project on sentry and you should see something like this
![615d7b6a5cb29b2c8500c77f_Screen Shot 2021-08-24 at 6.42.07 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9u2di1u8t6711bn7g1gv.png)
 
You should also be able to filter by environment
![615d7bb371e7cb8452e44f96_Screen Shot 2021-08-24 at 6.42.19 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8jsxkv8tswoy2hqifq4o.png)

## Add support for source-maps
### Step 1
Click on the event to get some more details about it
![615d7bc6cc65f1810bb1d65b_Screen Shot 2021-08-24 at 6.44.06 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2xg2smol5rm7pg608aio.png)
You will notice that it is not very easy to track where the exact issue is. We will now integrate source-maps so that we get the complete stack trace.

### Step 2
In sentry go to Settings → Developer Settings → New Internal Integration
![615d7bdecc65f1569fb1d66b_Screen Shot 2021-08-24 at 6.53.07 PM (1)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ahhbf9tjnq20nmqz8gy.png)
 
Add the name of the integration like <b>Github Action Release</b>

Setup permissions. We will need <b>Admin</b> for Release and <b>Read</b> for Organization

Click <b>Save</b> and <b>copy the token</b>

### Step 3
Go to your repository on Github → Settings → Secrets → New Repository Secret

name it <b>SENTRY_AUTH_TOKEN</b> and paste the token in the value field.

Similarly add <b>SENTRY_ORG</b> and <b>SENTRY_PROJECT</b> to the secrets. Those these are not really secrets it will allow you to reuse this workflow as is in all your projects.

### Step 4
Now we will write the sentry workflow that will handle deployment to <b>AWS S3</b> and upload the source-maps. Create an S3 bucket and enable static website hosting
![615d7c03235c81be34c308b8_Screen Shot 2021-08-25 at 4.04.13 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6lkqos15cr0ko7z8l2pz.png)
![615d7c0ed33fbad3f94e9307_Screen Shot 2021-08-25 at 4.03.59 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j3ntjmfmo8cw57z5j0a3.png)
Create a new workflow for uploading the source-maps
```
rm .github/workflows/cd.yml
vi .github/workflows/sentry.yml
```
Copy the following snippet. in the `sentry.yml` file
```
name: Upload Source Maps
on:
  push:
    branches:
      - master
jobs:
  upload-source-maps:
    runs-on: ubuntu-latest
    env:
      SENTRY_RELEASE: ${{ github.sha }}
      SOURCE_DIR: './build/'
      AWS_REGION: ${{ secrets.AWS_REGION }}
      AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
      AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      PATHS: '/*'
      AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
    steps:
      - uses: actions/checkout@v2
      - name: Install dependencies
        run: yarn
      - name: Build
        run: export SENTRY_RELEASE=${{ github.sha }} && yarn build
      - name: AWS Deploy #5
        uses: jakejarvis/s3-sync-action@v0.5.0
        with:
          args: --acl public-read --follow-symlink
      - name: Set env BRANCH
        run: echo "BRANCH=$(echo $GITHUB_REF | cut -d'/' -f 3)" >> $GITHUB_ENV
      - name: Get environment_name
        id: vars
        run: |
          if [[ $BRANCH == 'master' ]]; then
              echo ::set-output name=environment_name::production
          else
              echo ::set-output name=environment_name::development
          fi
      - name: Create Sentry release
        uses: getsentry/action-release@v1
        env:
          SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
          SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
          SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
        with:
          environment: ${{steps.vars.outputs.environment_name}}
          sourcemaps: './build'
          set_commits: 'auto'
```
1. Add environment variables for <b>AWS_REGION</b>, <b>AWS_ACCESS_KEY_ID</b>, <b>AWS_SECRET_ACCESS_KEY</b>, <b>AWS_S3_BUCKET</b>
2. Set the <b>environment_name</b> to either <b>production</b> or <b>development</b> based on the branch.

Update the `initSentry` function `services/sentry.js` as follows
```
export function initSentry() {
  ...
    Sentry.init({
      release: process.env.SENTRY_RELEASE,
      environment: process.env.ENVIRONMENT_NAME,
      dsn: process.env.SENTRY_DSN,
      integrations: [new Integrations.BrowserTracing()],
      tracesSampleRate: 1.0
    });
  ...
}
```
## Testing your integration and source-maps
Paste this snippet in your `app/containers/App/index.js`
```
import React, { useEffect } from 'react';
...

export function App({location}) {
	useEffect(() => {
    if (process.env.NODE_ENV !== 'test') {
      const a = null;
      // eslint-disable-next-line
      console.log(a.a300);
    }
  }, []);
  ...
}
...
```
Commit your code and push it.

Wait for the sentry action to complete.

Navigate to the URL where the website is hosted.
![615d7c4ed33fba334c4e9327_Screen Shot 2021-08-25 at 4.46.17 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/es6tryrnciurcbprszyu.png)
You'll be greeted with a <b>Sorry. Something went wrong!</b> screen. Don't worry, this means your <b>ErrorBoundary</b> has been invoked. Go to sentry and take a look at the issue. 
![615d7c5dd80aaa80e5106e4d_Screen Shot 2021-08-25 at 5.55.45 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2xx5vi98o5ly2082if28.png)
 
<b>We now have support for release mapping!</b>

## Adding support for suspected commits
Add a <b>Github Integration</b>
Go to Settings → Integrations → Github

![615d7c72bb23c2de9e1eb0b3_Screen Shot 2021-08-27 at 6.43.39 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r2l79b90dzg8ry4t2dqd.png)
Choose the right organisation → Only select repositories → Install
![615d7c8466fdd1b0d641f99f_Screen Shot 2021-08-27 at 6.45.15 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kkkg9fffu3x6tudenibm.png)
Reload the react application to fire a new event.

You should now start seeing <b>Suspect commits</b> which help attribute the issue to the commit that introduced it.

Filter all issues by releases, and assign issues to the right team member!
![615d7c9309607e213f8970fb_Screen Shot 2021-08-25 at 5.55.36 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/izi77dlqmk6jazhxbr97.png)
 
## Where to go from here
You now have the ability to proactively handle errors on the backend. Use the sendMessage function to capture and report errors to slack. Pull only the relevant logs using the request-id as a filter.

I hope you enjoyed reading this article as much as I enjoyed writing it. If this peaked your interest stay tuned for the next article in the series where I will take you through how to proactively report frontend errors using Sentry.

If you have any questions or comments, please join the forum discussion below.