@@ -7,9 +7,15 @@ import type { ActivatedRouteSnapshot, Event, RouterState } from '@angular/router
7
7
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
8
8
import { NavigationCancel , NavigationError , Router } from '@angular/router' ;
9
9
import { NavigationEnd , NavigationStart , ResolveEnd } from '@angular/router' ;
10
- import { WINDOW , getCurrentScope } from '@sentry/browser' ;
11
- import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE , spanToJSON } from '@sentry/core' ;
12
- import type { Span , Transaction , TransactionContext } from '@sentry/types' ;
10
+ import {
11
+ WINDOW ,
12
+ browserTracingIntegration as originalBrowserTracingIntegration ,
13
+ disableDefaultBrowserTracingNavigationSpan ,
14
+ getCurrentScope ,
15
+ startBrowserTracingNavigationSpan ,
16
+ } from '@sentry/browser' ;
17
+ import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE , getActiveSpan , spanToJSON , startInactiveSpan } from '@sentry/core' ;
18
+ import type { Integration , Span , Transaction , TransactionContext } from '@sentry/types' ;
13
19
import { logger , stripUrlQueryAndFragment , timestampInSeconds } from '@sentry/utils' ;
14
20
import type { Observable } from 'rxjs' ;
15
21
import { Subscription } from 'rxjs' ;
@@ -23,8 +29,12 @@ let instrumentationInitialized: boolean;
23
29
let stashedStartTransaction : ( context : TransactionContext ) => Transaction | undefined ;
24
30
let stashedStartTransactionOnLocationChange : boolean ;
25
31
32
+ let hooksBasedInstrumentation = false ;
33
+
26
34
/**
27
35
* Creates routing instrumentation for Angular Router.
36
+ *
37
+ * @deprecated Use `browserTracingIntegration()` instead, which includes Angular-specific instrumentation out of the box.
28
38
*/
29
39
export function routingInstrumentation (
30
40
customStartTransaction : ( context : TransactionContext ) => Transaction | undefined ,
@@ -47,8 +57,30 @@ export function routingInstrumentation(
47
57
}
48
58
}
49
59
60
+ /**
61
+ * Creates routing instrumentation for Angular Router.
62
+ *
63
+ * @deprecated Use `browserTracingIntegration()` instead, which includes Angular-specific instrumentation out of the box.
64
+ */
65
+ // eslint-disable-next-line deprecation/deprecation
50
66
export const instrumentAngularRouting = routingInstrumentation ;
51
67
68
+ /**
69
+ * A custom BrowserTracing integration for Angular.
70
+ *
71
+ * Use this integration in combination with `TraceService`
72
+ */
73
+ export function browserTracingIntegration (
74
+ options ?: Parameters < typeof originalBrowserTracingIntegration > [ 0 ] ,
75
+ ) : Integration {
76
+ instrumentationInitialized = true ;
77
+ hooksBasedInstrumentation = true ;
78
+
79
+ disableDefaultBrowserTracingNavigationSpan ( ) ;
80
+
81
+ return originalBrowserTracingIntegration ( options ) ;
82
+ }
83
+
52
84
/**
53
85
* Grabs active transaction off scope.
54
86
*
@@ -74,7 +106,43 @@ export class TraceService implements OnDestroy {
74
106
return ;
75
107
}
76
108
109
+ if ( this . _routingSpan ) {
110
+ this . _routingSpan . end ( ) ;
111
+ this . _routingSpan = null ;
112
+ }
113
+
77
114
const strippedUrl = stripUrlQueryAndFragment ( navigationEvent . url ) ;
115
+
116
+ if ( hooksBasedInstrumentation ) {
117
+ if ( ! getActiveSpan ( ) ) {
118
+ startBrowserTracingNavigationSpan ( {
119
+ name : strippedUrl ,
120
+ op : 'navigation' ,
121
+ origin : 'auto.navigation.angular' ,
122
+ attributes : {
123
+ [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] : 'url' ,
124
+ } ,
125
+ } ) ;
126
+ }
127
+
128
+ // eslint-disable-next-line deprecation/deprecation
129
+ this . _routingSpan =
130
+ startInactiveSpan ( {
131
+ name : `${ navigationEvent . url } ` ,
132
+ op : ANGULAR_ROUTING_OP ,
133
+ origin : 'auto.ui.angular' ,
134
+ tags : {
135
+ 'routing.instrumentation' : '@sentry/angular' ,
136
+ url : strippedUrl ,
137
+ ...( navigationEvent . navigationTrigger && {
138
+ navigationTrigger : navigationEvent . navigationTrigger ,
139
+ } ) ,
140
+ } ,
141
+ } ) || null ;
142
+
143
+ return ;
144
+ }
145
+
78
146
// eslint-disable-next-line deprecation/deprecation
79
147
let activeTransaction = getActiveTransaction ( ) ;
80
148
@@ -90,9 +158,6 @@ export class TraceService implements OnDestroy {
90
158
}
91
159
92
160
if ( activeTransaction ) {
93
- if ( this . _routingSpan ) {
94
- this . _routingSpan . end ( ) ;
95
- }
96
161
// eslint-disable-next-line deprecation/deprecation
97
162
this . _routingSpan = activeTransaction . startChild ( {
98
163
description : `${ navigationEvent . url } ` ,
0 commit comments