Front End Error Monitoring With Sentry

Damla Demir
9 min readJun 28, 2024

--

Image from https://leadgenera.com

We all love those perfectly functioning websites, right? They load quickly, run smoothly, and give us the desired experience. But have you ever wondered what’s going on behind the scenes? This is where error monitoring, comes into play.

The Importance of Error Monitoring

Imagine a seller trying to update their product listings or process an order, and the system crashes. Pages won’t load, buttons won’t respond, and critical tasks are incomplete. These errors frustrate the sellers and can impact their sales and reputation. Here’s why error monitoring is essential:

  1. User Satisfaction: When you can quickly identify and fix errors, your users will happily browse your site.
  2. Uninterrupted Operations: Addressing errors promptly prevents disruptions, ensuring that transactions and updates flow smoothly without causing delays or issues.
  3. Efficient Development: Error monitoring speeds up the development process by quickly pinpointing issues, allowing developers to focus on adding new features.
  4. Proactive Problem Solving: It helps identify potential issues before they become major problems, ensuring your site runs flawlessly even during peak times.

To ensure seamless error monitoring:

  1. Choose the Right Tools: Use powerful tools
  2. Real-Time Monitoring: Detect and fix errors instantly with real-time tools.
  3. Comprehensive Reporting: Provide detailed error reports for quick problem-solving.

Top Tools for Front-End Error Monitoring

In this article, I will focus on two powerful tools for front-end error monitoring: New Relic and Sentry.

New Relic vs Sentry

New Relic and Sentry are two widely used tools for monitoring errors in front-end applications. Each has its unique features and areas of focus. Here’s a comparison of these two tools:

  • New Relic primarily focuses on performance monitoring, and Sentry’s main focus is on error monitoring and providing detailed reports on those errors.
  • Sentry provides detailed error information such as operating system, browser, error stack trace, environment, release tag, user flow, etc. New Relic does not provide as detailed information as Sentry.
  • Sentry groups errors according to users, allowing us to see how many different users encountered the error.
  • Sentry is compatible with micro-frontend architecture
  • With source map integration, Sentry shows which lines in the source code the errors occur in, making debugging easier.
  • The disadvantage of Sentry is that there is a quota covering all teams that are reset at the beginning of the month, and once this quota is filled, errors cannot be collected. Quota must be managed correctly and effectively. There is no quota in New Relic.

For frontend error monitoring, Sentry is a more suitable option due to its detailed error information and user-based error grouping features. Additionally, Sentry’s environment support allows for identifying bugs before they reach the production environment. On the other hand, New Relic is more effective for performance monitoring and server-side analysis but does not offer as comprehensive error monitoring capabilities as Sentry.

Sentry Integration

Integrating Sentry into your projects is straightforward. For this example, we will integrate Sentry into a Vue.js project. Sentry provides a user interface to track errors, set up alerts, and create dashboards to monitor these errors. You can use the free version of Sentry available at the link provided.

First, create a new project in Sentry by navigating to the Projects section and selecting “Create Project”. In the pop-up screen, select the technology your application is built with, enter your project name, and create your project. Choosing the correct technology is crucial because Sentry uses different SDKs depending on the technology.

Create New Project

After creating the project on Sentry.io, you need to integrate it into your application. After clicking “Create Project,” you’ll see a screen with instructions on how to add the Sentry integration to your project.

Basic Sentry Integration

Here is a detailed configuration example:

import * as Sentry from '@sentry/vue';
import merge from 'ts-deepmerge';

export default class SentryService {
private readonly sentryInitOptions;
private readonly defaultUserOptions = {
id: 1
name: 'test-user',
};
public readonly defaultSentryOptions = {
ignoreErrors: [
'sample error',
],
ignoreUrls: [/^chrome-extensions:\/\//i],
denyUrls: [
/extensions\//i,
],
};
constructor(sentryInitOptions) {
this.sentryInitOptions = sentryInitOptions;
}
public createUser(userOptions) {
return Sentry.setUser({
...this.defaultUserOptions,
...userOptions,
});
}
public captureException(error) {
Sentry.captureException(error);
}
private mergeSentryOptions(options) {
const sentryOptions = merge(this.defaultSentryOptions, options);
return sentryOptions;
}
public init(app, options) {
const sentryOptions = this.mergeSentryOptions(options);
Sentry.init({
...sentryOptions,
...this.sentryInitOptions,
});
this.createUser();
}
}

Code Explanation:

  • defaultUserOptions: This section provides user information to Sentry, enabling it to group errors by users.
  • sentryInitOptions: This is where we configure Sentry settings.
  • ignoreErrors: If there are certain errors we do not want to track, we add them here. Sentry will not collect errors that match the patterns specified in this section.
  • ignoreUrls: This option is used to specify URL patterns that should be completely ignored. Errors from these URLs will not be sent to Sentry at all.
  • denyUrls: This option specifies URL patterns where errors should be filtered out and ignored. However, unlike ignoreUrls, these errors are still captured and logged internally by Sentry but are filtered out during reporting. This is useful for analyzing these errors later without cluttering the main error-tracking dashboard.
  • createUser : These functions are used to set user information in Sentry.
  • captureException: Sentry automatically captures unhandled errors. However, if we have a try-catch block and an error is caught, Sentry will not automatically track it. In such cases, if we want to track the error in Sentry, we need to send it manually using captureException.
  • init: This function initializes Sentry with the specified configurations.

You can follow for more options: Sentry Basic Options

The final step is to initialize the Sentry service. We do this by providing the initial values as shown below:

import { SentryService } from '@services/sentry';

const sentryService = new SentryService({
dsn: 'sample dsn',
release: 'sample release',
environment: 'sample environment',
});

sentryService.init(app);
  • dsn: The unique project ID is automatically generated by Sentry when you create a project on sentry.io.
  • release: The release version of your project.
  • environment: The environment in which the application is running (e.g., production, staging).

Capturing Our First Error

We have completed our sentry configuration, now we can catch our first error.

Let’s assume we have an application with a button labeled “Convert To Lower Case The Null”. When this button is clicked, we attempt to execute this.formData.serviceName.toLowerCase(). Since there is no null check in our code if the serviceName variable is null, an error will occur. Sentry will capture this unhandled error and display it in the issue list on sentry.io.

export default {
data() {
return {
formData: {
serviceName: null
}
};
},
methods: {
convertToLowerCaseTheNull() {
this.formData.serviceName = this.formData.serviceName.toLowerCase();
}
},
template: `
<div>
<button @click="convertToLowerCaseTheNull">Convert To Lower Case The Null</button>
</div>
`
};
Sample Application
First Issue in Sentry.io

As seen in the images above, when an error occurs, Sentry automatically captures it and displays it in the issue list. Here’s what the key elements in the issue list indicate:

