diff --git a/lib/AuditManager.js b/lib/AuditManager.js index c5b5367..b56b904 100644 --- a/lib/AuditManager.js +++ b/lib/AuditManager.js @@ -5,6 +5,7 @@ const path = require("path"); const enums_1 = require("./enums"); const helper_1 = require("./helper"); const crypto = require("crypto"); +const sleep = require("sleep-promise"); class AuditManager { constructor(config, emitter) { this.config = config; @@ -52,36 +53,46 @@ class AuditManager { helper_1.Logger.debug("file already in the log", name); return; } - var time = Date.now(); - this.config.files.push({ - date: time, - name: name, - hash: crypto.createHash(this.config.hashType).update(name + "LOG_FILE" + time).digest("hex") - }); - helper_1.Logger.debug(`added file ${name} to log`); - if (this.config.keepSettings && this.config.keepSettings.amount) { - if (this.config.keepSettings.type == enums_1.KeepLogFiles.days) { - let date = Date.now() - 86400 * this.config.keepSettings.amount * 1000; - let files = this.config.files.filter((logEntry) => { - if (logEntry.date >= date) { - return true; - } - this.removeLog(logEntry); + // add a random sleep to avoid concurrent writes to the same file + sleep(Math.random() * 1000).then(() => { + // read audit file again before updating it (mainly for nodejs cluster mode with concurrent writes from workers) + this.loadLog(); + // check if file name is already present in the audit file and don't + // include it in case is already there (mainly for nodejs cluster mode with concurrent writes from workers) + var fileIsPresent = this.config.files.some((file) => file.name === name); + if (!fileIsPresent) { + var time = Date.now(); + this.config.files.push({ + date: time, + name: name, + hash: crypto.createHash(this.config.hashType).update(name + "LOG_FILE" + time).digest("hex") }); - this.config.files = files; + helper_1.Logger.debug(`added file ${name} to log`); } - else if (this.config.files.length > this.config.keepSettings.amount) { - var filesToKeep = this.config.files.splice(-this.config.keepSettings.amount); - if (this.config.files.length > 0) { - this.config.files.filter((logEntry) => { + if (this.config.keepSettings && this.config.keepSettings.amount) { + if (this.config.keepSettings.type == enums_1.KeepLogFiles.days) { + let date = Date.now() - 86400 * this.config.keepSettings.amount * 1000; + let files = this.config.files.filter((logEntry) => { + if (logEntry.date >= date) { + return true; + } this.removeLog(logEntry); - return false; }); + this.config.files = files; + } + else if (this.config.files.length > this.config.keepSettings.amount) { + var filesToKeep = this.config.files.splice(-this.config.keepSettings.amount); + if (this.config.files.length > 0) { + this.config.files.filter((logEntry) => { + this.removeLog(logEntry); + return false; + }); + } + this.config.files = filesToKeep; } - this.config.files = filesToKeep; } - } - this.writeLog(); + this.writeLog(); + }); } removeLog(logEntry) { if (logEntry.hash === crypto.createHash(this.config.hashType).update(logEntry.name + "LOG_FILE" + logEntry.date).digest("hex")) { diff --git a/package-lock.json b/package-lock.json index 8a1a953..1414243 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,38 +1,8 @@ { "name": "file-stream-rotator", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "file-stream-rotator", - "version": "1.0.0", - "license": "MIT", - "devDependencies": { - "@types/node": "^18.11.3", - "typescript": "^4.8.4" - } - }, - "node_modules/@types/node": { - "version": "18.11.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.3.tgz", - "integrity": "sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A==", - "dev": true - }, - "node_modules/typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - } - }, "dependencies": { "@types/node": { "version": "18.11.3", @@ -40,6 +10,11 @@ "integrity": "sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A==", "dev": true }, + "sleep-promise": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/sleep-promise/-/sleep-promise-9.1.0.tgz", + "integrity": "sha512-UHYzVpz9Xn8b+jikYSD6bqvf754xL2uBUzDFwiU6NcdZeifPr6UfgU43xpkPu67VMS88+TI2PSI7Eohgqf2fKA==" + }, "typescript": { "version": "4.8.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", diff --git a/package.json b/package.json index f2ef106..c0123f8 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,9 @@ ], "author": "Roger Castells", "license": "MIT", - "dependencies": {}, + "dependencies": { + "sleep-promise": "^9.1.0" + }, "devDependencies": { "@types/node": "^18.11.3", "typescript": "^4.8.4" diff --git a/src/AuditManager.ts b/src/AuditManager.ts index 93e4dd7..e3e1f67 100644 --- a/src/AuditManager.ts +++ b/src/AuditManager.ts @@ -5,6 +5,7 @@ import { Logger, makeDirectory } from "./helper"; import { AuditConfigFile, AuditEntry, AuditSettings } from "./types"; import * as crypto from "crypto" import { EventEmitter } from "stream"; +import * as sleep from "sleep-promise"; export default class AuditManager { @@ -59,38 +60,48 @@ export default class AuditManager { return } - var time = Date.now(); - this.config.files.push({ - date: time, - name: name, - hash: crypto.createHash(this.config.hashType).update(name + "LOG_FILE" + time).digest("hex") - }); - Logger.debug(`added file ${name} to log`) + // add a random sleep to avoid concurrent writes to the same file + sleep(Math.random() * 1000).then(() => { + // read audit file again before updating it (mainly for nodejs cluster mode with concurrent writes from workers) + this.loadLog(); + // check if file name is already present in the audit file and don't + // include it in case is already there (mainly for nodejs cluster mode with concurrent writes from workers) + var fileIsPresent = this.config.files.some((file) => file.name === name); + if (!fileIsPresent) { + var time = Date.now(); + this.config.files.push({ + date: time, + name: name, + hash: crypto.createHash(this.config.hashType).update(name + "LOG_FILE" + time).digest("hex") + }); + Logger.debug(`added file ${name} to log`) + } - if (this.config.keepSettings && this.config.keepSettings.amount){ - if(this.config.keepSettings.type == KeepLogFiles.days){ - let date = Date.now() - 86400*this.config.keepSettings.amount*1000 - let files = this.config.files.filter((logEntry) => { - if (logEntry.date >= date) { - return true - } - this.removeLog(logEntry) - }) - - this.config.files = files - } else if (this.config.files.length > this.config.keepSettings.amount){ - var filesToKeep = this.config.files.splice(-this.config.keepSettings.amount); - if(this.config.files.length > 0){ - this.config.files.filter((logEntry) => { - this.removeLog(logEntry); - return false; + if (this.config.keepSettings && this.config.keepSettings.amount){ + if(this.config.keepSettings.type == KeepLogFiles.days){ + let date = Date.now() - 86400*this.config.keepSettings.amount*1000 + let files = this.config.files.filter((logEntry) => { + if (logEntry.date >= date) { + return true + } + this.removeLog(logEntry) }) + + this.config.files = files + } else if (this.config.files.length > this.config.keepSettings.amount){ + var filesToKeep = this.config.files.splice(-this.config.keepSettings.amount); + if(this.config.files.length > 0){ + this.config.files.filter((logEntry) => { + this.removeLog(logEntry); + return false; + }) + } + this.config.files = filesToKeep } - this.config.files = filesToKeep } - } - this.writeLog() + this.writeLog() + }); } private removeLog(logEntry: AuditEntry){