Add logs rotation.
authorJérôme Benoit <jerome.benoit@sap.com>
Wed, 11 Nov 2020 18:12:42 +0000 (19:12 +0100)
committerJérôme Benoit <jerome.benoit@sap.com>
Wed, 11 Nov 2020 18:12:42 +0000 (19:12 +0100)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
12 files changed:
.gitignore
docker/config.json
package-lock.json
package.json
src/assets/config-template.json
src/charging-station/AutomaticTransactionGenerator.ts
src/charging-station/ChargingStation.ts
src/types/ConfigurationData.ts
src/utils/Configuration.ts
src/utils/Logger.ts
src/utils/Statistics.ts
src/utils/Utils.ts

index afb29cd96f68c88b4b9a3047314d58231b4d5144..113248a3e780edeb236facfca7fcd9407e371d0e 100644 (file)
@@ -79,3 +79,6 @@ build/config.gypi
 # System Files
 .DS_Store
 Thumbs.db
+
+# Winston
+*-audit.json
index 02ec20602171034dcfcd1138f410d61b4c66577e..277f68f12f7a63361c77d428c3b45f15e365c0e9 100644 (file)
@@ -34,7 +34,7 @@
       "numberOfStations": 10
     }
   ],
-  "consoleLog": false,
+  "logConsole": false,
   "logFile": "/dev/stdout",
-  "errorFile": "/dev/stderr"
+  "logErrorFile": "/dev/stderr"
 }
index 58ee363bfde1f462d26678633c1ff5bf41e1505c..a7ed82c37b777a52a3f61f5b9ee06b37f84164eb 100644 (file)
         "flat-cache": "^2.0.1"
       }
     },
+    "file-stream-rotator": {
+      "version": "0.5.7",
+      "resolved": "https://registry.npmjs.org/file-stream-rotator/-/file-stream-rotator-0.5.7.tgz",
+      "integrity": "sha512-VYb3HZ/GiAGUCrfeakO8Mp54YGswNUHvL7P09WQcXAJNSj3iQ5QraYSp3cIn1MUyw6uzfgN/EFOarCNa4JvUHQ==",
+      "requires": {
+        "moment": "^2.11.2"
+      }
+    },
     "file-uri-to-path": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
         "xtend": "^4.0.0"
       }
     },
+    "moment": {
+      "version": "2.29.1",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
+      "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
+    },
     "morphdom": {
       "version": "2.6.1",
       "resolved": "https://registry.npmjs.org/morphdom/-/morphdom-2.6.1.tgz",
         }
       }
     },
+    "object-hash": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.0.3.tgz",
+      "integrity": "sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg=="
+    },
     "object-inspect": {
       "version": "1.7.0",
       "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
         }
       }
     },
+    "winston-daily-rotate-file": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-4.5.0.tgz",
+      "integrity": "sha512-/HqeWiU48dzGqcrABRlxYWVMdL6l3uKCtFSJyrqK+E2rLnSFNsgYpvwx15EgTitBLNzH69lQd/+z2ASryV2aqw==",
+      "requires": {
+        "file-stream-rotator": "^0.5.7",
+        "object-hash": "^2.0.1",
+        "triple-beam": "^1.3.0",
+        "winston-transport": "^4.2.0"
+      }
+    },
     "winston-transport": {
       "version": "4.4.0",
       "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz",
index b3dde3660ec7d00b2704fd01cf8fe4c014fa4eec..2aa64bed4f411d0fd1ab323bdd9980dda2f3bfac 100644 (file)
@@ -48,6 +48,7 @@
     "tslib": "^2.0.3",
     "uuid": "^8.3.1",
     "winston": "^3.3.3",
+    "winston-daily-rotate-file": "^4.5.0",
     "worker-threads-pool": "^2.0.0",
     "ws": "^7.4.0"
   },
index d55855febfe22ff2dca51fde9f314e4aca6a3c93..b3085a7c3af0d0a87046731c06e7daa93f0dd3bf 100644 (file)
@@ -31,6 +31,6 @@
     }
   ],
   "logFile": "combined.log",
-  "errorFile": "error.log",
-  "consoleLog": false
+  "logErrorFile": "error.log",
+  "logConsole": false
 }
