1- import { EventProcessor , Hub , Integration , IntegrationClass , Span } from '@sentry/types' ;
1+ import { EventProcessor , Hub , Integration , Scope , Span , Transaction } from '@sentry/types' ;
22import { basename , getGlobalObject , logger , timestampWithMs } from '@sentry/utils' ;
33
4- /**
5- * Used to extract Tracing integration from the current client,
6- * without the need to import `Tracing` itself from the @sentry/apm package.
7- */
8- const TRACING_GETTER = ( {
9- id : 'Tracing' ,
10- } as any ) as IntegrationClass < Integration > ;
11-
124/** Global Vue object limited to the methods/attributes we require */
135interface VueInstance {
146 config : {
@@ -71,7 +63,7 @@ interface TracingOptions {
7163 * Or to an array of specific component names (case-sensitive).
7264 */
7365 trackComponents : boolean | string [ ] ;
74- /** How long to wait until the tracked root activity is marked as finished and sent of to Sentry */
66+ /** How long to wait until the tracked root span is marked as finished and sent of to Sentry */
7567 timeout : number ;
7668 /**
7769 * List of hooks to keep track of during component lifecycle.
@@ -137,7 +129,6 @@ export class Vue implements Integration {
137129 private readonly _componentsCache : { [ key : string ] : string } = { } ;
138130 private _rootSpan ?: Span ;
139131 private _rootSpanTimer ?: ReturnType < typeof setTimeout > ;
140- private _tracingActivity ?: number ;
141132
142133 /**
143134 * @inheritDoc
@@ -221,27 +212,18 @@ export class Vue implements Integration {
221212 // On the first handler call (before), it'll be undefined, as `$once` will add it in the future.
222213 // However, on the second call (after), it'll be already in place.
223214 if ( this . _rootSpan ) {
224- this . _finishRootSpan ( now , getCurrentHub ) ;
215+ this . _finishRootSpan ( now ) ;
225216 } else {
226217 vm . $once ( `hook:${ hook } ` , ( ) => {
227- // Create an activity on the first event call. There'll be no second call, as rootSpan will be in place,
218+ // Create an span on the first event call. There'll be no second call, as rootSpan will be in place,
228219 // thus new event handler won't be attached.
229220
230- // We do this whole dance with `TRACING_GETTER` to prevent `@sentry/apm` from becoming a peerDependency.
231- // We also need to ask for the `.constructor`, as `pushActivity` and `popActivity` are static, not instance methods.
232- const tracingIntegration = getCurrentHub ( ) . getIntegration ( TRACING_GETTER ) ;
233- if ( tracingIntegration ) {
234- // tslint:disable-next-line:no-unsafe-any
235- this . _tracingActivity = ( tracingIntegration as any ) . constructor . pushActivity ( 'Vue Application Render' ) ;
236- // tslint:disable-next-line:no-unsafe-any
237- const transaction = ( tracingIntegration as any ) . constructor . getTransaction ( ) ;
238- if ( transaction ) {
239- // tslint:disable-next-line:no-unsafe-any
240- this . _rootSpan = transaction . startChild ( {
241- description : 'Application Render' ,
242- op : 'Vue' ,
243- } ) ;
244- }
221+ const activeTransaction = getActiveTransaction ( getCurrentHub ( ) ) ;
222+ if ( activeTransaction ) {
223+ this . _rootSpan = activeTransaction . startChild ( {
224+ description : 'Application Render' ,
225+ op : 'Vue' ,
226+ } ) ;
245227 }
246228 } ) ;
247229 }
@@ -264,7 +246,7 @@ export class Vue implements Integration {
264246 // However, on the second call (after), it'll be already in place.
265247 if ( span ) {
266248 span . finish ( ) ;
267- this . _finishRootSpan ( now , getCurrentHub ) ;
249+ this . _finishRootSpan ( now ) ;
268250 } else {
269251 vm . $once ( `hook:${ hook } ` , ( ) => {
270252 if ( this . _rootSpan ) {
@@ -305,24 +287,15 @@ export class Vue implements Integration {
305287 } ) ;
306288 } ;
307289
308- /** Finish top-level span and activity with a debounce configured using `timeout` option */
309- private _finishRootSpan ( timestamp : number , getCurrentHub : ( ) => Hub ) : void {
290+ /** Finish top-level span with a debounce configured using `timeout` option */
291+ private _finishRootSpan ( timestamp : number ) : void {
310292 if ( this . _rootSpanTimer ) {
311293 clearTimeout ( this . _rootSpanTimer ) ;
312294 }
313295
314296 this . _rootSpanTimer = setTimeout ( ( ) => {
315- if ( this . _tracingActivity ) {
316- // We do this whole dance with `TRACING_GETTER` to prevent `@sentry/apm` from becoming a peerDependency.
317- // We also need to ask for the `.constructor`, as `pushActivity` and `popActivity` are static, not instance methods.
318- const tracingIntegration = getCurrentHub ( ) . getIntegration ( TRACING_GETTER ) ;
319- if ( tracingIntegration ) {
320- // tslint:disable-next-line:no-unsafe-any
321- ( tracingIntegration as any ) . constructor . popActivity ( this . _tracingActivity ) ;
322- if ( this . _rootSpan ) {
323- this . _rootSpan . finish ( timestamp ) ;
324- }
325- }
297+ if ( this . _rootSpan ) {
298+ this . _rootSpan . finish ( timestamp ) ;
326299 }
327300 } , this . _options . tracingOptions . timeout ) ;
328301 }
@@ -333,7 +306,7 @@ export class Vue implements Integration {
333306
334307 this . _options . Vue . mixin ( {
335308 beforeCreate ( this : ViewModel ) : void {
336- if ( getCurrentHub ( ) . getIntegration ( TRACING_GETTER ) ) {
309+ if ( getActiveTransaction ( getCurrentHub ( ) ) ) {
337310 // `this` points to currently rendered component
338311 applyTracingHooks ( this , getCurrentHub ) ;
339312 } else {
@@ -405,3 +378,21 @@ export class Vue implements Integration {
405378 }
406379 }
407380}
381+
382+ // tslint:disable-next-line: completed-docs
383+ interface HubType extends Hub {
384+ // tslint:disable-next-line: completed-docs
385+ getScope ?( ) : Scope | undefined ;
386+ }
387+
388+ /** Grabs active transaction off scope */
389+ export function getActiveTransaction < T extends Transaction > ( hub : HubType ) : T | undefined {
390+ if ( hub && hub . getScope ) {
391+ const scope = hub . getScope ( ) as Scope ;
392+ if ( scope ) {
393+ return scope . getTransaction ( ) as T | undefined ;
394+ }
395+ }
396+
397+ return undefined ;
398+ }
0 commit comments