Back to Blog Home

Making your JavaScript projects less noisy

Scott Cooper image

Scott Cooper -

Making your JavaScript projects less noisy

If you're using Sentry for JavaScript error monitoring, you may be familiar with a common challenge: sifting through noisy, low-value errors that hinder identifying high-priority issues for you and your team.

Capturing errors in JavaScript browser project can be tricky. Why? Well, it's not just a single environment. There are numerous major browsers, JavaScript engines, operating systems, and browser extension ecosystems that all come together, making it challenging to capture relevant errors effectively.

Sentry performs a number of tricks right out of the box to reduce this noise as much as possible. But with a few additional steps, you can go even further in achieving error monitoring bliss.
By implementing these steps, you'll create a more efficient error monitoring experience so you and your team can focus on resolving critical issues faster. Let's dive in.

Upload source maps and tag releases

Source maps don’t just make debugging your production stack traces easier by un-minifying your code. Source maps also make it easier for Sentry to group errors into individual issues. This means that events bucket into a smaller, more manageable set of issues, causing less noise in your issue stream.

The easiest way to configure uploading source maps is by using the Sentry Wizard. Run this one line command to install the necessary Sentry packages, and configure your build tool/CI to generate and upload source maps:

npx @sentry/wizard@latest -i sourcemaps

Prefer to go the manual route? Check our in-depth source map documentation to get started. Besides helping to reduce noise, source maps may be the single most impactful improvement you make to your monitoring and debugging workflow.

After you’re uploading source maps, be sure to start passing the release version to the Sentry SDK. It should look something like this, you might consider passing it in via an environment variable during production for the production build.

Sentry.init({ release: "my-project-name@2.3.12", });

Pass the original error cause

When using a try…catch statement, you might throw a new error instead of re-throwing the same error. We can preserve the context of the original error and add a cause in our new error. This is supported in the browser since Chrome 93, Safari 15, and Firefox 91.

try { await getReplay(); } catch (err) { throw new Error("API Request Error.", { cause: err }); }

Linked errors are supported by default in our SDK and the error stacks are grouped and displayed with their original message. Passing the original error as the cause can add more context to the stack trace and help with debugging.

Ignore un-actionable errors

We’ve seen all kinds of interesting errors at Sentry. Users using homemade electron browsers, custom JavaScript injected directly into the page, browser extensions running wild, and vendor code that throws useless errors. You might have seen some of these errors before in your application, and if they’re causing noise, you could ignore them in the SDK using ignoreErrors.

Some of the errors developers at Sentry have silenced in our own environment:

  • TypeError: can't access dead object an error thrown by Firefox when a browser extension has accessed a DOM element that has been removed. These errors are usually not actionable if you aren’t creating a browser extension.

  • Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node. This is an error thrown by React when browsers like Chrome have the translate feature enabled and React attempts to update the component. This error can be fixed by wrapping string literals with spans, but in large applications this may be difficult to enforce. The Sentry app also offers translations that can be enabled in user settings.

You can filter these errors out directly on the client by declaring ignoreErrors to filter them before they ever get reported.

Sentry.init({ ignoreErrors: [ /** * Thrown when firefox prevents an add-on from refrencing a DOM element that has been removed. * This can also be filtered by enabling the browser extension inbound filter */ "TypeError: can't access dead object", /** * React internal error thrown when something outside react modifies the DOM * This is usually because of a browser extension or Chrome's built-in translate */ "NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.", "NotFoundError: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.", ], });

Enable project inbound filters

Project level filters can prevent issues from ever appearing in your issues stream, similar to ignoreErrors in the Sentry JavaScript SDK. They can be turned on by going to Settings → Projects → Project Settings → Inbound Filters. We recommend turning on Filter out errors known to be caused by browser extensions and Filter out events coming from localhost in order to silence errors likely caused by browser errors not coming from your application’s code.

You can also make your own rules on the inbound filters page to filter out custom error messages. Set one up using the wildcard star “*”, e.g. - *ResizeObserver loop limit exceeded to filter all errors that contain that particular message. As a warning, errors filtered out cannot be recovered.

Ignore errors that don't come from your code

