import MP , { APP_LIFE_CYCLE , PAGE_LIFE_CYCLE } from '../mp' ; import { BeiDouTimeLine } from '../types/tracing' ; import { addAppContexts } from './context' ; import { addNavigationSpans } from './metrics' ; import { Transaction } from './transaction' ; let vitals = null ; export interface Record { layoutTime : number ; extra : { name : string ; scene : string ; } ; } declare var App ; declare var Page ; declare var Component ; export class MPVitals { private __TIMELINE__ : BeiDouTimeLine ; private _appLanch : Record ; private _fpDown : boolean ; constructor ( ) { this . __TIMELINE__ = { in : Date . now ( ) || new Date ( ) . getTime ( ) } ; this . _appLanch = { } ; this . _fpDown = false ; this . interceptApp ( ) ; this . interceptPage ( ) ; } private interceptApp = ( ) : void => { let self = this ; let mpInstance = MP . instance ( ) ; const primaryApp = App ; App = ( obj ) => { APP_LIFE_CYCLE . forEach ( name => { const primaryHookFn = obj [ name ] ; obj [ name ] = function ( info ) { if ( ! mpInstance . indexPage ) { mpInstance . indexPage = info . path ; mpInstance . networkInfo ; mpInstance . userInfo ; } let date = Date . now ( ) || new Date ( ) . getTime ( ) ; console . log ( `App：${ name }_${ date }` ) ; self . __TIMELINE__ [ `App_${ name }` ] = date ; if ( name === 'onLaunch' ) { self . _appLanch = { layoutTime : date , extra : { name : '初始化耗时' , scene : info . scene } } ; mpInstance . sceneInfo = info ; } if ( name === 'onShow' ) { self . __TIMELINE__ [ 'Page_init' ] = date ; } return primaryHookFn && primaryHookFn . call ( this , info ) ; } ; } ) ; primaryApp && primaryApp . call ( this , obj ) ; } ; } ; private interceptPage = ( ) : void => { let self = this ; let isTaro = ( typeof ( process ) !== 'undefined' && typeof ( process . env ) !== 'undefined' && typeof ( process . env . TARO_ENV ) !== 'undefined' ) ? true : false ; const primaryPage = Page ; if ( isTaro ) { let primaryComponent = Component ; Component = ( obj ) => { PAGE_LIFE_CYCLE . forEach ( name => { if ( typeof obj . methods [ name ] === 'function' ) { const primaryHookFn = obj . methods [ name ] ; obj . methods [ name ] = function ( info ) { return self . rewritePageLifeCycle ( name , this , primaryHookFn , info ) ; } ; } } ) ; primaryComponent && primaryComponent . call ( this , obj ) ; } ; } Page = ( obj ) => { PAGE_LIFE_CYCLE . forEach ( name => { const primaryHookFn = obj [ name ] ; obj [ name ] = function ( info ) { return self . rewritePageLifeCycle ( name , this , primaryHookFn , info ) ; } ; } ) ; primaryPage && primaryPage . call ( this , obj ) ; } ; } ; private rewritePageLifeCycle ( name , self , primaryHookFn , info ) { let date = Date . now ( ) || new Date ( ) . getTime ( ) ; const mpInstance = MP . instance ( ) ; console . log ( `Page：${ name }_${ date }` ) ; this . __TIMELINE__ [ `Page_${ name }` ] = date ; if ( name === 'onHide' ) { this . __TIMELINE__ [ 'Page_init' ] = date ; } if ( name === 'onLoad' ) { mpInstance . pageParams = { url : mpInstance . currentPage , query : info } ; } if ( name === 'onReady' ) { const transaction = Transaction . instance ( ) ; if ( ! this . _fpDown ) { this . __TIMELINE__ [ 'ready' ] = date ; this . _fpDown = true ; } addNavigationSpans ( transaction , this . __TIMELINE__ ) ; addAppContexts ( transaction , { ... this . __TIMELINE__ , AppLaunch : this . _appLanch } ) ; transaction . finish ( ) ; } return primaryHookFn && primaryHookFn . call ( self , info ) ; } static instance ( ) { if ( vitals ) return vitals ; vitals = new MPVitals ( ) ; return vitals ; } }