This post is also posted on my blog at 😄

The need for front-end error monitoring

Front-end monitoring is relative to back-end monitoring. In the past, back-end monitoring could only record errors occurred after the interface was requested. However, nowadays, with the increasing complexity of users, many errors are JS errors occurred before the back-end interface was requested. For this kind of error, the traditional backend error monitoring is powerless, so the front-end monitoring comes into being.

Why Sentry

We recently wanted to deploy front-end monitoring on our company’s projects to proactively catch client errors (to satisfy our own desire for control 😄), rather than waiting for user feedback (which was very little 😓). Originally consider oneself write one, helpless level is limited, coupled with see already have a lot of mature plan, so… You know! At present, there are relatively mature front-end monitoring schemes. For details, refer to the post on Zhihu on how to do front-end abnormal monitoring. Generally, the options are as follows:

  1. Sentry
  2. Fundebug
  3. Bugsnag
  4. BetterJS

It seems that only Sentry and BetterJS offer self-deployment solutions because they are intended to be deployed on the company’s own servers. Then, given that front-end projects are now packaged and released, it was necessary to be able to locate errors with Sourcemaps, so Sentry was chosen. (Fundebug also supports sourcemaps in the above scenario)

How to use

As a trial, I chose to use the service provided by Sentry. After registering my account, I chose to use the free version of the service and started front-end error monitoring for our project.

Error monitoring module is introduced preliminarily

The first step, of course, is to look at the Docs provided by Sentry, and the steps to create the project are pretty clear.

  1. Create a new project
  2. Choose a language or framework
  3. Then follow the docs

OK, after creating a new project, it’s time to introduce the monitoring module into my front-end project. Here, because my project is a SPA project using Vue, I use raven.js, which is officially recommended by Sentry. After downloading this module, introduce files in the project according to the official guidelines. Key and project will be automatically generated by the official after you register your account, which is very considerate.

// main.js

import Raven from 'raven-js'
import RavenVue from 'raven-js/plugins/vue'

Raven
  .config('https://<key>@sentry.io/<project>')
  .addPlugin(RavenVue, Vue)
  .install()
  
Copy the code

You can simply bury an error in an obscure corner of your project, trigger it, and see that raven.js was called to send an error, as well as in your Sentry project.

However, such an error message is not meaningful, in addition to the specific cause of the error can be seen, the location of the error can not be located. If the error message is not specific enough for us to immediately locate the error, we can only go through the code over and over again, which is time-consuming and costly. This is the time to use Sourcemaps to locate errors, which Sentry supports very well.

Sourcemaps are introduced to locate errors

First, let’s look at the official documentation for the introduction of Sourcemaps. Sentry allows us to use the Sourcemaps, Releases API, Sentry-CLI, and Sentry-webpack-plugin in three ways. Given that sourcemaps were submitted along with the project build, I personally only practiced the last one.

Start by creating a new authentication token under **[Account] > API**. 2. Ensure you have project:write selected under scopes. 3. Install @sentry/webpack-plugin using npm 4. Create .sentryclirc file with necessary config (see Sentry Webpack Plugin docs below) 5. Update your webpack.config.jsonCopy the code

Let’s put it into practice:

The first two steps, very simple, skip skip skip.

For the third step, I personally find that it is not enough to just install @sentry/webpack-plugin. I also need to install @sentry/cli.

The fourth step, perhaps I am not familiar with this configuration format, the longest toss is this step. To give the official configuration instructions, here is my basic configuration (in fact, I will split defaults.url, auth.token, etc., into the configuration file), in the root directory of the project:

// .sentryclirc [defaults] url = https://sentry.io/ <! This can be seen from the full path to your sentry. IO, as in: https://sentry.io/ here is your org/ here is your project/ --> org = project = [auth] token = here is the token you created in step 1 and step 2Copy the code

Step 5, update my Webpack configuration and configure my monitor module

A Plugin is used to implement the Plugin.

For the record, the methods in this article are all very well, but for the problem of intercepting a 7 digit parameter as a version number, my personal practice is that raven.js cannot pass the correct version number after intercepting, and instead can pass the correct version number without intercepting! When you look at the POST in Raven.js, you see that the release is very long, more than seven bits.

