From: Jérôme Benoit Date: Sun, 16 Jul 2023 22:02:19 +0000 (+0200) Subject: fix: fix configuration section caching X-Git-Tag: v1.2.18~18 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=5d0498291974ec3a130ba4b1c4663d13d16992c5;p=e-mobility-charging-stations-simulator.git fix: fix configuration section caching Signed-off-by: Jérôme Benoit --- diff --git a/src/charging-station/Bootstrap.ts b/src/charging-station/Bootstrap.ts index 15eb4fce..2c5d6a7d 100644 --- a/src/charging-station/Bootstrap.ts +++ b/src/charging-station/Bootstrap.ts @@ -20,9 +20,13 @@ import { type ChargingStationWorkerMessage, type ChargingStationWorkerMessageData, ChargingStationWorkerMessageEvents, + ConfigurationSection, ProcedureName, type StationTemplateUrl, type Statistics, + type StorageConfiguration, + type UIServerConfiguration, + type WorkerConfiguration, } from '../types'; import { Configuration, @@ -78,12 +82,21 @@ export class Bootstrap extends EventEmitter { dirname(fileURLToPath(import.meta.url)), `ChargingStationWorker${extname(fileURLToPath(import.meta.url))}`, ); - Configuration.getUIServer().enabled === true && - (this.uiServer = UIServerFactory.getUIServerImplementation(Configuration.getUIServer())); - Configuration.getPerformanceStorage().enabled === true && + Configuration.getConfigurationSection(ConfigurationSection.uiServer) + .enabled === true && + (this.uiServer = UIServerFactory.getUIServerImplementation( + Configuration.getConfigurationSection(ConfigurationSection.uiServer), + )); + Configuration.getConfigurationSection( + ConfigurationSection.performanceStorage, + ).enabled === true && (this.storage = StorageFactory.getStorage( - Configuration.getPerformanceStorage().type!, - Configuration.getPerformanceStorage().uri!, + Configuration.getConfigurationSection( + ConfigurationSection.performanceStorage, + ).type!, + Configuration.getConfigurationSection( + ConfigurationSection.performanceStorage, + ).uri!, this.logPrefix(), )); Configuration.setConfigurationChangeCallback(async () => Bootstrap.getInstance().restart()); @@ -130,13 +143,21 @@ export class Bootstrap extends EventEmitter { this.version } started with ${this.numberOfChargingStations.toString()} charging station(s) from ${this.numberOfChargingStationTemplates.toString()} configured charging station template(s) and ${ Configuration.workerDynamicPoolInUse() - ? `${Configuration.getWorker().poolMinSize?.toString()}/` + ? `${Configuration.getConfigurationSection( + ConfigurationSection.worker, + ).poolMinSize?.toString()}/` : '' }${this.workerImplementation?.size}${ Configuration.workerPoolInUse() - ? `/${Configuration.getWorker().poolMaxSize?.toString()}` + ? `/${Configuration.getConfigurationSection( + ConfigurationSection.worker, + ).poolMaxSize?.toString()}` : '' - } worker(s) concurrently running in '${Configuration.getWorker().processType}' mode${ + } worker(s) concurrently running in '${ + Configuration.getConfigurationSection( + ConfigurationSection.worker, + ).processType + }' mode${ !isNullOrUndefined(this.workerImplementation?.maxElementsPerWorker) ? ` (${this.workerImplementation?.maxElementsPerWorker} charging station(s) per worker)` : '' @@ -213,7 +234,10 @@ export class Bootstrap extends EventEmitter { private initializeWorkerImplementation(): void { let elementsPerWorker: number | undefined; - if (Configuration.getWorker()?.elementsPerWorker === 'auto') { + if ( + Configuration.getConfigurationSection(ConfigurationSection.worker) + ?.elementsPerWorker === 'auto' + ) { elementsPerWorker = this.numberOfChargingStations > availableParallelism() ? Math.round(this.numberOfChargingStations / availableParallelism()) @@ -222,14 +246,25 @@ export class Bootstrap extends EventEmitter { this.workerImplementation === null && (this.workerImplementation = WorkerFactory.getWorkerImplementation( this.workerScript, - Configuration.getWorker().processType!, + Configuration.getConfigurationSection(ConfigurationSection.worker) + .processType!, { - workerStartDelay: Configuration.getWorker().startDelay, - elementStartDelay: Configuration.getWorker().elementStartDelay, - poolMaxSize: Configuration.getWorker().poolMaxSize!, - poolMinSize: Configuration.getWorker().poolMinSize!, + workerStartDelay: Configuration.getConfigurationSection( + ConfigurationSection.worker, + ).startDelay, + elementStartDelay: Configuration.getConfigurationSection( + ConfigurationSection.worker, + ).elementStartDelay, + poolMaxSize: Configuration.getConfigurationSection( + ConfigurationSection.worker, + ).poolMaxSize!, + poolMinSize: Configuration.getConfigurationSection( + ConfigurationSection.worker, + ).poolMinSize!, elementsPerWorker: - elementsPerWorker ?? (Configuration.getWorker().elementsPerWorker as number), + elementsPerWorker ?? + (Configuration.getConfigurationSection(ConfigurationSection.worker) + .elementsPerWorker as number), poolOptions: { messageHandler: this.messageHandler.bind(this) as (message: unknown) => void, }, diff --git a/src/charging-station/ui-server/UIServerFactory.ts b/src/charging-station/ui-server/UIServerFactory.ts index e0f4a78e..2a6b521e 100644 --- a/src/charging-station/ui-server/UIServerFactory.ts +++ b/src/charging-station/ui-server/UIServerFactory.ts @@ -4,7 +4,7 @@ import type { AbstractUIServer } from './AbstractUIServer'; import { UIHttpServer } from './UIHttpServer'; import { UIServerUtils } from './UIServerUtils'; import { UIWebSocketServer } from './UIWebSocketServer'; -import { ApplicationProtocol, type UIServerConfiguration } from '../../types'; +import { ApplicationProtocol, ConfigurationSection, type UIServerConfiguration } from '../../types'; import { Configuration } from '../../utils'; export class UIServerFactory { @@ -22,11 +22,25 @@ export class UIServerFactory { ), ); } - switch (uiServerConfiguration?.type ?? Configuration.getUIServer().type) { + switch ( + uiServerConfiguration?.type ?? + Configuration.getConfigurationSection(ConfigurationSection.uiServer) + .type + ) { case ApplicationProtocol.WS: - return new UIWebSocketServer(uiServerConfiguration ?? Configuration.getUIServer()); + return new UIWebSocketServer( + uiServerConfiguration ?? + Configuration.getConfigurationSection( + ConfigurationSection.uiServer, + ), + ); case ApplicationProtocol.HTTP: - return new UIHttpServer(uiServerConfiguration ?? Configuration.getUIServer()); + return new UIHttpServer( + uiServerConfiguration ?? + Configuration.getConfigurationSection( + ConfigurationSection.uiServer, + ), + ); default: return null; } diff --git a/src/performance/PerformanceStatistics.ts b/src/performance/PerformanceStatistics.ts index 4b19e1d7..6471265e 100644 --- a/src/performance/PerformanceStatistics.ts +++ b/src/performance/PerformanceStatistics.ts @@ -5,10 +5,13 @@ import type { URL } from 'node:url'; import { parentPort } from 'node:worker_threads'; import { + ConfigurationSection, type IncomingRequestCommand, + type LogConfiguration, MessageType, type RequestCommand, type Statistics, + type StorageConfiguration, type TimestampedData, } from '../types'; import { @@ -128,11 +131,21 @@ export class PerformanceStatistics { public start(): void { this.startLogStatisticsInterval(); - if (Configuration.getPerformanceStorage().enabled) { + if ( + Configuration.getConfigurationSection( + ConfigurationSection.performanceStorage, + ).enabled + ) { logger.info( `${this.logPrefix()} storage enabled: type ${ - Configuration.getPerformanceStorage().type - }, uri: ${Configuration.getPerformanceStorage().uri}`, + Configuration.getConfigurationSection( + ConfigurationSection.performanceStorage, + ).type + }, uri: ${ + Configuration.getConfigurationSection( + ConfigurationSection.performanceStorage, + ).uri + }`, ); } } @@ -169,8 +182,11 @@ export class PerformanceStatistics { } private startLogStatisticsInterval(): void { - const logStatisticsInterval = Configuration.getLog().enabled - ? Configuration.getLog().statisticsInterval! + const logStatisticsInterval = Configuration.getConfigurationSection( + ConfigurationSection.log, + ).enabled + ? Configuration.getConfigurationSection(ConfigurationSection.log) + .statisticsInterval! : 0; if (logStatisticsInterval > 0 && !this.displayInterval) { this.displayInterval = setInterval(() => { @@ -183,7 +199,9 @@ export class PerformanceStatistics { logger.info( `${this.logPrefix()} already logged every ${formatDurationSeconds(logStatisticsInterval)}`, ); - } else if (Configuration.getLog().enabled) { + } else if ( + Configuration.getConfigurationSection(ConfigurationSection.log).enabled + ) { logger.info( `${this.logPrefix()} log interval is set to ${logStatisticsInterval?.toString()}. Not logging statistics`, ); @@ -247,7 +265,11 @@ export class PerformanceStatistics { this.statistics.statisticsData.get(entryName)!.measurementTimeSeries as TimestampedData[], ), ); - if (Configuration.getPerformanceStorage().enabled) { + if ( + Configuration.getConfigurationSection( + ConfigurationSection.performanceStorage, + ).enabled + ) { parentPort?.postMessage(buildPerformanceStatisticsMessage(this.statistics)); } } diff --git a/src/types/ConfigurationData.ts b/src/types/ConfigurationData.ts index 41d45e4a..ebec3a0d 100644 --- a/src/types/ConfigurationData.ts +++ b/src/types/ConfigurationData.ts @@ -8,6 +8,13 @@ import type { WorkerProcessType } from '../worker'; type ServerOptions = ListenOptions; +export enum ConfigurationSection { + log = 'log', + performanceStorage = 'performanceStorage', + worker = 'worker', + uiServer = 'uiServer', +} + export enum SupervisionUrlDistribution { ROUND_ROBIN = 'round-robin', RANDOM = 'random', diff --git a/src/types/index.ts b/src/types/index.ts index 05828944..436941aa 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -167,6 +167,7 @@ export { } from './ChargingStationTemplate'; export { type ConfigurationData, + ConfigurationSection, type LogConfiguration, type StationTemplateUrl, type StorageConfiguration, diff --git a/src/utils/Configuration.ts b/src/utils/Configuration.ts index 544f4a10..d9c297e9 100644 --- a/src/utils/Configuration.ts +++ b/src/utils/Configuration.ts @@ -10,6 +10,7 @@ import { hasOwnProp, isCFEnvironment, isNotEmptyString, isUndefined } from './Ut import { ApplicationProtocol, type ConfigurationData, + ConfigurationSection, FileType, type LogConfiguration, type StationTemplateUrl, @@ -21,13 +22,6 @@ import { } from '../types'; import { WorkerConstants, WorkerProcessType } from '../worker'; -enum ConfigurationSection { - log = 'log', - performanceStorage = 'performanceStorage', - worker = 'worker', - uiServer = 'uiServer', -} - export class Configuration { private static configurationFile = join( dirname(fileURLToPath(import.meta.url)), @@ -40,7 +34,12 @@ export class Configuration { private static configurationSectionCache = new Map< ConfigurationSection, LogConfiguration | StorageConfiguration | WorkerConfiguration | UIServerConfiguration - >(); + >([ + [ConfigurationSection.log, Configuration.buildLogSection()], + [ConfigurationSection.performanceStorage, Configuration.buildPerformanceStorageSection()], + [ConfigurationSection.worker, Configuration.buildWorkerSection()], + [ConfigurationSection.uiServer, Configuration.buildUIServerSection()], + ]); private static configurationChangeCallback: () => Promise; @@ -52,7 +51,102 @@ export class Configuration { Configuration.configurationChangeCallback = cb; } - public static getUIServer(): UIServerConfiguration { + public static getConfigurationSection(sectionName: ConfigurationSection): T { + return Configuration.configurationSectionCache.get(sectionName) as T; + } + + public static getAutoReconnectMaxRetries(): number | undefined { + Configuration.warnDeprecatedConfigurationKey( + 'autoReconnectTimeout', + undefined, + "Use 'ConnectionTimeOut' OCPP parameter in charging station template instead", + ); + Configuration.warnDeprecatedConfigurationKey( + 'connectionTimeout', + undefined, + "Use 'ConnectionTimeOut' OCPP parameter in charging station template instead", + ); + Configuration.warnDeprecatedConfigurationKey( + 'autoReconnectMaxRetries', + undefined, + 'Use it in charging station template instead', + ); + if (hasOwnProp(Configuration.getConfigurationData(), 'autoReconnectMaxRetries')) { + return Configuration.getConfigurationData()?.autoReconnectMaxRetries; + } + } + + public static getStationTemplateUrls(): StationTemplateUrl[] | undefined { + Configuration.warnDeprecatedConfigurationKey( + 'stationTemplateURLs', + undefined, + "Use 'stationTemplateUrls' instead", + ); + // eslint-disable-next-line @typescript-eslint/dot-notation + !isUndefined(Configuration.getConfigurationData()!['stationTemplateURLs']) && + (Configuration.getConfigurationData()!.stationTemplateUrls = + Configuration.getConfigurationData()![ + // eslint-disable-next-line @typescript-eslint/dot-notation + 'stationTemplateURLs' + ] as StationTemplateUrl[]); + Configuration.getConfigurationData()!.stationTemplateUrls.forEach( + (stationTemplateUrl: StationTemplateUrl) => { + // eslint-disable-next-line @typescript-eslint/dot-notation + if (!isUndefined(stationTemplateUrl['numberOfStation'])) { + console.error( + `${chalk.green(Configuration.logPrefix())} ${chalk.red( + `Deprecated configuration key 'numberOfStation' usage for template file '${stationTemplateUrl.file}' in 'stationTemplateUrls'. Use 'numberOfStations' instead`, + )}`, + ); + } + }, + ); + return Configuration.getConfigurationData()?.stationTemplateUrls; + } + + public static workerPoolInUse(): boolean { + return [WorkerProcessType.dynamicPool, WorkerProcessType.staticPool].includes( + Configuration.buildWorkerSection().processType!, + ); + } + + public static workerDynamicPoolInUse(): boolean { + return Configuration.buildWorkerSection().processType === WorkerProcessType.dynamicPool; + } + + public static getSupervisionUrls(): string | string[] | undefined { + Configuration.warnDeprecatedConfigurationKey( + 'supervisionURLs', + undefined, + "Use 'supervisionUrls' instead", + ); + // eslint-disable-next-line @typescript-eslint/dot-notation + if (!isUndefined(Configuration.getConfigurationData()!['supervisionURLs'])) { + Configuration.getConfigurationData()!.supervisionUrls = Configuration.getConfigurationData()![ + // eslint-disable-next-line @typescript-eslint/dot-notation + 'supervisionURLs' + ] as string | string[]; + } + return Configuration.getConfigurationData()?.supervisionUrls; + } + + public static getSupervisionUrlDistribution(): SupervisionUrlDistribution | undefined { + Configuration.warnDeprecatedConfigurationKey( + 'distributeStationToTenantEqually', + undefined, + "Use 'supervisionUrlDistribution' instead", + ); + Configuration.warnDeprecatedConfigurationKey( + 'distributeStationsToTenantsEqually', + undefined, + "Use 'supervisionUrlDistribution' instead", + ); + return hasOwnProp(Configuration.getConfigurationData(), 'supervisionUrlDistribution') + ? Configuration.getConfigurationData()?.supervisionUrlDistribution + : SupervisionUrlDistribution.ROUND_ROBIN; + } + + private static buildUIServerSection(): UIServerConfiguration { if (hasOwnProp(Configuration.getConfigurationData(), 'uiWebSocketServer')) { console.error( `${chalk.green(Configuration.logPrefix())} ${chalk.red( @@ -78,13 +172,10 @@ export class Configuration { delete uiServerConfiguration.options?.host; uiServerConfiguration.options!.port = parseInt(process.env.PORT!); } - return Configuration.getConfigurationSection( - ConfigurationSection.uiServer, - uiServerConfiguration, - ); + return uiServerConfiguration; } - public static getPerformanceStorage(): StorageConfiguration { + private static buildPerformanceStorageSection(): StorageConfiguration { Configuration.warnDeprecatedConfigurationKey( 'URI', ConfigurationSection.performanceStorage, @@ -108,62 +199,10 @@ export class Configuration { }), }; } - return Configuration.getConfigurationSection( - ConfigurationSection.performanceStorage, - storageConfiguration, - ); + return storageConfiguration; } - public static getAutoReconnectMaxRetries(): number | undefined { - Configuration.warnDeprecatedConfigurationKey( - 'autoReconnectTimeout', - undefined, - "Use 'ConnectionTimeOut' OCPP parameter in charging station template instead", - ); - Configuration.warnDeprecatedConfigurationKey( - 'connectionTimeout', - undefined, - "Use 'ConnectionTimeOut' OCPP parameter in charging station template instead", - ); - Configuration.warnDeprecatedConfigurationKey( - 'autoReconnectMaxRetries', - undefined, - 'Use it in charging station template instead', - ); - if (hasOwnProp(Configuration.getConfigurationData(), 'autoReconnectMaxRetries')) { - return Configuration.getConfigurationData()?.autoReconnectMaxRetries; - } - } - - public static getStationTemplateUrls(): StationTemplateUrl[] | undefined { - Configuration.warnDeprecatedConfigurationKey( - 'stationTemplateURLs', - undefined, - "Use 'stationTemplateUrls' instead", - ); - // eslint-disable-next-line @typescript-eslint/dot-notation - !isUndefined(Configuration.getConfigurationData()!['stationTemplateURLs']) && - (Configuration.getConfigurationData()!.stationTemplateUrls = - Configuration.getConfigurationData()![ - // eslint-disable-next-line @typescript-eslint/dot-notation - 'stationTemplateURLs' - ] as StationTemplateUrl[]); - Configuration.getConfigurationData()!.stationTemplateUrls.forEach( - (stationTemplateUrl: StationTemplateUrl) => { - // eslint-disable-next-line @typescript-eslint/dot-notation - if (!isUndefined(stationTemplateUrl['numberOfStation'])) { - console.error( - `${chalk.green(Configuration.logPrefix())} ${chalk.red( - `Deprecated configuration key 'numberOfStation' usage for template file '${stationTemplateUrl.file}' in 'stationTemplateUrls'. Use 'numberOfStations' instead`, - )}`, - ); - } - }, - ); - return Configuration.getConfigurationData()?.stationTemplateUrls; - } - - public static getLog(): LogConfiguration { + private static buildLogSection(): LogConfiguration { Configuration.warnDeprecatedConfigurationKey( 'logEnabled', undefined, @@ -261,13 +300,10 @@ export class Configuration { ...(hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.log) && Configuration.getConfigurationData()?.log), }; - return Configuration.getConfigurationSection( - ConfigurationSection.log, - logConfiguration, - ); + return logConfiguration; } - public static getWorker(): WorkerConfiguration { + private static buildWorkerSection(): WorkerConfiguration { Configuration.warnDeprecatedConfigurationKey( 'useWorkerPool', undefined, @@ -359,52 +395,7 @@ export class Configuration { `Invalid worker process type '${workerConfiguration.processType}' defined in configuration`, ); } - return Configuration.getConfigurationSection( - ConfigurationSection.worker, - workerConfiguration, - ); - } - - public static workerPoolInUse(): boolean { - return [WorkerProcessType.dynamicPool, WorkerProcessType.staticPool].includes( - Configuration.getWorker().processType!, - ); - } - - public static workerDynamicPoolInUse(): boolean { - return Configuration.getWorker().processType === WorkerProcessType.dynamicPool; - } - - public static getSupervisionUrls(): string | string[] | undefined { - Configuration.warnDeprecatedConfigurationKey( - 'supervisionURLs', - undefined, - "Use 'supervisionUrls' instead", - ); - // eslint-disable-next-line @typescript-eslint/dot-notation - if (!isUndefined(Configuration.getConfigurationData()!['supervisionURLs'])) { - Configuration.getConfigurationData()!.supervisionUrls = Configuration.getConfigurationData()![ - // eslint-disable-next-line @typescript-eslint/dot-notation - 'supervisionURLs' - ] as string | string[]; - } - return Configuration.getConfigurationData()?.supervisionUrls; - } - - public static getSupervisionUrlDistribution(): SupervisionUrlDistribution | undefined { - Configuration.warnDeprecatedConfigurationKey( - 'distributeStationToTenantEqually', - undefined, - "Use 'supervisionUrlDistribution' instead", - ); - Configuration.warnDeprecatedConfigurationKey( - 'distributeStationsToTenantsEqually', - undefined, - "Use 'supervisionUrlDistribution' instead", - ); - return hasOwnProp(Configuration.getConfigurationData(), 'supervisionUrlDistribution') - ? Configuration.getConfigurationData()?.supervisionUrlDistribution - : SupervisionUrlDistribution.ROUND_ROBIN; + return workerConfiguration; } private static logPrefix = (): string => { @@ -441,16 +432,6 @@ export class Configuration { } } - private static getConfigurationSection( - sectionName: ConfigurationSection, - sectionConfiguration?: T, - ): T { - if (!Configuration.configurationSectionCache.has(sectionName) && sectionConfiguration) { - Configuration.configurationSectionCache.set(sectionName, sectionConfiguration); - } - return Configuration.configurationSectionCache.get(sectionName) as T; - } - private static getConfigurationData(): ConfigurationData | null { if (!Configuration.configurationData) { try { diff --git a/src/utils/Logger.ts b/src/utils/Logger.ts index a456fa73..1e22e405 100644 --- a/src/utils/Logger.ts +++ b/src/utils/Logger.ts @@ -5,17 +5,27 @@ import DailyRotateFile from 'winston-daily-rotate-file'; import { Configuration } from './Configuration'; import { insertAt } from './Utils'; +import { ConfigurationSection, type LogConfiguration } from '../types'; let transports: transport[]; -if (Configuration.getLog().rotate === true) { - const logMaxFiles = Configuration.getLog().maxFiles; - const logMaxSize = Configuration.getLog().maxSize; +if ( + Configuration.getConfigurationSection(ConfigurationSection.log).rotate === true +) { + const logMaxFiles = Configuration.getConfigurationSection( + ConfigurationSection.log, + ).maxFiles; + const logMaxSize = Configuration.getConfigurationSection( + ConfigurationSection.log, + ).maxSize; transports = [ new DailyRotateFile({ filename: insertAt( - Configuration.getLog().errorFile!, + Configuration.getConfigurationSection(ConfigurationSection.log) + .errorFile!, '-%DATE%', - Configuration.getLog().errorFile!.indexOf('.log'), + Configuration.getConfigurationSection( + ConfigurationSection.log, + ).errorFile!.indexOf('.log'), ), level: 'error', ...(logMaxFiles && { maxFiles: logMaxFiles }), @@ -23,9 +33,11 @@ if (Configuration.getLog().rotate === true) { }), new DailyRotateFile({ filename: insertAt( - Configuration.getLog().file!, + Configuration.getConfigurationSection(ConfigurationSection.log).file!, '-%DATE%', - Configuration.getLog().file!.indexOf('.log'), + Configuration.getConfigurationSection( + ConfigurationSection.log, + ).file!.indexOf('.log'), ), ...(logMaxFiles && { maxFiles: logMaxFiles }), ...(logMaxSize && { maxSize: logMaxSize }), @@ -33,15 +45,30 @@ if (Configuration.getLog().rotate === true) { ]; } else { transports = [ - new TransportType.File({ filename: Configuration.getLog().errorFile, level: 'error' }), - new TransportType.File({ filename: Configuration.getLog().file }), + new TransportType.File({ + filename: Configuration.getConfigurationSection(ConfigurationSection.log) + .errorFile, + level: 'error', + }), + new TransportType.File({ + filename: Configuration.getConfigurationSection(ConfigurationSection.log) + .file, + }), ]; } export const logger = createLogger({ - silent: !Configuration.getLog().enabled, - level: Configuration.getLog().level, - format: format.combine(format.splat(), (format[Configuration.getLog().format!] as FormatWrap)()), + silent: !Configuration.getConfigurationSection(ConfigurationSection.log) + .enabled, + level: Configuration.getConfigurationSection(ConfigurationSection.log).level, + format: format.combine( + format.splat(), + ( + format[ + Configuration.getConfigurationSection(ConfigurationSection.log).format! + ] as FormatWrap + )(), + ), transports, }); @@ -49,12 +76,17 @@ export const logger = createLogger({ // If enabled, log to the `console` with the format: // `${info.level}: ${info.message} JSON.stringify({ ...rest }) ` // -if (Configuration.getLog().console) { +if (Configuration.getConfigurationSection(ConfigurationSection.log).console) { logger.add( new TransportType.Console({ format: format.combine( format.splat(), - (format[Configuration.getLog().format!] as FormatWrap)(), + ( + format[ + Configuration.getConfigurationSection(ConfigurationSection.log) + .format! + ] as FormatWrap + )(), ), }), );