From: Jérôme Benoit Date: Fri, 13 Nov 2020 23:14:33 +0000 (+0100) Subject: Add median to statistics. X-Git-Tag: v1.0.1-0~199 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=6bf6769ef4ee4fd3935a442243984a8aa2136e53;p=e-mobility-charging-stations-simulator.git Add median to statistics. Signed-off-by: Jérôme Benoit --- diff --git a/docker/config.json b/docker/config.json index f5b36a17..aee90bc7 100644 --- a/docker/config.json +++ b/docker/config.json @@ -34,6 +34,7 @@ "numberOfStations": 10 } ], + "logRotate": false, "logConsole": false, "logFile": "/dev/stdout", "logErrorFile": "/dev/stderr" diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index 85a944b5..600ec077 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -488,7 +488,7 @@ export default class ChargingStation { } _reconnect(error): void { - logger.error(this._logPrefix() + ' Socket: abnormally closed %j', error); + logger.error(this._logPrefix() + ' Socket: abnormally closed: %j', error); // Stop the ATG if needed if (this._stationInfo.AutomaticTransactionGenerator.enable && this._stationInfo.AutomaticTransactionGenerator.stopOnConnectionFailure && @@ -548,7 +548,7 @@ export default class ChargingStation { switch (closeEvent) { case 1000: // Normal close case 1005: - logger.info(this._logPrefix() + ' Socket normally closed %j', closeEvent); + logger.info(this._logPrefix() + ' Socket normally closed: %j', closeEvent); this._autoReconnectRetryCount = 0; break; default: // Abnormal close @@ -1000,7 +1000,7 @@ export default class ChargingStation { if (self.getEnableStatistics()) { self._statistics.addMessage(commandName, messageType); } - logger.debug(`${self._logPrefix()} Error %j occurred when calling command %s with parameters %j`, error, commandName, commandParams); + logger.debug(`${self._logPrefix()} Error: %j occurred when calling command %s with parameters: %j`, error, commandName, commandParams); // Build Exception // eslint-disable-next-line no-empty-function self._requests[messageId] = [() => { }, () => { }, {}]; // Properly format the request diff --git a/src/types/CommandStatistics.ts b/src/types/CommandStatistics.ts index 88375395..9c1896f4 100644 --- a/src/types/CommandStatistics.ts +++ b/src/types/CommandStatistics.ts @@ -1,13 +1,24 @@ +import { EntryType } from 'perf_hooks'; + +export interface PerfEntry { + name: string; + entryType: EntryType; + startTime: number; + duration: number; +} + export interface CommandStatisticsData { countRequest: number; countResponse: number; countError: number; countTimeMeasurement: number; - currentTime: number; - minTime: number; - maxTime: number; - totalTime: number; - avgTime: number; + timeMeasurementSeries: number[]; + currentTimeMeasurement: number; + minTimeMeasurement: number; + maxTimeMeasurement: number; + totalTimeMeasurement: number; + avgTimeMeasurement: number; + medTimeMeasurement: number; } export default interface CommandStatistics { diff --git a/src/types/ConfigurationData.ts b/src/types/ConfigurationData.ts index 0570531d..bf4420ec 100644 --- a/src/types/ConfigurationData.ts +++ b/src/types/ConfigurationData.ts @@ -14,6 +14,8 @@ export default interface ConfigurationData { workerPoolSize?: number; logFormat?: string; logLevel?: string; + logRotate?: boolean; + logMaxFiles?: number; logFile?: string; logErrorFile?: string; logConsole?: boolean; diff --git a/src/utils/Configuration.ts b/src/utils/Configuration.ts index 9492bb9b..57aa1ad9 100644 --- a/src/utils/Configuration.ts +++ b/src/utils/Configuration.ts @@ -50,6 +50,14 @@ export default class Configuration { return Utils.objectHasOwnProperty(Configuration.getConfig(), 'logFormat') ? Configuration.getConfig().logFormat : 'simple'; } + static getLogRotate(): boolean { + return Utils.objectHasOwnProperty(Configuration.getConfig(), 'logRotate') ? Configuration.getConfig().logRotate : true; + } + + static getLogMaxFiles(): number { + return Utils.objectHasOwnProperty(Configuration.getConfig(), 'logMaxFiles') ? Configuration.getConfig().logMaxFiles : 7; + } + static getLogLevel(): string { return Utils.objectHasOwnProperty(Configuration.getConfig(), 'logLevel') ? Configuration.getConfig().logLevel : 'info'; } diff --git a/src/utils/ElectricUtils.ts b/src/utils/ElectricUtils.ts index 7df3db73..dba823ab 100644 --- a/src/utils/ElectricUtils.ts +++ b/src/utils/ElectricUtils.ts @@ -1,4 +1,5 @@ /** + * Rationale: https://wiki.piment-noir.org/doku.php/en:cs:modelling_multi-phased_electrical_system_interconnexion * Targeted to AC related values calculation. * To use for DC, always consider cosPhi = 1 and do not use per phase helpers */ diff --git a/src/utils/Logger.ts b/src/utils/Logger.ts index e45550c9..dfd04e90 100644 --- a/src/utils/Logger.ts +++ b/src/utils/Logger.ts @@ -1,22 +1,28 @@ import 'winston-daily-rotate-file'; +import winston, { transport } from 'winston'; + import Configuration from './Configuration'; import Utils from './Utils'; -import winston from 'winston'; -const maxLogFiles = 7; +let transports: transport[]; +if (Configuration.getLogRotate()) { + const logMaxFiles = Configuration.getLogMaxFiles(); + transports = [ + new winston.transports.DailyRotateFile({ filename: Utils.insertAt(Configuration.getLogErrorFile(), '-%DATE%', Configuration.getLogErrorFile().indexOf('.log')), level: 'error', maxFiles: logMaxFiles }), + new winston.transports.DailyRotateFile({ filename: Utils.insertAt(Configuration.getLogFile(), '-%DATE%', Configuration.getLogFile().indexOf('.log')), maxFiles: logMaxFiles }), + ]; +} else { + transports = [ + new winston.transports.File({ filename: Configuration.getLogErrorFile(), level: 'error' }), + new winston.transports.File({ filename: Configuration.getLogFile() }), + ]; +} const logger = winston.createLogger({ level: Configuration.getLogLevel(), format: winston.format.combine(winston.format.splat(), winston.format[Configuration.getLogFormat()]()), - transports: [ - // - // - Write to all logs with level `info` and below to `combined.log` - // - Write all logs error (and below) to `error.log`. - // - new winston.transports.DailyRotateFile({ filename: Utils.insertAt(Configuration.getLogErrorFile(), '-%DATE%', Configuration.getLogErrorFile().indexOf('.log')), level: 'error', maxFiles: maxLogFiles }), - new winston.transports.DailyRotateFile({ filename: Utils.insertAt(Configuration.getLogFile(), '-%DATE%', Configuration.getLogFile().indexOf('.log')), maxFiles: maxLogFiles }), - ], + transports: transports, }); // diff --git a/src/utils/Statistics.ts b/src/utils/Statistics.ts index c2ad25a9..3fa4c783 100644 --- a/src/utils/Statistics.ts +++ b/src/utils/Statistics.ts @@ -1,4 +1,4 @@ -import CommandStatistics, { CommandStatisticsData } from '../types/CommandStatistics'; +import CommandStatistics, { CommandStatisticsData, PerfEntry } from '../types/CommandStatistics'; import Configuration from './Configuration'; import Constants from './Constants'; @@ -68,7 +68,12 @@ export default class Statistics { logPerformance(entry: PerformanceEntry, className: string): void { this.addPerformanceTimer(entry.name, entry.duration); - logger.info(`${this._logPrefix()} class->${className}, method->${entry.name}, duration->${entry.duration}`); + const perfEntry: PerfEntry = {} as PerfEntry; + perfEntry.name = entry.name; + perfEntry.entryType = entry.entryType; + perfEntry.startTime = entry.startTime; + perfEntry.duration = entry.duration; + logger.info(`${this._logPrefix()} object ${className} method performance entry: %j`, perfEntry); } _display(): void { @@ -88,6 +93,18 @@ export default class Statistics { this._displayInterval(); } + private median(dataSet: number[]): number { + if (Array.isArray(dataSet) && dataSet.length === 1) { + return dataSet[0]; + } + const sortedDataSet = dataSet.slice().sort(); + const middleIndex = Math.floor(sortedDataSet.length / 2); + if (sortedDataSet.length % 2) { + return sortedDataSet[middleIndex / 2]; + } + return (sortedDataSet[(middleIndex - 1)] + sortedDataSet[middleIndex]) / 2; + } + private addPerformanceTimer(command: string, duration: number): void { // Map to proper command name const MAPCOMMAND = { @@ -104,11 +121,13 @@ export default class Statistics { } // Update current statistics timers this._commandsStatistics[command].countTimeMeasurement = this._commandsStatistics[command].countTimeMeasurement ? this._commandsStatistics[command].countTimeMeasurement + 1 : 1; - this._commandsStatistics[command].currentTime = duration; - this._commandsStatistics[command].minTime = this._commandsStatistics[command].minTime ? (this._commandsStatistics[command].minTime > duration ? duration : this._commandsStatistics[command].minTime) : duration; - this._commandsStatistics[command].maxTime = this._commandsStatistics[command].maxTime ? (this._commandsStatistics[command].maxTime < duration ? duration : this._commandsStatistics[command].maxTime) : duration; - this._commandsStatistics[command].totalTime = this._commandsStatistics[command].totalTime ? this._commandsStatistics[command].totalTime + duration : duration; - this._commandsStatistics[command].avgTime = this._commandsStatistics[command].totalTime / this._commandsStatistics[command].countTimeMeasurement; + this._commandsStatistics[command].currentTimeMeasurement = duration; + this._commandsStatistics[command].minTimeMeasurement = this._commandsStatistics[command].minTimeMeasurement ? (this._commandsStatistics[command].minTimeMeasurement > duration ? duration : this._commandsStatistics[command].minTimeMeasurement) : duration; + this._commandsStatistics[command].maxTimeMeasurement = this._commandsStatistics[command].maxTimeMeasurement ? (this._commandsStatistics[command].maxTimeMeasurement < duration ? duration : this._commandsStatistics[command].maxTimeMeasurement) : duration; + this._commandsStatistics[command].totalTimeMeasurement = this._commandsStatistics[command].totalTimeMeasurement ? this._commandsStatistics[command].totalTimeMeasurement + duration : duration; + this._commandsStatistics[command].avgTimeMeasurement = this._commandsStatistics[command].totalTimeMeasurement / this._commandsStatistics[command].countTimeMeasurement; + Array.isArray(this._commandsStatistics[command].timeMeasurementSeries) ? this._commandsStatistics[command].timeMeasurementSeries.push(duration) : this._commandsStatistics[command].timeMeasurementSeries = [duration]; + this._commandsStatistics[command].medTimeMeasurement = this.median(this._commandsStatistics[command].timeMeasurementSeries); } private _logPrefix(): string {