Skip to content

Commit d1ba98f

Browse files
committed
fix(angular): run tracing stuff outside Angular
This commit updates all tracing functionality to run outside the Angular zone. Before this change, it hindered server-side rendering and hydration, causing instability in the app. The app achieves stability when there are no micro/macro tasks running. As a result, the HTML can now be serialized and sent to the client.
1 parent 2288caf commit d1ba98f

File tree

1 file changed

+52
-42
lines changed

1 file changed

+52
-42
lines changed

packages/angular/src/tracing.ts

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,14 @@ export class TraceService implements OnDestroy {
8989
if (client) {
9090
// see comment in `_isPageloadOngoing` for rationale
9191
if (!this._isPageloadOngoing()) {
92-
startBrowserTracingNavigationSpan(client, {
93-
name: strippedUrl,
94-
attributes: {
95-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.angular',
96-
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
97-
},
92+
runOutsideAngular(() => {
93+
startBrowserTracingNavigationSpan(client, {
94+
name: strippedUrl,
95+
attributes: {
96+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.angular',
97+
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
98+
},
99+
});
98100
});
99101
} else {
100102
// The first time we end up here, we set the pageload flag to false
@@ -104,18 +106,20 @@ export class TraceService implements OnDestroy {
104106
}
105107

106108
this._routingSpan =
107-
startInactiveSpan({
108-
name: `${navigationEvent.url}`,
109-
op: ANGULAR_ROUTING_OP,
110-
attributes: {
111-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular',
112-
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
113-
url: strippedUrl,
114-
...(navigationEvent.navigationTrigger && {
115-
navigationTrigger: navigationEvent.navigationTrigger,
116-
}),
117-
},
118-
}) || null;
109+
runOutsideAngular(() =>
110+
startInactiveSpan({
111+
name: `${navigationEvent.url}`,
112+
op: ANGULAR_ROUTING_OP,
113+
attributes: {
114+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular',
115+
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
116+
url: strippedUrl,
117+
...(navigationEvent.navigationTrigger && {
118+
navigationTrigger: navigationEvent.navigationTrigger,
119+
}),
120+
},
121+
}),
122+
) || null;
119123

120124
return;
121125
}
@@ -252,11 +256,13 @@ export class TraceDirective implements OnInit, AfterViewInit {
252256
}
253257

254258
if (getActiveSpan()) {
255-
this._tracingSpan = startInactiveSpan({
256-
name: `<${this.componentName}>`,
257-
op: ANGULAR_INIT_OP,
258-
attributes: { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular.trace_directive' },
259-
});
259+
this._tracingSpan = runOutsideAngular(() =>
260+
startInactiveSpan({
261+
name: `<${this.componentName}>`,
262+
op: ANGULAR_INIT_OP,
263+
attributes: { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular.trace_directive' },
264+
}),
265+
);
260266
}
261267
}
262268

@@ -266,7 +272,7 @@ export class TraceDirective implements OnInit, AfterViewInit {
266272
*/
267273
public ngAfterViewInit(): void {
268274
if (this._tracingSpan) {
269-
this._tracingSpan.end();
275+
runOutsideAngular(() => this._tracingSpan!.end());
270276
}
271277
}
272278
}
@@ -298,14 +304,16 @@ export function TraceClass(options?: TraceClassOptions): ClassDecorator {
298304
const originalOnInit = target.prototype.ngOnInit;
299305
// eslint-disable-next-line @typescript-eslint/no-explicit-any
300306
target.prototype.ngOnInit = function (...args: any[]): ReturnType<typeof originalOnInit> {
301-
tracingSpan = startInactiveSpan({
302-
onlyIfParent: true,
303-
name: `<${options && options.name ? options.name : 'unnamed'}>`,
304-
op: ANGULAR_INIT_OP,
305-
attributes: {
306-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular.trace_class_decorator',
307-
},
308-
});
307+
tracingSpan = runOutsideAngular(() =>
308+
startInactiveSpan({
309+
onlyIfParent: true,
310+
name: `<${options && options.name ? options.name : 'unnamed'}>`,
311+
op: ANGULAR_INIT_OP,
312+
attributes: {
313+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular.trace_class_decorator',
314+
},
315+
}),
316+
);
309317

310318
if (originalOnInit) {
311319
return originalOnInit.apply(this, args);
@@ -316,7 +324,7 @@ export function TraceClass(options?: TraceClassOptions): ClassDecorator {
316324
// eslint-disable-next-line @typescript-eslint/no-explicit-any
317325
target.prototype.ngAfterViewInit = function (...args: any[]): ReturnType<typeof originalAfterViewInit> {
318326
if (tracingSpan) {
319-
tracingSpan.end();
327+
runOutsideAngular(() => tracingSpan.end());
320328
}
321329
if (originalAfterViewInit) {
322330
return originalAfterViewInit.apply(this, args);
@@ -344,15 +352,17 @@ export function TraceMethod(options?: TraceMethodOptions): MethodDecorator {
344352
descriptor.value = function (...args: any[]): ReturnType<typeof originalMethod> {
345353
const now = timestampInSeconds();
346354

347-
startInactiveSpan({
348-
onlyIfParent: true,
349-
name: `<${options && options.name ? options.name : 'unnamed'}>`,
350-
op: `${ANGULAR_OP}.${String(propertyKey)}`,
351-
startTime: now,
352-
attributes: {
353-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular.trace_method_decorator',
354-
},
355-
}).end(now);
355+
runOutsideAngular(() => {
356+
startInactiveSpan({
357+
onlyIfParent: true,
358+
name: `<${options && options.name ? options.name : 'unnamed'}>`,
359+
op: `${ANGULAR_OP}.${String(propertyKey)}`,
360+
startTime: now,
361+
attributes: {
362+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular.trace_method_decorator',
363+
},
364+
}).end(now);
365+
});
356366

357367
if (originalMethod) {
358368
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access

0 commit comments

Comments
 (0)