Skip to content

Commit 113be3a

Browse files
perf(angular): do not run change detection when capturing the exception (#3618)
Co-authored-by: Kamil Ogórek <[email protected]>
1 parent 6433cd0 commit 113be3a

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

packages/angular/src/errorhandler.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@ import { HttpErrorResponse } from '@angular/common/http';
22
import { ErrorHandler as AngularErrorHandler, Injectable } from '@angular/core';
33
import * as Sentry from '@sentry/browser';
44

5+
// That's the `global.Zone` exposed when the `zone.js` package is used.
6+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
7+
declare const Zone: any;
8+
9+
// There're 2 types of Angular applications:
10+
// 1) zone-full (by default)
11+
// 2) zone-less
12+
// The developer can avoid importing the `zone.js` package and tells Angular that
13+
// he is responsible for running the change detection by himself. This is done by
14+
// "nooping" the zone through `CompilerOptions` when bootstrapping the root module.
15+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
16+
const isNgZoneEnabled = typeof Zone !== 'undefined' && !!Zone.current;
17+
518
/**
619
* Options used to configure the behavior of the Angular ErrorHandler.
720
*/
@@ -38,7 +51,16 @@ class SentryErrorHandler implements AngularErrorHandler {
3851
const extractedError = this._extractError(error) || 'Handled unknown error';
3952

4053
// Capture handled exception and send it to Sentry.
41-
const eventId = Sentry.captureException(extractedError);
54+
const eventId = isNgZoneEnabled
55+
? // The `Zone.root.run` basically will capture the exception in the most parent zone.
56+
// The Angular's zone is forked from the `Zone.root`. In this case, `zone.js` won't
57+
// trigger change detection, and `ApplicationRef.tick()` will not be run.
58+
// Caretaker note: we're using `Zone.root` except `NgZone.runOutsideAngular` since this
59+
// will require injecting the `NgZone` facade. That will create a breaking change for
60+
// projects already using the `SentryErrorHandler`.
61+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
62+
Zone.root.run(() => Sentry.captureException(extractedError))
63+
: Sentry.captureException(extractedError);
4264

4365
// When in development mode, log the error to console for immediate feedback.
4466
if (this._options.logErrors) {

0 commit comments

Comments
 (0)