import { DerivativeMetric , Metric } from './baseMetric' ; import { IDAMetrics } from './protocol' ; const sizeLabels = [ 'B' , 'KB' , 'MB' , 'GB' , 'TB' ] ; const sizeInnerFormat = new Intl . NumberFormat ( undefined , { maximumSignificantDigits : 3 , } as Intl . NumberFormatOptions ) ; const wholeNumberFormat = new Intl . NumberFormat ( undefined , { notation : 'compact' , } as Intl . NumberFormatOptions ) ; const formatSize = ( bytes ) => { let size = 0 ; while ( bytes > 1000 && size < sizeLabels . length ) { bytes /= 1000 ; size ++ ; } return `${ sizeInnerFormat . format ( bytes ) } ${ sizeLabels [ size ] }` ; } ; const largePercentFormat = new Intl . NumberFormat ( undefined , { style : 'percent' , minimumSignificantDigits : 2 , maximumSignificantDigits : 2 , } ) ; const smallPercentFormat = new Intl . NumberFormat ( undefined , { style : 'percent' , maximumFractionDigits : 2 , } ) ; const durationRawFormat = new Intl . NumberFormat ( undefined , { maximumFractionDigits : 1 , } ) ; export const durationFormat = ( seconds ) => { if ( seconds < 120 ) { return `${ durationRawFormat . format ( seconds ) }s` ; } const minutes = seconds / 60 ; if ( minutes < 120 ) { return `${ durationRawFormat . format ( minutes ) }m` ; } const hours = minutes / 60 ; return `${ durationRawFormat . format ( hours ) }h` ; } ; export class CpuMetric extends DerivativeMetric { public update ( timestamp , metrics ) { if ( metrics . cpu ) { this . push ( timestamp , metrics . cpu . user / 1000 / 1000 ) ; } else if ( metrics . TaskDuration !== undefined ) { this . push ( timestamp , metrics . TaskDuration / 1000 ) ; } } public format ( metric ) { metric = Math . max ( 0 , Math . min ( 1 , metric ) ) ; return metric >= 0.01 ? largePercentFormat . format ( metric ) : smallPercentFormat . format ( metric ) ; } public name ( ) { return 'CPU Usage' ; } public short ( ) { return 'CPU' ; } protected recalcMax ( ) { return 1 ; } } export class HeapMetric extends Metric { public update ( timestamp , metrics ) { if ( metrics . memory ) { this . push ( timestamp , metrics . memory . rss ) ; } else if ( metrics . JSHeapUsedSize !== undefined ) { this . push ( timestamp , metrics . JSHeapUsedSize ) ; } } public format ( metric ) { return formatSize ( metric ) ; } public short ( ) { return 'Heap' ; } public name ( ) { return 'Heap Used' ; } } export class DOMNodes extends Metric { public update ( timestamp , metrics ) { if ( metrics . Nodes ) { this . push ( timestamp , metrics . Nodes ) ; } } public format ( metric ) { return wholeNumberFormat . format ( metric ) ; } public short ( ) { return 'DOM Nodes' ; } public name ( ) { return 'DOM Nodes' ; } } export class LayoutCount extends DerivativeMetric { public update ( timestamp , metrics ) { if ( metrics . LayoutCount !== undefined ) { this . push ( timestamp , metrics . LayoutCount / 1000 ) ; } } public format ( metric ) { return wholeNumberFormat . format ( metric ) ; } public short ( ) { return 'Relayouts' ; } public name ( ) { return 'DOM Relayouts / s' ; } } export class StyleRecalcs extends DerivativeMetric { public update ( timestamp , metrics ) { if ( metrics . RecalcStyleCount !== undefined ) { this . push ( timestamp , metrics . RecalcStyleCount / 1000 ) ; } } public format ( metric ) { return wholeNumberFormat . format ( metric ) ; } public short ( ) { return 'Restyles' ; } public name ( ) { return 'Style Recalcs / s' ; } } export const createMetrics = ( ) => [ new CpuMetric ( ) , new HeapMetric ( ) , new DOMNodes ( ) , new LayoutCount ( ) , new StyleRecalcs ( ) , ] ;