@@ -31,8 +31,10 @@ const HOOKS: { [key in Operation]: Hook[] } = {
31
31
update : [ 'beforeUpdate' , 'updated' ] ,
32
32
} ;
33
33
34
- /** Finish top-level span and activity with a debounce configured using `timeout` option */
35
- function finishRootSpan ( vm : VueSentry , timestamp : number , timeout : number ) : void {
34
+ /**
35
+ * End the top-level span and with a debounce configured using `timeout` option
36
+ */
37
+ function maybeEndRootSpan ( vm : VueSentry , timestamp : number , timeout : number ) : void {
36
38
if ( vm . $_sentryRootSpanTimer ) {
37
39
clearTimeout ( vm . $_sentryRootSpanTimer ) ;
38
40
}
@@ -66,6 +68,8 @@ export const createTracingMixins = (options: Partial<TracingOptions> = {}): Mixi
66
68
67
69
const mixins : Mixins = { } ;
68
70
71
+ const rootComponentSpanFinalTimeout = options . timeout || 2000 ;
72
+
69
73
for ( const operation of hooks ) {
70
74
// Retrieve corresponding hooks from Vue lifecycle.
71
75
// eg. mount => ['beforeMount', 'mounted']
@@ -80,6 +84,14 @@ export const createTracingMixins = (options: Partial<TracingOptions> = {}): Mixi
80
84
const isRoot = this . $root === this ;
81
85
82
86
if ( isRoot ) {
87
+ /**
88
+ * The root component span is basically an idle child span that remains active
89
+ * as long as child components are processed (mounted, updated, etc).
90
+ * Every time a child component span ends, we debounce the ending of the root
91
+ * component span so that the root span duration still reflects potential future
92
+ * child spans.
93
+ * See {@link maybeEndRootSpan} for the debounging mechanism.
94
+ */
83
95
this . $_sentryRootSpan =
84
96
this . $_sentryRootSpan ||
85
97
startInactiveSpan ( {
@@ -90,6 +102,9 @@ export const createTracingMixins = (options: Partial<TracingOptions> = {}): Mixi
90
102
} ,
91
103
onlyIfParent : true ,
92
104
} ) ;
105
+
106
+ // call debounced end function once directly, just in case no child components call it
107
+ maybeEndRootSpan ( this , timestampInSeconds ( ) , rootComponentSpanFinalTimeout ) ;
93
108
}
94
109
95
110
// Skip components that we don't want to track to minimize the noise and give a more granular control to the user
@@ -101,6 +116,8 @@ export const createTracingMixins = (options: Partial<TracingOptions> = {}): Mixi
101
116
102
117
// We always want to track root component
103
118
if ( ! isRoot && ! shouldTrack ) {
119
+ // even if we don't track `this` component, we still want to end the root span eventually
120
+ maybeEndRootSpan ( this , timestampInSeconds ( ) , rootComponentSpanFinalTimeout ) ;
104
121
return ;
105
122
}
106
123
@@ -137,7 +154,7 @@ export const createTracingMixins = (options: Partial<TracingOptions> = {}): Mixi
137
154
if ( ! span ) return ;
138
155
span . end ( ) ;
139
156
140
- finishRootSpan ( this , timestampInSeconds ( ) , options . timeout || 2000 ) ;
157
+ maybeEndRootSpan ( this , timestampInSeconds ( ) , rootComponentSpanFinalTimeout ) ;
141
158
}
142
159
} ;
143
160
}
0 commit comments