diff --git a/.eslintrc.json b/.eslintrc.json index 00e6adb..0028d90 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -76,10 +76,10 @@ ], "lines-around-comment": "warn", "lines-around-directive": "warn", - "lines-between-class-members": [ - "warn", - "always" - ], + // "lines-between-class-members": [ + // "warn", + // "always" + // ], "max-classes-per-file": "warn", "max-nested-callbacks": "warn", "new-parens": "warn", diff --git a/README.md b/README.md index 72ed1e0..a063a62 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ The child processes are expected to be attached with the attach() method found i { //////// SHARED BETWEEN CLIENT & MASTER guard: '_logger', // Message guard, e.g this property has to be true in the IPC message for the logger to read it - debug: false, // On the master logger this determines whether the output is written to console (i.e. will always be written to file), on the client this determines whether it is sent to the master at all + loglevel: false, // On the master logger this determines whether the output is written to console (i.e. will always be written to file), on the client this determines whether it is sent to the master at all customTypes: [], // Log types, defaults are 'error', 'warn', 'info', 'debug', 'status'. Each one of these has an associated shorthand function, the custom ones will receive one too, e.g. adding 'access' to the custom types will add a logger.access() function /////// MASTER EXCLUSIVE customStreams: [], // File streams, by default there are streams for error and default @@ -29,4 +29,11 @@ The child processes are expected to be attached with the attach() method found i fileRotationFreq: 1, // How frequently to roate files in days - will not work with anything less than 1 day currently directory: './logs', // Directory in which to write log files } -``` \ No newline at end of file +``` + +**Log levels** +0 - Debug +1 - Info +2 - Status +3 - Warning +4 - Error \ No newline at end of file diff --git a/src/Defaults.js b/src/Defaults.js index 050c461..b15615f 100644 --- a/src/Defaults.js +++ b/src/Defaults.js @@ -30,12 +30,26 @@ module.exports = { customStreams: [], customTypeMapping: {}, customColors: {}, - debug: false, - guard: '_logger' + guard: '_logger', + logLevel: 1, + logLevelMapping: { + debug: 0, + info: 1, + status: 2, + warn: 3, + error: 4 + } }, ClientOptions: { - debug: true, guard: '_logger', - customStreams: [] + customStreams: [], + logLevel: 1, + logLevelMapping: { + debug: 0, + info: 1, + status: 2, + warn: 3, + error: 4 + } } }; \ No newline at end of file diff --git a/src/LoggerClient.js b/src/LoggerClient.js index 4bcff0e..e40d1f2 100644 --- a/src/LoggerClient.js +++ b/src/LoggerClient.js @@ -4,6 +4,10 @@ class LoggerClient { static MaxChars = 0; + #_guard = null; + #_logLevel = null; + #_logLevelMapping = null; + constructor (opts = Defaults.ClientOptions) { this.name = opts.name || opts.constructor.name; @@ -22,14 +26,28 @@ class LoggerClient { }); } - this.guard = opts.guard || Defaults.ClientOptions.guard; - this._debug = opts.debug || Defaults.ClientOptions.debug; + this.#_guard = opts.guard || Defaults.ClientOptions.guard; + this.#_logLevel = opts.logLevel || Defaults.ClientOptions.logLevel; + this.#_logLevelMapping = { ...Defaults.ClientOptions.logLevelMapping, ...opts.logLevelMapping }; } + get logLevel () { + return this.#_logLevel; + } + + setLogLevel (level = 'info') { + if (typeof level === 'number') + this.#_logLevel = level; + else if (typeof level === 'string') + this.#_logLevel = this.#_logLevelMapping[level.toLowerCase()]; + else + throw new Error(`Invalid log level type, expected string or number, got ${typeof level}`); + } + transport (message, opts) { - - if (opts.type === 'debug' && !this._debug) + + if (this.#_logLevelMapping[opts.type] < this.#_logLevel) return; if (typeof message !== 'string') @@ -42,7 +60,7 @@ class LoggerClient { // eslint-disable-next-line no-console console.log(`${header} ${message}`); else - process.send({ [this.guard]: true, header, message, ...opts }); + process.send({ [this.#_guard]: true, header, message, ...opts }); } diff --git a/src/MasterLogger.js b/src/MasterLogger.js index d46693f..808d922 100644 --- a/src/MasterLogger.js +++ b/src/MasterLogger.js @@ -10,36 +10,27 @@ const Defaults = require('./Defaults'); const DAY = 1000 * 60 * 60 * 24; -const DefaultOpts = { - fileRotationFreq: 1, - directory: './logs', - customTypes: [], - customStreams: [], - customTypeMapping: {}, - customColors: {}, - debug: false, - guard: '_logger' -}; - // TODO: // - Discord webhook, need to write a separate package for that, don't want to add the entirety of d.js as a dep just for a webhook class MasterLogger { - constructor ({ - directory = './logs', - customTypes = [], - customStreams = [], - customTypeMapping = {}, - customColors = {}, - debug = false, - guard = '_logger', - fileRotationFreq = 1 - } = DefaultOpts) { + #_guard = null; + #_logLevel = null; + #_logLevelMapping = null; + + constructor (config = Defaults.MasterOptions) { + const { + directory, customTypes, customStreams, customTypeMapping, + customColors, guard, fileRotationFreq, logLevel, logLevelMapping + } = { ...Defaults.MasterOptions, ...config }; + this.directory = path.resolve(directory); if (!fs.existsSync(this.directory)) fs.mkdirSync(this.directory, { recursive: true }); - this._debug = debug; + this.#_logLevel = logLevel; + this.#_logLevelMapping = { ...Defaults.MasterOptions.logLevelMapping, ...logLevelMapping }; + this.#_guard = guard; this.types = [ ...customTypes, ...Defaults.Types ]; for (const type of this.types) { @@ -61,13 +52,11 @@ class MasterLogger { this.startDay = Math.floor(Date.now() / this.rotationFreq) * this.rotationFreq; this.rotateTO = setTimeout(this.rotateLogFiles.bind(this), this.startDay + this.rotationFreq - Date.now()); - this.guard = guard; - } attach (shard) { shard.on('message', (msg) => { - if (!msg[this.guard]) + if (!msg[this.#_guard]) return; const { message, type, header, broadcast } = msg; this[type](message, { subheader: header, shard, broadcast }); @@ -88,7 +77,8 @@ class MasterLogger { const maxChars = Math.max(...this.types.map(t => t.length)); const spacer = ' '.repeat(maxChars - type.length); - if (type === 'debug' && this._debug || type !== 'debug') + // if (type === 'debug' && this._debug || type !== 'debug') + if (this.#_logLevelMapping[type] >= this.#_logLevel) console.log(`${chalk[colour](type)}${spacer} ${chalk[colour](header)}: ${chalk.bold(subheader)}${text}`); // eslint-disable-line no-console if (broadcast) { diff --git a/test/otherProcess.js b/test/otherProcess.js index a79f38c..b47504c 100644 --- a/test/otherProcess.js +++ b/test/otherProcess.js @@ -1,17 +1,17 @@ const { LoggerClient } = require('../'); const logger = new LoggerClient({ - debug: true, customTypes: [ 'access' ], customStreams: [ 'access' ], customTypeMapping: { access: 'access', warn: 'error' }, - customColors: { access: 'green' } + customColors: { access: 'green' }, + logLevelMapping: { access: 2 } }); const main = async () => { - for (let i = 0; i < 10000; i++) { - if (i % 500 === 0) - await new Promise(resolve => setTimeout(resolve, 1000)); + for (let i = 0; i < 5; i++) { + // if (i % 500 === 0) + await new Promise(resolve => setTimeout(resolve, 1000)); logger.info('Info test'); logger.status('Status test'); logger.debug('Debug test'); diff --git a/test/test.js b/test/test.js index 2a9e529..bc57d33 100644 --- a/test/test.js +++ b/test/test.js @@ -16,7 +16,8 @@ const main = async () => { customStreams: [ 'access' ], customTypeMapping: { access: 'access', warn: 'error' }, customColors: { access: 'green' }, - fileRotationFreq: 0.0001 + fileRotationFreq: 0.0001, + logLevelMapping: { access: 2 } }); const child = ChildProcess.fork('./test/otherProcess.js'); logger.attach(child);