import { i18n } from '@kbn/i18n' ; import moment from 'moment' ; import { memoize } from 'lodash' ; import { NOT_AVAILABLE_LABEL } from '../../../common/i18n' ; import { asDecimalOrInteger , asInteger , asDecimal } from './formatters' ; import { TimeUnit } from './datetime' ; import { Maybe } from '../../../typings/common' ; import { isFiniteNumber } from '../is_finite_number' ; interface FormatterOptions { defaultValue ? : string ; } type DurationTimeUnit = TimeUnit | 'microseconds' ; interface ConvertedDuration { value : string ; unit ? : string ; formatted : string ; } export type TimeFormatter = ( value : Maybe < number > , options ? : FormatterOptions ) => ConvertedDuration ; type TimeFormatterBuilder = ( max : number , threshold ? : number ) => TimeFormatter ; function getUnitLabelAndConvertedValue ( unitKey , value , threshold = 10 ) { const ms = value / 1000 ; switch ( unitKey ) { case 'hours' : { return { unitLabel : i18n . translate ( 'xpack.apm.formatters.hoursTimeUnitLabel' , { defaultMessage : 'h' , } ) , convertedValue : asDecimalOrInteger ( moment . duration ( ms ) . asHours ( ) , threshold ) , } ; } case 'minutes' : { return { unitLabel : i18n . translate ( 'xpack.apm.formatters.minutesTimeUnitLabel' , { defaultMessage : 'min' , } ) , convertedValue : asDecimalOrInteger ( moment . duration ( ms ) . asMinutes ( ) , threshold ) , } ; } case 'seconds' : { return { unitLabel : i18n . translate ( 'xpack.apm.formatters.secondsTimeUnitLabel' , { defaultMessage : 's' , } ) , convertedValue : asDecimalOrInteger ( moment . duration ( ms ) . asSeconds ( ) , threshold ) , } ; } case 'milliseconds' : { return { unitLabel : i18n . translate ( 'xpack.apm.formatters.millisTimeUnitLabel' , { defaultMessage : 'ms' , } ) , convertedValue : asDecimalOrInteger ( moment . duration ( ms ) . asMilliseconds ( ) , threshold ) , } ; } case 'microseconds' : { return { unitLabel : i18n . translate ( 'xpack.apm.formatters.microsTimeUnitLabel' , { defaultMessage : 'μs' , } ) , convertedValue : asInteger ( value ) , } ; } } } /**
 * Converts a microseconds value into the unit defined.
 */ function convertTo ( { unit , microseconds , defaultValue = NOT_AVAILABLE_LABEL , threshold = 10 , } ) { if ( ! isFiniteNumber ( microseconds ) ) { return { value : defaultValue , formatted : defaultValue } ; } const { convertedValue , unitLabel } = getUnitLabelAndConvertedValue ( unit , microseconds , threshold ) ; return { value : convertedValue , unit : unitLabel , formatted : `${ convertedValue } ${ unitLabel }` , } ; } export const toMicroseconds = ( value , timeUnit ) => moment . duration ( value , timeUnit ) . asMilliseconds ( ) * 1000 ; function getDurationUnitKey ( max , threshold = 10 ) { if ( max > toMicroseconds ( threshold , 'hours' ) ) { return 'hours' ; } if ( max > toMicroseconds ( threshold , 'minutes' ) ) { return 'minutes' ; } if ( max > toMicroseconds ( threshold , 'seconds' ) ) { return 'seconds' ; } if ( max > toMicroseconds ( 1 , 'milliseconds' ) ) { return 'milliseconds' ; } return 'microseconds' ; } export const getDurationFormatter = memoize ( ( max , threshold = 10 ) => { const unit = getDurationUnitKey ( max , threshold ) ; return ( value , { defaultValue } = { } ) => { return convertTo ( { unit , microseconds : value , defaultValue , threshold } ) ; } ; } , ( max , threshold ) => `${ max }_${ threshold }` ) ; export function asTransactionRate ( value ) { if ( ! isFiniteNumber ( value ) ) { return NOT_AVAILABLE_LABEL ; } let displayedValue ; if ( value === 0 ) { displayedValue = '0' ; } else if ( value <= 0.1 ) { displayedValue = '< 0.1' ; } else { displayedValue = asDecimal ( value ) ; } return i18n . translate ( 'xpack.apm.transactionRateLabel' , { defaultMessage : `{displayedValue} tpm` , values : { displayedValue } , } ) ; } export function asExactTransactionRate ( value ) { return i18n . translate ( 'xpack.apm.exactTransactionRateLabel' , { defaultMessage : `{value} tpm` , values : { value : asDecimalOrInteger ( value ) } , } ) ; } /**
 * Converts value and returns it formatted - 00 unit
 */ export function asDuration ( value , { defaultValue = NOT_AVAILABLE_LABEL } = { } ) { if ( ! isFiniteNumber ( value ) ) { return defaultValue ; } const formatter = getDurationFormatter ( value ) ; return formatter ( value , { defaultValue } ) . formatted ; } /**
 * Convert a microsecond value to decimal milliseconds. Normally we use
 * `asDuration`, but this is used in places like tables where we always want
 * the same units.
 */ export function asMillisecondDuration ( value ) { return convertTo ( { unit : 'milliseconds' , microseconds : value , } ) . formatted ; }