index ac7b2008e1370dda7e566d973591e8e53fc8f107..399a9942fa0d7d64545c88fa4553c0956dbf8913 100644 (file)
@@ -29,7 +29,7 @@ export default class AutomaticTransactionGenerator {
 
   _logPrefix(connectorId: number = null): string {
     if (connectorId) {
-      return Utils.logPrefix(' ' + this._chargingStation.stationInfo.name + ' ATG on connector #' + connectorId + ':');
+      return Utils.logPrefix(' ' + this._chargingStation.stationInfo.name + ' ATG on connector #' + connectorId.toString() + ':');
     }
     return Utils.logPrefix(' ' + this._chargingStation.stationInfo.name + ' ATG:');
   }
@@ -54,7 +54,7 @@ export default class AutomaticTransactionGenerator {
     logger.info(this._logPrefix() + ' ATG OVER => STOPPING ALL TRANSACTIONS');
     for (const connector in this._chargingStation.connectors) {
       if (this._chargingStation.getConnector(Utils.convertToInt(connector)).transactionStarted) {
-        logger.info(this._logPrefix(Utils.convertToInt(connector)) + ' ATG OVER. Stop transaction ' + this._chargingStation.getConnector(Utils.convertToInt(connector)).transactionId);
+        logger.info(this._logPrefix(Utils.convertToInt(connector)) + ' ATG OVER. Stop transaction ' + this._chargingStation.getConnector(Utils.convertToInt(connector)).transactionId.toString());
         await this._chargingStation.sendStopTransaction(this._chargingStation.getConnector(Utils.convertToInt(connector)).transactionId, reason);
       }
     }
@@ -91,11 +91,11 @@ export default class AutomaticTransactionGenerator {
           // Wait until end of transaction
           const waitTrxEnd = Utils.getRandomInt(this._chargingStation.stationInfo.AutomaticTransactionGenerator.maxDuration,
             this._chargingStation.stationInfo.AutomaticTransactionGenerator.minDuration) * 1000;
-          logger.info(this._logPrefix(connectorId) + ' transaction ' + this._chargingStation.getConnector(connectorId).transactionId + ' will stop in ' + Utils.milliSecondsToHHMMSS(waitTrxEnd));
+          logger.info(this._logPrefix(connectorId) + ' transaction ' + this._chargingStation.getConnector(connectorId).transactionId.toString() + ' will stop in ' + Utils.milliSecondsToHHMMSS(waitTrxEnd));
           await Utils.sleep(waitTrxEnd);
           // Stop transaction
           if (this._chargingStation.getConnector(connectorId).transactionStarted) {
-            logger.info(this._logPrefix(connectorId) + ' stop transaction ' + this._chargingStation.getConnector(connectorId).transactionId);
+            logger.info(this._logPrefix(connectorId) + ' stop transaction ' + this._chargingStation.getConnector(connectorId).transactionId.toString());
             if (this._chargingStation.getEnableStatistics()) {
               const stopTransaction = performance.timerify(this.stopTransaction);
               this._performanceObserver.observe({ entryTypes: ['function'] });
index 843093e27fd226b17bbba8f7062b271a8808e5a6..734960464a25351be459f8f82952cb0659741aeb 100644 (file)
@@ -83,7 +83,7 @@ export default class ChargingStation {
       stationTemplateFromFile = JSON.parse(fs.readFileSync(fileDescriptor, 'utf8')) as ChargingStationTemplate;
       fs.closeSync(fileDescriptor);
     } catch (error) {
-      logger.error('Template file ' + this._stationTemplateFile + ' loading error: ' + error);
+      logger.error('Template file ' + this._stationTemplateFile + ' loading error: %j', error);
       throw error;
     }
     const stationInfo: ChargingStationInfo = stationTemplateFromFile || {} as ChargingStationInfo;
@@ -201,7 +201,7 @@ export default class ChargingStation {
         authorizedTags = JSON.parse(fs.readFileSync(fileDescriptor, 'utf8')) as string[];
         fs.closeSync(fileDescriptor);
       } catch (error) {
-        logger.error(this._logPrefix() + ' Authorization file ' + authorizationFile + ' loading error: ' + error);
+        logger.error(this._logPrefix() + ' Authorization file ' + authorizationFile + ' loading error: %j', error);
         throw error;
       }
     } else {
@@ -263,7 +263,7 @@ export default class ChargingStation {
     if (!Utils.isEmptyArray(this._stationInfo.numberOfConnectors)) {
       const numberOfConnectors = this._stationInfo.numberOfConnectors as number[];
       // Distribute evenly the number of connectors
-      maxConnectors = numberOfConnectors[(this._index - 1) % numberOfConnectors.length] ;
+      maxConnectors = numberOfConnectors[(this._index - 1) % numberOfConnectors.length];
     } else if (!Utils.isUndefined(this._stationInfo.numberOfConnectors)) {
       maxConnectors = this._stationInfo.numberOfConnectors as number;
     } else {
@@ -306,7 +306,7 @@ export default class ChargingStation {
   }
 
   _getSupervisionURL(): string {
-    const supervisionUrls = Utils.cloneObject(this._stationInfo.supervisionURL ? this._stationInfo.supervisionURL : Configuration.getSupervisionURLs()) as string|string[];
+    const supervisionUrls = Utils.cloneObject(this._stationInfo.supervisionURL ? this._stationInfo.supervisionURL : Configuration.getSupervisionURLs()) as string | string[];
     let indexUrl = 0;
     if (!Utils.isEmptyArray(supervisionUrls)) {
       if (Configuration.getDistributeStationToTenantEqually()) {
@@ -315,7 +315,7 @@ export default class ChargingStation {
         // Get a random url
         indexUrl = Math.floor(Math.random() * supervisionUrls.length);
       }
-      return supervisionUrls[indexUrl] ;
+      return supervisionUrls[indexUrl];
     }
     return supervisionUrls as string;
   }
@@ -404,7 +404,7 @@ export default class ChargingStation {
         // Initialize _authorizedTags
         this._authorizedTags = this._loadAndGetAuthorizedTags();
       } catch (error) {
-        logger.error(this._logPrefix() + ' Authorization file monitoring error: ' + error);
+        logger.error(this._logPrefix() + ' Authorization file monitoring error: %j', error);
       }
     });
   }
@@ -421,7 +421,7 @@ export default class ChargingStation {
           this._automaticTransactionGeneration.stop().catch(() => { });
         }
       } catch (error) {
-        logger.error(this._logPrefix() + ' Charging station template file monitoring error: ' + error);
+        logger.error(this._logPrefix() + ' Charging station template file monitoring error: %j', error);
       }
     });
   }
@@ -487,13 +487,13 @@ export default class ChargingStation {
   }
 
   _reconnect(error): void {
-    logger.error(this._logPrefix() + ' Socket: abnormally closed', error);
+    logger.error(this._logPrefix() + ' Socket: abnormally closed %j', error);
     // Stop the ATG if needed
     if (this._stationInfo.AutomaticTransactionGenerator.enable &&
       this._stationInfo.AutomaticTransactionGenerator.stopOnConnectionFailure &&
       this._automaticTransactionGeneration &&
       !this._automaticTransactionGeneration.timeToStop) {
-      this._automaticTransactionGeneration.stop().catch(() => {});
+      this._automaticTransactionGeneration.stop().catch(() => { });
     }
     // Stop heartbeat
     this._stopHeartbeat();
@@ -537,7 +537,7 @@ export default class ChargingStation {
         this._reconnect(error);
         break;
       default:
-        logger.error(this._logPrefix() + ' Socket error: ' + error);
+        logger.error(this._logPrefix() + ' Socket error: %j', error);
         break;
     }
   }
@@ -546,7 +546,7 @@ export default class ChargingStation {
     switch (error) {
       case 1000: // Normal close
       case 1005:
-        logger.info(this._logPrefix() + ' Socket normally closed ' + error);
+        logger.info(this._logPrefix() + ' Socket normally closed %j', error);
         this._autoReconnectRetryCount = 0;
         break;
       default: // Abnormal close
@@ -631,7 +631,7 @@ export default class ChargingStation {
       };
       await this.sendMessage(Utils.generateUUID(), payload, Constants.OCPP_JSON_CALL_MESSAGE, 'Heartbeat');
     } catch (error) {
-      logger.error(this._logPrefix() + ' Send Heartbeat error: ' + error);
+      logger.error(this._logPrefix() + ' Send Heartbeat error: %j', error);
       throw error;
     }
   }
@@ -640,7 +640,7 @@ export default class ChargingStation {
     try {
       await this.sendMessage(Utils.generateUUID(), this._bootNotificationMessage, Constants.OCPP_JSON_CALL_MESSAGE, 'BootNotification');
     } catch (error) {
-      logger.error(this._logPrefix() + ' Send BootNotification error: ' + error);
+      logger.error(this._logPrefix() + ' Send BootNotification error: %j', error);
       throw error;
     }
   }
@@ -655,7 +655,7 @@ export default class ChargingStation {
       };
       await this.sendMessage(Utils.generateUUID(), payload, Constants.OCPP_JSON_CALL_MESSAGE, 'StatusNotification');
     } catch (error) {
-      logger.error(this._logPrefix() + ' Send StatusNotification error: ' + error);
+      logger.error(this._logPrefix() + ' Send StatusNotification error: %j', error);
       throw error;
     }
   }
