@@ -6,6 +6,19 @@ import { logger, stripUrlQueryAndFragment, timestampWithMs } from '@sentry/utils
66import { Observable , Subscription } from 'rxjs' ;
77import { filter , tap } from 'rxjs/operators' ;
88
9+ // That's the `global.Zone` exposed when the `zone.js` package is used.
10+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11+ declare const Zone : any ;
12+
13+ // There're 2 types of Angular applications:
14+ // 1) zone-full (by default)
15+ // 2) zone-less
16+ // The developer can avoid importing the `zone.js` package and tells Angular that
17+ // he is responsible for running the change detection by himself. This is done by
18+ // "nooping" the zone through `CompilerOptions` when bootstrapping the root module.
19+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
20+ const isNgZoneEnabled = typeof Zone !== 'undefined' && ! ! Zone . current ;
21+
922let instrumentationInitialized : boolean ;
1023let stashedStartTransaction : ( context : TransactionContext ) => Transaction | undefined ;
1124let stashedStartTransactionOnLocationChange : boolean ;
@@ -93,13 +106,27 @@ export class TraceService implements OnDestroy {
93106 filter ( event => event instanceof NavigationEnd ) ,
94107 tap ( ( ) => {
95108 if ( this . _routingSpan ) {
96- this . _routingSpan . finish ( ) ;
97- delete this . _routingSpan ;
109+ if ( isNgZoneEnabled ) {
110+ // The `Zone.root.run` basically will finish the transaction in the most parent zone.
111+ // The Angular's zone is forked from the `Zone.root`. In this case, `zone.js` won't
112+ // trigger change detection, and `ApplicationRef.tick()` will not be run.
113+ // Caretaker note: we're using `Zone.root` except `NgZone.runOutsideAngular` since this
114+ // will require injecting the `NgZone` facade. That will create a breaking change for
115+ // projects already using the `TraceService`.
116+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
117+ Zone . root . run ( ( ) => {
118+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
119+ this . _routingSpan ! . finish ( ) ;
120+ } ) ;
121+ } else {
122+ this . _routingSpan . finish ( ) ;
123+ }
124+ this . _routingSpan = null ;
98125 }
99126 } ) ,
100127 ) ;
101128
102- private _routingSpan ? : Span ;
129+ private _routingSpan : Span | null = null ;
103130 private _subscription : Subscription = new Subscription ( ) ;
104131
105132 public constructor ( private readonly _router : Router ) {
0 commit comments