import { appendFileSync , writeFileSync } from 'fs' ; import { format } from 'util' ; import { EOL } from 'os' ; export interface Logger { log ( message , ... args ) : void ; } export class ConsoleLogger implements Logger { log ( message , ... args ) { console . log ( '**' , message , ... args ) ; } } export class FileLogger implements Logger { constructor ( private path ) { writeFileSync ( path , '' ) ; } log ( message , ... args ) { const date = new Date ( ) . toISOString ( ) ; appendFileSync ( this . path , `[${ date }] ${ format ( message , ... args ) }${ EOL }` ) ; } } export class MultiLogger implements Logger { constructor ( private loggers ) { } log ( message , ... args ) { for ( const logger of this . loggers ) { logger . log ( message , ... args ) ; } } } export async function measureAndLog < T > ( promise , name , logger ) { const now = Date . now ( ) ; logger . log ( `Starting operation '${ name }...` ) ; let res = undefined ; let e ; try { res = await promise ; } catch ( error ) { e = error ; } if ( e ) { logger . log ( `Finished operation '${ name }' with error ${ e } after ${ Date . now ( ) - now }ms` ) ; throw e ; } logger . log ( `Finished operation '${ name }' successfully after ${ Date . now ( ) - now }ms` ) ; return res as unknown as T ; }