@@ -670,7 +670,7 @@ export default class ChargingStation {
       };
       return await this.sendMessage(Utils.generateUUID(), payload, Constants.OCPP_JSON_CALL_MESSAGE, 'StartTransaction') as StartTransactionResponse;
     } catch (error) {
-      logger.error(this._logPrefix() + ' Send StartTransaction error: ' + error);
+      logger.error(this._logPrefix() + ' Send StartTransaction error: %j', error);
       throw error;
     }
   }
@@ -687,7 +687,7 @@ export default class ChargingStation {
       };
       return await this.sendMessage(Utils.generateUUID(), payload, Constants.OCPP_JSON_CALL_MESSAGE, 'StopTransaction') as StartTransactionResponse;
     } catch (error) {
-      logger.error(this._logPrefix() + ' Send StopTransaction error: ' + error);
+      logger.error(this._logPrefix() + ' Send StopTransaction error: %j', error);
       throw error;
     }
   }
@@ -801,7 +801,7 @@ export default class ChargingStation {
               ...!Utils.isUndefined(meterValuesTemplate[index].context) && { context: meterValuesTemplate[index].context },
               ...!Utils.isUndefined(meterValuesTemplate[index].measurand) && { measurand: meterValuesTemplate[index].measurand },
               ...!Utils.isUndefined(meterValuesTemplate[index].location) && { location: meterValuesTemplate[index].location },
-              ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: powerMeasurandValues[`L${phase}`] },
+              ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: powerMeasurandValues[`L${phase}`] as string },
               phase: phaseValue as MeterValuePhase,
             });
           }
