Skip to content

Commit d1d6c41

Browse files
authored
fix(angular): prevent memory leak when the root view is removed (#3594)
1 parent 4b7edf2 commit d1d6c41

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed

packages/angular/src/tracing.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { AfterViewInit, Directive, Injectable, Input, OnInit } from '@angular/core';
1+
import { AfterViewInit, Directive, Injectable, Input, OnDestroy, OnInit } from '@angular/core';
22
import { Event, NavigationEnd, NavigationStart, Router } from '@angular/router';
33
import { getCurrentHub } from '@sentry/browser';
44
import { Span, Transaction, TransactionContext } from '@sentry/types';
55
import { logger, stripUrlQueryAndFragment, timestampWithMs } from '@sentry/utils';
6-
import { Observable } from 'rxjs';
6+
import { Observable, Subscription } from 'rxjs';
77
import { filter, tap } from 'rxjs/operators';
88

99
let instrumentationInitialized: boolean;
@@ -53,7 +53,7 @@ export function getActiveTransaction(): Transaction | undefined {
5353
* Creates a new transaction for every route change and measures a duration of routing process.
5454
*/
5555
@Injectable({ providedIn: 'root' })
56-
export class TraceService {
56+
export class TraceService implements OnDestroy {
5757
public navStart$: Observable<Event> = this._router.events.pipe(
5858
filter(event => event instanceof NavigationStart),
5959
tap(event => {
@@ -100,10 +100,19 @@ export class TraceService {
100100
);
101101

102102
private _routingSpan?: Span;
103+
private _subscription: Subscription = new Subscription();
103104

104105
public constructor(private readonly _router: Router) {
105-
this.navStart$.subscribe();
106-
this.navEnd$.subscribe();
106+
this._subscription.add(this.navStart$.subscribe());
107+
this._subscription.add(this.navEnd$.subscribe());
108+
}
109+
110+
/**
111+
* This is used to prevent memory leaks when the root view is created and destroyed multiple times,
112+
* since `subscribe` callbacks captures `this` and prevent many resources from being GC'd.
113+
*/
114+
public ngOnDestroy(): void {
115+
this._subscription.unsubscribe();
107116
}
108117
}
109118

0 commit comments

Comments
 (0)