'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;