The urlPrefix attribute in the following step is particularly critical because it prefixes uploaded files because sentry matches the path in a particular version number in addition to the version number. The default value of this attribute is ~ /, and ~ is just in front of the agreement and remove the url domain, namely pieced together the map resource path is http://host/static/js/app.js.map. But if, like my site, you have one more level of path, you need to configure this property, otherwise the maps uploaded to Sentry won’t be accessible.

// webpack.prod.conf.js

const SentryPlugin = require('@sentry/webpack-plugin');

plugins: [
    new SentryPlugin({
      include: './dist'.release: process.env.RELEASE_VERSION,
      configFile: 'sentry.properties'.urlPrefix: '~/TechPage/'.// Do not pass this parameter if you do not need it}),]Copy the code

This is the following step. You shouldn’t intercept it

// prod.env.js

let gitSha = require('child_process').execSync('git rev-parse HEAD').toString().trim()

// process.env.release_version = gitsha.substr (2, 9) should not be intercepted

process.env.RELEASE_VERSION = gitSha

module.exports = {
  RELEASE_VERSION: `"${gitSha}"`.NODE_ENV: '"production"'
}

Copy the code
// main.js
import Raven from 'raven-js'
import RavenVue from 'raven-js/plugins/vue'

Raven
  .config('https://<key>@sentry.io/<project>', {
    release: process.env.RELEASE_VERSION,
    debug: true
  })
  .addPlugin(RavenVue, Vue)
  .install()

Copy the code

Since Sentry uses version-specific sourcemaps to locate errors through release matching, we need to generate a specific version number at project build time and assign this version number to raven.js and SentryPlugin so that a corresponding relationship can be formed. Of course, you can also generate the corresponding release number in another way, which is ok, as long as the corresponding version is unique. Even if you don’t have a mapping, Sentry by default will find the map file based on the sourceMappingURL in the JS file once you publish the Source maps, and then locate the error.

The official configuration documentation for Raven.js is also detailed. Click here for details. Here I just configured release and debug, and if YOU set debug to true, raven.js will print some debug messages to the console.

At this point, you trigger the error in the project and get the following effect. The error message has been successfully located, very clearly.

Upload the sourcemaps using the webpack-sentry-plugin and delete them after upload, preventing end users from accessing maps files

This is a reference to the brother mentioned above, but he was right to delete sourcemaps after uploading them to Sentry, out of reach of end users. But after I delete, after the error occurred on the client side, there is no way to return the error information after positioning. The returned error information is the code after compilation and packaging, and the readability is general. If you find any configuration errors, please point them out.

When I didn’t publish source maps, it was because the urlPrefix(@sentry/webpack-plugin) was not configured correctly. The error could not be located.



const SentryPlugin = require('webpack-sentry-plugin');

plugins: [
    new SentryPlugin(Object.assign({
      release: process.env.RELEASE_VERSION,
      deleteAfterCompile: true.suppressErrors: true./** filenameTransform: function (filename) { var pub = config.build.assetsPublicPath if (/^\/\//.test(pub)) pub = 'http:' + pub var urlObj = require('url').parse(pub) return '~' + urlObj.pathname.replace(/\/+$/, '') + '/' + filename } */
      filenameTransform: function (filename) {
         return '~/TechPage/' + filename
      },
    }, require('.. /sentry.conf.js'))),]Copy the code
// sentry.conf.js(in the root directory)

module.exports = {

// This can be seen from the full path to your sentry. IO, e.g. https://sentry.io/ here is your org/ here is your project
  organisation: ' '.project: ' '.apiKey: ' '
}

Copy the code

For this configuration, I get an error message like this, as shown below:

It is configured to get full error location without publishing Source maps!

The last

If you want to deploy Sentry to your own server, the Sentry official has detailed documentation, please go.

If you find my mistakes in the article, please do not bother, please develop fancy ridicule! Thank you very much!

Please also visit my Demo website and click on the creation time bar to trigger the error and see the Sentry effect. Thank you!

Thank you for reminding @time is the sea and referring to issues in the Sentry community to notice the urlPrefix issue. Attached are two posts from the community:

  1. JS source maps issue
  2. Doesn’t find match source map file (with tilde ~)