@@ -31,8 +31,10 @@ const HOOKS: { [key in Operation]: Hook[] } = {
3131 update : [ 'beforeUpdate' , 'updated' ] ,
3232} ;
3333
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 {
3638 if ( vm . $_sentryRootSpanTimer ) {
3739 clearTimeout ( vm . $_sentryRootSpanTimer ) ;
3840 }
@@ -66,6 +68,8 @@ export const createTracingMixins = (options: Partial<TracingOptions> = {}): Mixi
6668
6769 const mixins : Mixins = { } ;
6870
71+ const rootComponentSpanFinalTimeout = options . timeout || 2000 ;
72+
6973 for ( const operation of hooks ) {
7074 // Retrieve corresponding hooks from Vue lifecycle.
7175 // eg. mount => ['beforeMount', 'mounted']
@@ -80,6 +84,14 @@ export const createTracingMixins = (options: Partial<TracingOptions> = {}): Mixi
8084 const isRoot = this . $root === this ;
8185
8286 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+ */
8395 this . $_sentryRootSpan =
8496 this . $_sentryRootSpan ||
8597 startInactiveSpan ( {
@@ -90,6 +102,9 @@ export const createTracingMixins = (options: Partial<TracingOptions> = {}): Mixi
90102 } ,
91103 onlyIfParent : true ,
92104 } ) ;
105+
106+ // call debounced end function once directly, just in case no child components call it
107+ maybeEndRootSpan ( this , timestampInSeconds ( ) , rootComponentSpanFinalTimeout ) ;
93108 }
94109
95110 // 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
101116
102117 // We always want to track root component
103118 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 ) ;
104121 return ;
105122 }
106123
@@ -137,7 +154,7 @@ export const createTracingMixins = (options: Partial<TracingOptions> = {}): Mixi
137154 if ( ! span ) return ;
138155 span . end ( ) ;
139156
140- finishRootSpan ( this , timestampInSeconds ( ) , options . timeout || 2000 ) ;
157+ maybeEndRootSpan ( this , timestampInSeconds ( ) , rootComponentSpanFinalTimeout ) ;
141158 }
142159 } ;
143160 }
0 commit comments