diff options
Diffstat (limited to 'lib/cologne.js')
| -rw-r--r-- | lib/cologne.js | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/lib/cologne.js b/lib/cologne.js new file mode 100644 index 0000000..646fe79 --- /dev/null +++ b/lib/cologne.js @@ -0,0 +1,328 @@ +'use strict'; + +let LogUtilities = require('./cologne/log_utilities'); + +/** TYPE DEFINITIONS **/ + +/** + * Main interface for Cologne Loggers + * + * @memberof Cologne + * @interface ILogger + */ + +/** + * Receives any number of cologne log objects and logs them. + * + * @memberof Cologne.ILogger + * @function + * @name log + * @returns {undefined} + */ + +/** + * Main interface for Cologne Formatters + * + * @memberof Cologne + * @interface IFormatter + */ + +/** + * Receives a cologne log object and returns a formatted string. + * + * @memberof Cologne.IFormatter + * @function + * @name format + * @param {Cologne.tCologneLog} logObject the log to be formatted + * @returns {string} the formatted log + */ + +/** + * The main cologne log format. + * + * @memberof Cologne + * @typedef {object} tCologneLog + * @property {Number} _timestamp the timestamp in miliseconds with decimal + * numbers representing fractions of miliseconds + * @property {String} _cologneLog main identifier, encodes the version of the + * cologne log format being used. + * @property {String} _from the origin of the log message. + * @property {String} _level the severity level of the log, uses syslog + * priorities. + * @property {String} _levelString the severity level keyword of the log, + * uses syslog priority keywords. + */ + +/** + * Cologne is a logger multiplexer that works mainly with a JSON format. It + * can be instantiated with several loggers, or they can be changed after + * the fact. + * + * ## Usage + * + * ``` + * require('cologne'); + * + * let co = new Cologne({ + * from: "Special Worker Logger", + * loggers: [ + * new Cologne.Logger.Console({ + * formatter: new Cologne.Formatter.Token({ + * formatString: '[{{_timestamp}}]{{_from}}: {{message}}' + * }) + * }) + * ] + * }); + * ``` + * + * @class Cologne + */ +let Cologne = class Cologne { + + constructor (config) { + + /** + * The name of this logger, useful to distinguish between different + * loggers. + * + * @name from + * @instance + * @memberof Cologne + * @type String + * @default 'Generic Cologne Logger + */ + this.from = 'Generic Cologne Logger'; + + /** + * The array containing all the loggers it will call to. + * + * @name loggers + * @instance + * @memberof Cologne + * @type Cologne.ILogger[] + * @default [] + */ + this.loggers = []; + + Object.assign(this, config || {}); + } + + /** + * Adds a logger to the current instance. + * + * @function addLogger + * @instance + * @memberof Cologne + * @param {Cologne.ILogger} logger the logger to add + * @return {undefined} + */ + addLogger (logger) { + this.loggers.push(logger); + } + + /** + * Removes a logger from the current instance. + * + * @function removeLogger + * @instance + * @memberof Cologne + * @param {Cologne.ILogger} logger the logger to remove + * @return {Cologne.ILogger[]} the removed log, inside an array. + */ + removeLogger (logger) { + let index; + + index = this.loggers.indexOf(logger); + if (index >= 0) { + this.loggers.splice(index, 1); + } + } + + /** + * Given an item, it builds a cologne log object. this is done + * automatically by the logger, though this is useful if you need + * to attach metadata before logging. + * + * @function buildLog + * @instance + * @memberof Cologne + * @param {*} item The item to log + * @return {Cologne.tCologneLog} a cologne log object + */ + buildLog (item, level, meta) { + let logObject; + + logObject = {}; + + if (typeof item === 'undefined' || item === null || !item._cologneLog) { + logObject.message = item; + logObject._cologneLog = this.constructor._version; + logObject._from = this.from; + logObject._level = level || 6; + logObject._levelString = this._levelString(logObject._level); + logObject._timestamp = LogUtilities.now(); + + if (meta && typeof meta === 'object') { + Object.assign(logObject, meta); + } + + return logObject; + } + + if (item._cologneLog) { + item._level = level || item._level || 6; + item._levelString = this._levelString(item._level); + } + + return item; + } + + /** + * Default log function. Sends arguments to loggers. If not specified in log + * object, it will set the severity to 6 - INFO. + * + * @function log + * @instance + * @memberof Cologne + * @return {undefined} + */ + log () { + this._log.apply(this, [null].concat(Array.prototype.slice.call(arguments))); + } + + /** + * Logs with debug level + * + * @function debug + * @instance + * @memberof Cologne + * @return {undefined} + */ + debug () { + this._log.apply(this, [7].concat(Array.prototype.slice.call(arguments))); + } + + /** + * Logs with info level + * + * @function info + * @instance + * @memberof Cologne + * @return {undefined} + */ + info () { + this._log.apply(this, [6].concat(Array.prototype.slice.call(arguments))); + } + + /** + * Logs with notice level + * + * @function notice + * @instance + * @memberof Cologne + * @return {undefined} + */ + notice () { + this._log.apply(this, [5].concat(Array.prototype.slice.call(arguments))); + } + + /** + * Logs with warn level + * + * @function warn + * @instance + * @memberof Cologne + * @return {undefined} + */ + warn () { + this._log.apply(this, [4].concat(Array.prototype.slice.call(arguments))); + } + + /** + * Logs with error level + * + * @function error + * @instance + * @memberof Cologne + * @return {undefined} + */ + error () { + this._log.apply(this, [3].concat(Array.prototype.slice.call(arguments))); + } + + // Private method that builds all the logs and sends them to the loggers. + _log (severity) { + let remainingArguments, logObjectArray, log, logger; + + remainingArguments = Array.prototype.slice.call(arguments, 1); + logObjectArray = []; + + for (log of remainingArguments) { + if (typeof log === 'undefined') { + logObjectArray.push(this.buildLog('undefined', severity)); + continue; + } + + if (log === null) { + logObjectArray.push(this.buildLog('null', severity)); + continue; + } + + logObjectArray.push(this.buildLog(log, severity)); + } + + for (logger of this.loggers) { + logger.log.apply(logger, logObjectArray); + } + } + + // Private utility method that will return the string for any given + // numerical severity level + _levelString (level) { + switch(level) { + case 0: + return 'emerg'; + case 1: + return 'alert'; + case 2: + return 'crit'; + case 3: + return 'error'; + case 4: + return 'warning'; + case 5: + return 'notice'; + case 6: + return 'info'; + case 7: + return 'debug'; + } + } +}; + +// Version of the Cologne Log Format used. +Cologne._version = '1.0.0'; + +/** + * Namespace that includes the built-in formatters. + * + * @namespace Formatter + * @memberof Cologne + */ +Cologne.Formatter = {}; +Cologne.Formatter.Simple = require('./cologne/formatter/simple'); +Cologne.Formatter.Token = require('./cologne/formatter/token'); + +/** + * Namespace that includes the built-in loggers. + * + * @namespace Logger + * @memberof Cologne + */ +Cologne.Logger = {}; +Cologne.Logger.Console = require('./cologne/logger/console'); +Cologne.Logger.File = require('./cologne/logger/file'); + +Cologne.LogUtilities = require('./cologne/log_utilities'); + +module.exports = Cologne; |