  • Graph New Label: Indicates that this error has been captured for the first time.
  • Events: Shows how many times this particular error has occurred.
  • Users: Indicates how many unique users have encountered this error.

This information helps you understand the frequency and impact of the error, enabling you to prioritize and address issues effectively.

Issue Details
Issue Breadcrumbs

When you click on an issue to view its details, as shown in the images above, you can see various important details about the issue, including:

  • First Seen: The first time this error was encountered.
  • Last Seen: The most recent occurrence of this error.
  • Browser: The browser in which the error occurred.
  • Device: The device on which the error occurred.
  • Environment: The environment (e.g., production, staging) in which the error occurred.
  • Operating System: The OS on which the error occurred.
  • Breadcrumbs: A timeline of events leading up to the error, which can help in understanding the context.

Key Focus: Stack Trace

One critical aspect to pay attention to is the Stack Trace. The stack trace is essential for understanding the error, as it shows the exact line in your code where the error occurred. However, without source map integration, Sentry can only display the minified bundle files, making it difficult to pinpoint the exact location of the error in your original code.

By providing source maps to Sentry, you enable it to accurately display the exact location in your source code where the error occurred, significantly improving your ability to debug and resolve issues. This integration ensures that Sentry can map the minified code back to your source code, offering precise insights into where and why the error happened, which is crucial for effective error resolution.

Source Map Integration With Sentry CLI

Before diving into source map integration, I’d like to explain why we minify our code and what source map files are.

A minified JavaScript bundle is a compressed version of your JavaScript code. During the build process, unnecessary characters such as spaces, new lines, and comments are removed. Minification is used to reduce the size of JavaScript files, which helps speed up web page loading times. Smaller file sizes mean faster downloads and better performance, especially for users with slow internet connections.

A source map is a file that maps your minified JavaScript code back to your source code. It shows which lines in the minified code correspond to which lines in your original code. Source maps are crucial for debugging because minified code is difficult to read and understand. They allow you to trace errors back to the source code, making it easier to identify and fix issues.

Since our seller panel projects are client-side, we minify our JavaScript files for the reasons mentioned above. To accurately identify where errors occur in Sentry, we need to upload these source map files to Sentry.

Whenever we make changes to our code, add new features, or fix bugs, we generate a new JavaScript bundle and deploy it. After each deployment, we need to send the updated source maps to Sentry. We use GitLab pipelines for deploying our projects, and we will integrate source map uploads into the deployment process. How do we do this?

This is where Sentry CLI comes to our aid. Adding the following YAML configuration to our pipeline after deployment will suffice.

.sentry_release:
image: .../image/sentry-cli
variables:
SENTRY_VERSION: $CI_COMMIT_SHORT_SHA
SENTRY_PROJECT: $CI_PROJECT_NAME
SENTRY_SOURCEMAP_PATH: dist/js/
SENTRY_SOURCEMAP_URL_PREFIX: ~/
script:
- sentry-cli releases new $SENTRY_VERSION
- sentry-cli releases files $SENTRY_VERSION upload-sourcemaps --url-prefix $SENTRY_SOURCEMAP_URL_PREFIX --ext map $SENTRY_SOURCEMAP_PATH
- sentry-cli releases set-commits --auto --ignore-empty --ignore-missing $SENTRY_VERSION
- sentry-cli releases deploys $SENTRY_VERSION new -e $SENTRY_ENVIRONMENT
- sentry-cli releases finalize $SENTRY_VERSION

Explanation of Variables Used:

  • SENTRY_VERSION: By default, this takes the value of CI_COMMIT_SHORT_SHA, ensuring it is unique. It is used to create a new release in Sentry with every commit, allowing Sentry to show from which release an error started occurring.
  • $SENTRY_SOURCEMAP_PATH: Specifies the directory where the source map files are located, indicating to the CLI where to find the source maps to upload.
  • $SENTRY_SOURCEMAP_URL_PREFIX: Specifies the URL prefix for the source map files, indicating where the files are accessible on the web server. In our case, it is the CDN URL where we host our JS files.

After integrating the source maps and deploying them, you can verify that your source maps have been uploaded by navigating to the Settings section of your project in Sentry. Follow these steps:

  1. Go to Settings in your Sentry dashboard.
  2. Select your project by entering the project name.
  3. Navigate to the Source Maps section.

Here, you can check if your source maps have been successfully uploaded.

Source Map Files in Sentry

After uploading the source map files, if you reproduce the same error, you will be able to see exactly where the error occurred in your code within the stack trace section, as shown in the image below. This provides a clear and precise view of the error’s location in the source code, making debugging significantly easier.

Same Error with Stack Trace

In this article, we covered Sentry integration and how we use Sentry.
Thank you for sticking with me this far! 🎉

--

--