Share on Twitter
Share on Facebook
Share on HackerNews

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.

Sentry Linked Errors

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.

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.

Sentry Discover Filter

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.

Sentry Filter Results

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 to keep up to date with the latest support for JavaScript.

Your code is broken. Let's Fix it.
Get Started

More from the Sentry blog

ChangelogCodecovDashboardsDiscoverDogfooding ChroniclesEcosystemError MonitoringEventsGuest PostsMobileMoonlightingOpen SourcePerformance MonitoringRelease HealthSDK UpdatesSentry
© 2023 • Sentry is a registered Trademark
of Functional Software, Inc.