@@ -862,7 +862,7 @@ export default class ChargingStation {
               ...!Utils.isUndefined(meterValuesTemplate[index].context) && { context: meterValuesTemplate[index].context },
               ...!Utils.isUndefined(meterValuesTemplate[index].measurand) && { measurand: meterValuesTemplate[index].measurand },
               ...!Utils.isUndefined(meterValuesTemplate[index].location) && { location: meterValuesTemplate[index].location },
-              ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: currentMeasurandValues[phaseValue] },
+              ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: currentMeasurandValues[phaseValue] as string },
               phase: phaseValue as MeterValuePhase,
             });
           }
@@ -892,7 +892,8 @@ export default class ChargingStation {
             ...!Utils.isUndefined(meterValuesTemplate[index].context) && { context: meterValuesTemplate[index].context },
             ...!Utils.isUndefined(meterValuesTemplate[index].measurand) && { measurand: meterValuesTemplate[index].measurand },
             ...!Utils.isUndefined(meterValuesTemplate[index].location) && { location: meterValuesTemplate[index].location },
-            ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } : { value: connector.lastEnergyActiveImportRegisterValue.toString() },
+            ...!Utils.isUndefined(meterValuesTemplate[index].value) ? { value: meterValuesTemplate[index].value } :
+              { value: connector.lastEnergyActiveImportRegisterValue.toString() },
           });
           const sampledValuesIndex = sampledValues.sampledValue.length - 1;
           const maxConsumption = Math.round(self._stationInfo.maxPower * 3600 / (self._stationInfo.powerDivider * interval));
