/********************************************************************************
 * Copyright (C) 2017 Ericsson and others.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the Eclipse
 * Public License v. 2.0 are satisfied: GNU General Public License, version 2
 * with the GNU Classpath Exception which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 ********************************************************************************/ import { inject , injectable } from 'inversify' ; import { LoggerWatcher } from './logger-watcher' ; import { ILoggerServer , LogLevel , ConsoleLogger , rootLoggerName } from './logger-protocol' ; export { LogLevel , rootLoggerName } ; export let logger ; /**
 * Counterpart of the `#setRootLogger(ILogger)`. Restores the `console.xxx` bindings to the original one.
 * Invoking has no side-effect if `setRootLogger` was not called before. Multiple function invocation has
 * no side-effect either.
 */ export function unsetRootLogger ( ) { if ( logger !== undefined ) { ConsoleLogger . reset ( ) ; ( < any > logger ) = undefined ; } } export function setRootLogger ( aLogger ) { logger = aLogger ; const log = ( logLevel , message ? , ... optionalParams ) => logger . log ( logLevel , message , ... optionalParams ) ; console . error = log . bind ( undefined , LogLevel . ERROR ) ; console . warn = log . bind ( undefined , LogLevel . WARN ) ; console . info = log . bind ( undefined , LogLevel . INFO ) ; console . debug = log . bind ( undefined , LogLevel . DEBUG ) ; console . trace = log . bind ( undefined , LogLevel . TRACE ) ; console . log = log . bind ( undefined , LogLevel . INFO ) ; } export type Log = ( message : any , ... params : any [ ] ) => void ; export type Loggable = ( log : Log ) => void ; export const LoggerFactory = Symbol ( 'LoggerFactory' ) ; export type LoggerFactory = ( name : string ) => ILogger ; export const LoggerName = Symbol ( 'LoggerName' ) ; export const ILogger = Symbol ( 'ILogger' ) ; export interface ILogger { param loglevel setLogLevel ( logLevel ) : Promise < void > ; returns getLogLevel ( ) : Promise < number > ; /**
     * Test whether the given log level is enabled.
     */ isEnabled ( logLevel ) : Promise < boolean > ; /**
     * Resolve if the given log is enabled.
     */ ifEnabled ( logLevel ) : Promise < void > ; /**
     * Log a loggable with the given level if it is enabled.
     */ log ( logLevel , loggable ) : Promise < void > ; param logLevel param message param params log ( logLevel , message , ... params ) : void ; /**
     * Test whether the trace level is enabled.
     */ isTrace ( ) : Promise < boolean > ; /**
     * Resolve if the trace level is enabled.
     */ ifTrace ( ) : Promise < void > ; /**
     * Log a loggable with the trace level if it is enabled.
     */ trace ( loggable ) : Promise < void > ; param message param params trace ( message , ... params ) : Promise < void > ; /**
     * Test whether the debug level is enabled.
     */ isDebug ( ) : Promise < boolean > ; /**
     * Resolve if the debug level is enabled.
     */ ifDebug ( ) : Promise < void > ; /**
     * Log a loggable with the debug level if it is enabled.
     */ debug ( loggable ) : Promise < void > ; param message param params debug ( message , ... params ) : Promise < void > ; /**
     * Test whether the info level is enabled.
     */ isInfo ( ) : Promise < boolean > ; /**
     * Resolve if the info level is enabled.
     */ ifInfo ( ) : Promise < void > ; /**
     * Log a loggable with the info level if it is enabled.
     */ info ( loggable ) : Promise < void > ; param message param params info ( message , ... params ) : Promise < void > ; /**
     * Test whether the warn level is enabled.
     */ isWarn ( ) : Promise < boolean > ; /**
     * Resolve if the warn level is enabled.
     */ ifWarn ( ) : Promise < void > ; /**
     * Log a loggable with the warn level if it is enabled.
     */ warn ( loggable ) : Promise < void > ; param message param params warn ( message , ... params ) : Promise < void > ; /**
     * Test whether the error level is enabled.
     */ isError ( ) : Promise < boolean > ; /**
     * Resolve if the error level is enabled.
     */ ifError ( ) : Promise < void > ; /**
     * Log a loggable with the error level if it is enabled.
     */ error ( loggable ) : Promise < void > ; param message param params error ( message , ... params ) : Promise < void > ; /**
     * Test whether the fatal level is enabled.
     */ isFatal ( ) : Promise < boolean > ; /**
     * Resolve if the fatal level is enabled.
     */ ifFatal ( ) : Promise < void > ; /**
     * Log a loggable with the fatal level if it is enabled.
     */ fatal ( loggable ) : Promise < void > ; param message param params fatal ( message , ... params ) : Promise < void > ; param name child ( name ) : ILogger ; } @ injectable ( ) export class Logger implements ILogger { protected _logLevel : Promise < number > ; protected created : Promise < void > ; /**
     * Build a new Logger.
     */ constructor ( @ inject ( ILoggerServer ) protected readonly server , @ inject ( LoggerWatcher ) protected readonly loggerWatcher , @ inject ( LoggerFactory ) protected readonly factory , @ inject ( LoggerName ) protected name ) { if ( name !== rootLoggerName ) { this . created = server . child ( name ) ; } else { this . created = Promise . resolve ( ) ; } this . _logLevel = this . created . then ( _ => this . server . getLogLevel ( name ) ) ; loggerWatcher . onLogLevelChanged ( event => { this . created . then ( ( ) => { if ( event . loggerName === name ) { this . _logLevel = Promise . resolve ( event . newLogLevel ) ; } } ) ; } ) ; } setLogLevel ( logLevel ) { return new Promise < void > ( resolve => { this . created . then ( ( ) => { this . _logLevel . then ( oldLevel => { this . server . setLogLevel ( this . name , logLevel ) . then ( ( ) => { this . _logLevel = Promise . resolve ( logLevel ) ; resolve ( ) ; } ) ; } ) ; } ) ; } ) ; } getLogLevel ( ) { return this . _logLevel ; } isEnabled ( logLevel ) { return this . _logLevel . then ( level => logLevel >= level ) ; } ifEnabled ( logLevel ) { return new Promise < void > ( resolve => this . isEnabled ( logLevel ) . then ( enabled => { if ( enabled ) { resolve ( ) ; } } ) ) ; } log ( logLevel , arg2 , ... params ) { return this . getLog ( logLevel ) . then ( log => { if ( typeof arg2 === 'function' ) { const loggable = arg2 ; loggable ( log ) ; } else if ( arg2 ) { log ( arg2 , ... params ) ; } } ) ; } protected getLog ( logLevel ) { return this . ifEnabled ( logLevel ) . then ( ( ) => this . created . then ( ( ) => ( message , ... params ) => this . server . log ( this . name , logLevel , this . format ( message ) , params . map ( p => this . format ( p ) ) ) ) ) ; } protected format ( value ) { if ( value instanceof Error ) { return value . stack || value . toString ( ) ; } return value ; } isTrace ( ) { return this . isEnabled ( LogLevel . TRACE ) ; } ifTrace ( ) { return this . ifEnabled ( LogLevel . TRACE ) ; } trace ( arg , ... params ) { return this . log ( LogLevel . TRACE , arg , ... params ) ; } isDebug ( ) { return this . isEnabled ( LogLevel . DEBUG ) ; } ifDebug ( ) { return this . ifEnabled ( LogLevel . DEBUG ) ; } debug ( arg , ... params ) { return this . log ( LogLevel . DEBUG , arg , ... params ) ; } isInfo ( ) { return this . isEnabled ( LogLevel . INFO ) ; } ifInfo ( ) { return this . ifEnabled ( LogLevel . INFO ) ; } info ( arg , ... params ) { return this . log ( LogLevel . INFO , arg , ... params ) ; } isWarn ( ) { return this . isEnabled ( LogLevel . WARN ) ; } ifWarn ( ) { return this . ifEnabled ( LogLevel . WARN ) ; } warn ( arg , ... params ) { return this . log ( LogLevel . WARN , arg , ... params ) ; } isError ( ) { return this . isEnabled ( LogLevel . ERROR ) ; } ifError ( ) { return this . ifEnabled ( LogLevel . ERROR ) ; } error ( arg , ... params ) { return this . log ( LogLevel . ERROR , arg , ... params ) ; } isFatal ( ) { return this . isEnabled ( LogLevel . FATAL ) ; } ifFatal ( ) { return this . ifEnabled ( LogLevel . FATAL ) ; } fatal ( arg , ... params ) { return this . log ( LogLevel . FATAL , arg , ... params ) ; } child ( name ) { return this . factory ( name ) ; } }