import { schema , TypeOf } from '@kbn/config-schema' ; import { AppenderConfigType , Appenders } from './appenders/appenders' ; const toTuple = < A , B > ( a , b ) : [ A , B ] => [ a , b ] ; /**
 * Separator string that used within nested context name (eg. plugins.pid).
 */ const CONTEXT_SEPARATOR = '.' ; /**
 * Name of the `root` context that always exists and sits at the top of logger hierarchy.
 */ const ROOT_CONTEXT_NAME = 'root' ; /**
 * Name of the appender that is always presented and used by `root` logger by default.
 */ const DEFAULT_APPENDER_NAME = 'default' ; const levelSchema = schema . oneOf ( [ schema . literal ( 'all' ) , schema . literal ( 'fatal' ) , schema . literal ( 'error' ) , schema . literal ( 'warn' ) , schema . literal ( 'info' ) , schema . literal ( 'debug' ) , schema . literal ( 'trace' ) , schema . literal ( 'off' ) , ] , { defaultValue : 'info' , } ) ; /**
 * Config schema for validating the `loggers` key in  LoggerContextConfigType or  LoggingConfigType .
 *
 *  public export const loggerSchema = schema . object ( { appenders : schema . arrayOf ( schema . string ( ) , { defaultValue : [ ] } ) , name : schema . string ( ) , level : levelSchema , } ) ; public export type LoggerConfigType = TypeOf < typeof loggerSchema > ; export const config = { path : 'logging' , schema : schema . object ( { appenders : schema . mapOf ( schema . string ( ) , Appenders . configSchema , { defaultValue : new Map < string , AppenderConfigType > ( ) , } ) , loggers : schema . arrayOf ( loggerSchema , { defaultValue : [ ] , } ) , root : schema . object ( { appenders : schema . arrayOf ( schema . string ( ) , { defaultValue : [ DEFAULT_APPENDER_NAME ] , minSize : 1 , } ) , level : levelSchema , } ) , } ) , } ; export type LoggingConfigType = Pick < TypeOf < typeof config . schema > , 'loggers' | 'root' > & { appenders : Map < string , AppenderConfigType > ; } ; /**
 * Config schema for validating the inputs to the  LoggingServiceStart . configure API.
 * See  LoggerContextConfigType .
 *
 *  public export const loggerContextConfigSchema = schema . object ( { appenders : schema . mapOf ( schema . string ( ) , Appenders . configSchema , { defaultValue : new Map < string , AppenderConfigType > ( ) , } ) , loggers : schema . arrayOf ( loggerSchema , { defaultValue : [ ] } ) , } ) ; public export type LoggerContextConfigType = TypeOf < typeof loggerContextConfigSchema > ; public export interface LoggerContextConfigInput { appenders ? : Record < string , AppenderConfigType > | Map < string , AppenderConfigType > ; loggers ? : LoggerConfigType [ ] ; } internal export class LoggingConfig { param contextParts returns { string } public static getLoggerContext ( contextParts ) { return contextParts . join ( CONTEXT_SEPARATOR ) || ROOT_CONTEXT_NAME ; } param context returns public static getParentLoggerContext ( context ) { const lastIndexOfSeparator = context . lastIndexOf ( CONTEXT_SEPARATOR ) ; if ( lastIndexOfSeparator === - 1 ) { return ROOT_CONTEXT_NAME ; } return context . slice ( 0 , lastIndexOfSeparator ) ; } /**
     * Map of the appender unique arbitrary key and its corresponding config.
     */ public readonly appenders : Map < string , AppenderConfigType > = new Map ( [ [ 'default' , { type : 'console' , layout : { type : 'pattern' , highlight : true } , } as AppenderConfigType , ] , [ 'console' , { type : 'console' , layout : { type : 'pattern' , highlight : true } , } as AppenderConfigType , ] , ] ) ; /**
     * Map of the logger unique arbitrary key (context) and its corresponding config.
     */ public readonly loggers : Map < string , LoggerConfigType > = new Map ( ) ; constructor ( private readonly configType ) { this . fillAppendersConfig ( configType ) ; this . fillLoggersConfig ( configType ) ; } remarks param contextConfig public extend ( contextConfig ) { const mergedLoggers = new Map < string , LoggerConfigType > ( [ ... this . configType . loggers . map ( ( l ) => [ l . name , l ] as [ string , LoggerConfigType ] ) , ... contextConfig . loggers . map ( ( l ) => [ l . name , l ] as [ string , LoggerConfigType ] ) , ] ) ; const mergedConfig = { appenders : new Map ( [ ... this . configType . appenders , ... contextConfig . appenders ] ) , loggers : [ ... mergedLoggers . values ( ) ] , root : this . configType . root , } ; return new LoggingConfig ( mergedConfig ) ; } private fillAppendersConfig ( loggingConfig ) { for ( const [ appenderKey , appenderSchema ] of loggingConfig . appenders ) { this . appenders . set ( appenderKey , appenderSchema ) ; } } private fillLoggersConfig ( loggingConfig ) { const loggers = [ { name : ROOT_CONTEXT_NAME , ... loggingConfig . root } , ... loggingConfig . loggers ] ; const loggerConfigByContext = new Map ( loggers . map ( ( loggerConfig ) => toTuple ( loggerConfig . name , loggerConfig ) ) ) ; for ( const [ loggerContext , loggerConfig ] of loggerConfigByContext ) { const unsupportedAppenderKey = loggerConfig . appenders . find ( ( appenderKey ) => ! this . appenders . has ( appenderKey ) ) ; if ( unsupportedAppenderKey ) { throw new Error ( `Logger "${ loggerContext }" contains unsupported appender key "${ unsupportedAppenderKey }".` ) ; } const appenders = getAppenders ( loggerConfig , loggerConfigByContext ) ; this . loggers . set ( loggerContext , { ... loggerConfig , appenders , } ) ; } } } /**
 * Get appenders for logger config.
 *
 * If config for current context doesn't have any defined appenders inherit
 * appenders from the parent context config.
 */ function getAppenders ( loggerConfig , loggerConfigByContext ) { let currentContext = loggerConfig . name ; let appenders = loggerConfig . appenders ; while ( appenders . length === 0 ) { const parentContext = LoggingConfig . getParentLoggerContext ( currentContext ) ; const parentLogger = loggerConfigByContext . get ( parentContext ) ; if ( parentLogger ) { appenders = parentLogger . appenders ; } currentContext = parentContext ; } return appenders ; }