@@ -912,7 +913,7 @@ export default class ChargingStation {
       };
       await self.sendMessage(Utils.generateUUID(), payload, Constants.OCPP_JSON_CALL_MESSAGE, 'MeterValues');
     } catch (error) {
-      logger.error(self._logPrefix() + ' Send MeterValues error: ' + error);
+      logger.error(self._logPrefix() + ' Send MeterValues error: %j', error);
       throw error;
     }
   }
@@ -1045,46 +1046,47 @@ export default class ChargingStation {
   }
 
   handleResponseStartTransaction(payload: StartTransactionResponse, requestPayload): void {
-    if (this.getConnector(requestPayload.connectorId).transactionStarted) {
-      logger.debug(this._logPrefix() + ' Try to start a transaction on an already used connector ' + requestPayload.connectorId + ': %s', this.getConnector(requestPayload.connectorId));
+    const connectorId = Utils.convertToInt(requestPayload.connectorId);
+    if (this.getConnector(connectorId).transactionStarted) {
+      logger.debug(this._logPrefix() + ' Try to start a transaction on an already used connector ' + connectorId.toString() + ': %j', this.getConnector(connectorId));
       return;
     }
 
     let transactionConnectorId: number;
     for (const connector in this._connectors) {
-      if (Utils.convertToInt(connector) === Utils.convertToInt(requestPayload.connectorId)) {
+      if (Utils.convertToInt(connector) === connectorId) {
         transactionConnectorId = Utils.convertToInt(connector);
         break;
       }
     }
     if (!transactionConnectorId) {
-      logger.error(this._logPrefix() + ' Try to start a transaction on a non existing connector Id ' + requestPayload.connectorId);
+      logger.error(this._logPrefix() + ' Try to start a transaction on a non existing connector Id ' + connectorId.toString());
       return;
     }
     if (payload.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
-      this.getConnector(requestPayload.connectorId).transactionStarted = true;
-      this.getConnector(requestPayload.connectorId).transactionId = payload.transactionId;
-      this.getConnector(requestPayload.connectorId).idTag = requestPayload.idTag;
-      this.getConnector(requestPayload.connectorId).lastEnergyActiveImportRegisterValue = 0;
-      this.sendStatusNotification(requestPayload.connectorId, ChargePointStatus.CHARGING);
-      logger.info(this._logPrefix() + ' Transaction ' + payload.transactionId + ' STARTED on ' + this._stationInfo.name + '#' + requestPayload.connectorId + ' for idTag ' + requestPayload.idTag);
+      this.getConnector(connectorId).transactionStarted = true;
+      this.getConnector(connectorId).transactionId = payload.transactionId;
+      this.getConnector(connectorId).idTag = requestPayload.idTag;
+      this.getConnector(connectorId).lastEnergyActiveImportRegisterValue = 0;
+      this.sendStatusNotification(connectorId, ChargePointStatus.CHARGING).catch(() => { });
+      logger.info(this._logPrefix() + ' Transaction ' + payload.transactionId.toString() + ' STARTED on ' + this._stationInfo.name + '#' + connectorId.toString() + ' for idTag ' + requestPayload.idTag);
       if (this._stationInfo.powerSharedByConnectors) {
         this._stationInfo.powerDivider++;
       }
       const configuredMeterValueSampleInterval = this._getConfigurationKey('MeterValueSampleInterval');
-      this._startMeterValues(requestPayload.connectorId,
+      this._startMeterValues(connectorId,
         configuredMeterValueSampleInterval ? Utils.convertToInt(configuredMeterValueSampleInterval.value) * 1000 : 60000);
     } else {
-      logger.error(this._logPrefix() + ' Starting transaction id ' + payload.transactionId + ' REJECTED with status ' + payload.idTagInfo?.status + ', idTag ' + requestPayload.idTag);
-      this._resetTransactionOnConnector(requestPayload.connectorId);
-      this.sendStatusNotification(requestPayload.connectorId, ChargePointStatus.AVAILABLE);
+      logger.error(this._logPrefix() + ' Starting transaction id ' + payload.transactionId.toString() + ' REJECTED with status ' + payload.idTagInfo?.status + ', idTag ' + requestPayload.idTag);
+      this._resetTransactionOnConnector(connectorId);
+      this.sendStatusNotification(connectorId, ChargePointStatus.AVAILABLE).catch(() => { });
     }
   }
 
   handleResponseStopTransaction(payload: StopTransactionResponse, requestPayload): void {
     let transactionConnectorId: number;
     for (const connector in this._connectors) {
-      if (this.getConnector(Utils.convertToInt(connector)).transactionId === requestPayload.transactionId) {
+      if (this.getConnector(Utils.convertToInt(connector)).transactionId === Utils.convertToInt(requestPayload.transactionId)) {
         transactionConnectorId = Utils.convertToInt(connector);
         break;
       }
@@ -1094,7 +1096,7 @@ export default class ChargingStation {
       return;
     }
     if (payload.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
-      this.sendStatusNotification(transactionConnectorId, ChargePointStatus.AVAILABLE);
+      this.sendStatusNotification(transactionConnectorId, ChargePointStatus.AVAILABLE).catch(() => { });
       if (this._stationInfo.powerSharedByConnectors) {
         this._stationInfo.powerDivider--;
       }
@@ -1126,7 +1128,7 @@ export default class ChargingStation {
         response = await this['handleRequest' + commandName](commandPayload);
       } catch (error) {
         // Log
-        logger.error(this._logPrefix() + ' Handle request error: ' + error);
+        logger.error(this._logPrefix() + ' Handle request error: %j', error);
         // Send back response to inform backend
         await this.sendError(messageId, error, commandName);
         throw error;
@@ -1295,7 +1297,7 @@ export default class ChargingStation {
         return Constants.OCPP_RESPONSE_ACCEPTED;
       }
     }
-    logger.info(this._logPrefix() + ' Try to stop remotely a non existing transaction ' + commandPayload.transactionId);
+    logger.info(this._logPrefix() + ' Try to stop remotely a non existing transaction ' + transactionId.toString());
     return Constants.OCPP_RESPONSE_REJECTED;
   }
 }
index 29a443aabd2e118cc896c9fbb1d162327726c278..3f51cb85c951184d6efe680d06272236bce08339 100644 (file)
@@ -15,6 +15,6 @@ export default interface ConfigurationData {
   logFormat?: string;
   logLevel?: string;
   logFile?: string;
-  errorFile?: string;
-  consoleLog?: boolean;
+  logErrorFile?: string;
+  logConsole?: boolean;
 }
index d15f90537aea9a1975d2cb1d46c0efa658acb9be..ab48cf310a1d9944bfcb0b763b6ff513edb368f8 100644 (file)
@@ -42,8 +42,8 @@ export default class Configuration {
     return Configuration.getConfig().workerPoolSize;
   }
 
-  static getConsoleLog(): boolean {
-    return Utils.objectHasOwnProperty(Configuration.getConfig(), 'consoleLog') ? Configuration.getConfig().consoleLog : false;
+  static getLogConsole(): boolean {
+    return Utils.objectHasOwnProperty(Configuration.getConfig(), 'logConsole') ? Configuration.getConfig().logConsole : false;
   }
 
   static getLogFormat(): string {
@@ -58,8 +58,8 @@ export default class Configuration {
     return Utils.objectHasOwnProperty(Configuration.getConfig(), 'logFile') ? Configuration.getConfig().logFile : 'combined.log';
   }
 
-  static getErrorFile(): string {
-    return Utils.objectHasOwnProperty(Configuration.getConfig(), 'errorFile') ? Configuration.getConfig().errorFile : 'error.log';
+  static getLogErrorFile(): string {
+    return Utils.objectHasOwnProperty(Configuration.getConfig(), 'logErrorFile') ? Configuration.getConfig().logErrorFile : 'error.log';
   }
 
   static getSupervisionURLs(): string[] {
index 736e9b89732f73435683c014fca1fd6b2ce909c4..e45550c98a536d0c63a1d99d4e256526b736b89e 100644 (file)
@@ -1,16 +1,21 @@
+import 'winston-daily-rotate-file';
+
 import Configuration from './Configuration';
-import Winston from 'winston';
+import Utils from './Utils';
+import winston from 'winston';
+
+const maxLogFiles = 7;
 
-const logger = Winston.createLogger({
+const logger = winston.createLogger({
   level: Configuration.getLogLevel(),
-  format: Winston.format.combine(Winston.format.splat(), Winston.format[Configuration.getLogFormat()]()),
+  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.File({ filename: Configuration.getErrorFile(), level: 'error' }),
-    new Winston.transports.File({ filename: Configuration.getLogFile() }),
+    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 }),
   ],
 });
 
@@ -18,9 +23,9 @@ const logger = Winston.createLogger({
 // If enabled, log to the `console` with the format:
 // `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
 //
-if (Configuration.getConsoleLog()) {
-  logger.add(new Winston.transports.Console({
-    format: Winston.format.combine(Winston.format.splat(), Winston.format[Configuration.getLogFormat()]()),
+if (Configuration.getLogConsole()) {
+  logger.add(new winston.transports.Console({
+    format: winston.format.combine(winston.format.splat(), winston.format[Configuration.getLogFormat()]()),
   }));
 }
 
index f2bfee4ffc53208a9cf531ab7bb3be892403b01b..0f0674d1a08240e0343d57ea74c848957ea79882 100644 (file)
@@ -67,28 +67,6 @@ export default class Statistics {
     }
   }
 
-  addPerformanceTimer(command: string, duration: number): void {
-    // Map to proper command name
-    const MAPCOMMAND = {
-      sendMeterValues: 'MeterValues',
-      startTransaction: 'StartTransaction',
-      stopTransaction: 'StopTransaction',
-    };
-    if (MAPCOMMAND[command]) {
-      command = MAPCOMMAND[command] as string;
-    }
-    // Initialize command statistics
-    if (!this._commandsStatistics[command]) {
-      this._commandsStatistics[command] = {} as CommandStatisticsData;
-    }
-    // Update current statistics timers
-    this._commandsStatistics[command].countTime = this._commandsStatistics[command].countTime ? this._commandsStatistics[command].countTime + 1 : 1;
-    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].countTime;
-  }
-
   logPerformance(entry: PerformanceEntry, className: string): void {
     this.addPerformanceTimer(entry.name, entry.duration);
     logger.info(`${this._logPrefix()} class->${className}, method->${entry.name}, duration->${entry.duration}`);
@@ -103,7 +81,7 @@ export default class Statistics {
       setInterval(() => {
         this._display();
       }, Configuration.getStatisticsDisplayInterval() * 1000);
-      logger.info(this._logPrefix() + ' displayed every ' + Configuration.getStatisticsDisplayInterval().toString() + 's');
+      logger.info(this._logPrefix() + ' displayed every ' + Utils.secondsToHHMMSS(Configuration.getStatisticsDisplayInterval()));
     }
   }
 
@@ -111,6 +89,28 @@ export default class Statistics {
     this._displayInterval();
   }
 
+  private addPerformanceTimer(command: string, duration: number): void {
+    // Map to proper command name
+    const MAPCOMMAND = {
+      sendMeterValues: 'MeterValues',
+      startTransaction: 'StartTransaction',
+      stopTransaction: 'StopTransaction',
+    };
+    if (MAPCOMMAND[command]) {
+      command = MAPCOMMAND[command] as string;
+    }
+    // Initialize command statistics
+    if (!this._commandsStatistics[command]) {
+      this._commandsStatistics[command] = {} as CommandStatisticsData;
+    }
+    // Update current statistics timers
+    this._commandsStatistics[command].countTime = this._commandsStatistics[command].countTime ? this._commandsStatistics[command].countTime + 1 : 1;
+    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].countTime;
+  }
+
   private _logPrefix(): string {
     return Utils.logPrefix(` ${this._objName} Statistics:`);
   }
index 52a2b0ee7dc420682bfccb4b29f786dec6ee707a..167e299df27c075641927e0b884ee6bd76d7dbc6 100644 (file)
@@ -149,7 +149,7 @@ export default class Utils {
     return typeof value === 'string';
   }
 
-  static isUndefined(value) {
+  static isUndefined(value): boolean {
     return typeof value === 'undefined';
   }
 
@@ -171,4 +171,6 @@ export default class Utils {
   static isEmptyObject(obj): boolean {
     return !Object.keys(obj).length;
   }
+
+  static insertAt = (str: string, subStr: string, pos: number): string => `${str.slice(0, pos)}${subStr}${str.slice(pos)}`;
 }