A lot of noisy errors come from JavaScript that wasn't written by yourself. Browser extensions, code-injecting browsers, or widgets from third-party services all may throw errors that you cannot address.

There are two possibilities to filter out these kinds of errors:

  1. Using the allowUrls and denyUrls options

  2. Using the thirdPartyErrorFilterIntegration (recommended)

Using allowUrls and denyUrls

You can define an array of patterns matching the URLs of scripts where errors have been created.
Only errors that match one of the patterns will be recorded and sent to Sentry.
If your scripts are loaded from cdn.example.com and your site is example.com, you can set allowUrls to:

Sentry.init({ allowUrls: [/https?:\/\/((cdn|www)\.)?example\.com/], });

If you want to block errors from specific URLs you can use denyUrls.

Using the thirdPartyErrorFilterIntegration

The thirdPartyErrorFilterIntegration is an approach to automatically filter out errors that are unrelated to the code that you wrote.

This feature is available in all browser-based SDKs from version 8.10.0 onwards and requires you to use a bundler and one of Sentry's bundler plugins.

This integration works by "marking" your JavaScript files with an "application key" during the build process.
At runtime, if an error occurs, the thirdPartyErrorFilterIntegration checks application keys for each stack frame in the stack trace.
This allows you to filter out errors with "unmarked" stack frames, which would indicate third-party code.

To get started using the thirdPartyErrorFilterIntegration check out the Docs.

Handling request errors

It’s common for developers to report request errors to Sentry as a way of monitoring for spikes in things like 404s. Today, you can set up metric alerts for our backend to measure if there is a spike in transactions with transaction.status:not_found instead of reporting them from the frontend.

You can either stop reporting them to Sentry by handling the response or by filtering out the specific request errors in beforeSend. By returning null, the SDK will filter out specific errors.

Sentry.init({ beforeSend(event, _hint) { if (isFilteredRequestError(event) { // Return null to stop the error from being sent to Sentry return null; } return event; }, }); function isFilteredRequestError(event) { // In case there's a chain, we take the last entries const mainAndMaybeCauseErrors = event.exception?.values?.slice(-2) ?? []; for (const error of mainAndMaybeCauseErrors) { const is404 = type === 'NotFoundError' && !!value.match('(GET|POST|PUT|DELETE) .* 404'); const is429 = type === 'TooManyRequestsError' && !!value.match('(GET|POST|PUT|DELETE) .* 429'); if (is404 || is429) { return true; } } return false; }

Finding noisy events via Discover

If you’re on a Sentry Business Plan, you can use Sentry’s Discover to find issues that all share the same title and message to help us find the noisiest areas of our codebase.

Open discover and filter by event.type:error which will limit it to only events that are linked to an issue.

Then, change the columns to count the number of unique issues, grouping by the other two selected columns, title and message.

Once we have the columns setup, we can see that we had 204 issues coming from a performance API we were using in our frontend.

We ended up silencing this error altogether by checking that the browser performance API was available before calling it.

Catch JavaScript errors that matter

You’ve made your errors more actionable and enabled better grouping by making sure our production errors have source maps. You’ve started ignoring unactionable JavaScript framework errors, spam caused by browser extensions, and stopped recording some errors at the SDK level.

Staying on top of noise can save time later on by reducing notifications and leaving only the errors that matter at the top of your issues stream.

Then, change the columns to count the number of unique issues, grouping by the other two selected columns, title and message.

Don't forget to join the conversation on Discord and GitHub or visit our JavaScript debugging hub to keep up to date with the latest support for JavaScript.

Share

Share on Twitter
Share on Facebook
Share on HackerNews
Share on LinkedIn

Published

Sentry Sign Up CTA

Code breaks, fix it faster

Sign up for Sentry and monitor your application in minutes.

Try Sentry Free

Topics

SDK Updates

New product releases and exclusive demos

Listen to the Syntax Podcast

Of course we sponsor a developer podcast. Check it out on your favorite listening platform.

Listen To Syntax
    TwitterGitHubDribbbleLinkedinDiscord
© 2024 • Sentry is a registered Trademark of Functional Software, Inc.