export enum LogLevel { DEBUG , INFO , WARN , ERROR } export interface LogContext { getLogContext ( ) : Loggable ; } /**
 * Loggable may be used to give a log message additional context.
 */ export type Loggable = LogContext | Record < string , string > ; /**
 * Structured logger.
 */ export interface Logger { /**
     * Creates a new logger with additional context used by all subsequent log calls.
     */ withContext ( ... args ) : Logger ; log ( logLevel , message , ... args ) : void ; debug ( message , ... args ) : void ; info ( message , ... args ) : void ; warn ( message , ... args ) : void ; error ( message , ... args ) : void ; dispose ( ) : void ; } export abstract class AbstractLogger implements Logger { public abstract withContext ( ... args ) ; public abstract log ( logLevel , message , ... args ) ; public debug ( message , ... args ) { this . log ( LogLevel . DEBUG , message , ... args ) ; } public info ( message , ... args ) { this . log ( LogLevel . INFO , message , ... args ) ; } public warn ( message , ... args ) { this . log ( LogLevel . WARN , message , ... args ) ; } public error ( message , ... args ) { this . log ( LogLevel . ERROR , message , ... args ) ; } public dispose ( ) { } /**
     * Recursively unwraps loggables into objects.
     */ protected getContext ( args ) { let obj = { } ; for ( const arg of args ) { if ( "getLogContext" in arg ) { const loggable = ( arg as LogContext ) . getLogContext ( ) ; const context = this . getContext ( [ loggable ] ) ; obj = { ... obj , ... context } ; } else { obj = { ... obj , ... arg } ; } } return obj ; } }