Skip to content

Commit

Permalink
perf(angular): do not run change detection when finishing transaction (
Browse files Browse the repository at this point in the history
  • Loading branch information
arturovt committed Jun 4, 2021
1 parent e44bc63 commit 6433cd0
Showing 1 changed file with 30 additions and 3 deletions.
33 changes: 30 additions & 3 deletions packages/angular/src/tracing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ import { logger, stripUrlQueryAndFragment, timestampWithMs } from '@sentry/utils
import { Observable, Subscription } from 'rxjs';
import { filter, tap } from 'rxjs/operators';

// That's the `global.Zone` exposed when the `zone.js` package is used.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
declare const Zone: any;

// There're 2 types of Angular applications:
// 1) zone-full (by default)
// 2) zone-less
// The developer can avoid importing the `zone.js` package and tells Angular that
// he is responsible for running the change detection by himself. This is done by
// "nooping" the zone through `CompilerOptions` when bootstrapping the root module.
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const isNgZoneEnabled = typeof Zone !== 'undefined' && !!Zone.current;

let instrumentationInitialized: boolean;
let stashedStartTransaction: (context: TransactionContext) => Transaction | undefined;
let stashedStartTransactionOnLocationChange: boolean;
Expand Down Expand Up @@ -93,13 +106,27 @@ export class TraceService implements OnDestroy {
filter(event => event instanceof NavigationEnd),
tap(() => {
if (this._routingSpan) {
this._routingSpan.finish();
delete this._routingSpan;
if (isNgZoneEnabled) {
// The `Zone.root.run` basically will finish the transaction in the most parent zone.
// The Angular's zone is forked from the `Zone.root`. In this case, `zone.js` won't
// trigger change detection, and `ApplicationRef.tick()` will not be run.
// Caretaker note: we're using `Zone.root` except `NgZone.runOutsideAngular` since this
// will require injecting the `NgZone` facade. That will create a breaking change for
// projects already using the `TraceService`.
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
Zone.root.run(() => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this._routingSpan!.finish();
});
} else {
this._routingSpan.finish();
}
this._routingSpan = null;
}
}),
);

private _routingSpan?: Span;
private _routingSpan: Span | null = null;
private _subscription: Subscription = new Subscription();

public constructor(private readonly _router: Router) {
Expand Down

0 comments on commit 6433cd0

Please sign in to comment.