'use strict';
-let LogUtilities = require('./cologne/log_utilities');
+const Utilities = require('./utilities');
+
+const internals = {
+
+ // Maps log levels to their syslog labels
+
+ kLevelStrings: [
+ 'emerg',
+ 'alert',
+ 'crit',
+ 'error',
+ 'warning',
+ 'notice',
+ 'info',
+ 'debug'
+ ],
+
+ // Version of the Cologne Log Format used
+
+ kLogVersion: '2.0.0'
+};
/** TYPE DEFINITIONS **/
/**
* Main interface for Cologne Loggers
*
- * @memberof Cologne
* @interface ILogger
*/
/**
* Receives any number of cologne log objects and logs them.
*
- * @memberof Cologne.ILogger
+ * @memberof 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
+ * @memberof IFormatter
* @function
* @name format
- * @param {Cologne.tCologneLog} logObject the log to be formatted
+ * @param {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 {Bigint} _timestamp the timestamp in nanoseconds
* @property {String} _cologneLog main identifier, encodes the version of the
* cologne log format being used.
* @property {String} _from the origin of the log message.
*/
/**
- * 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}}'
- * })
- * })
- * ]
- * });
- * ```
+ * The main logger class. It can be instantiated with loggers in order to
+ * send messages to different destinations.
*
* @class Cologne
*/
-let Cologne = class Cologne {
+const Cologne = class Cologne {
- constructor (config) {
+ constructor(config) {
/**
* The name of this logger, useful to distinguish between different
* @name loggers
* @instance
* @memberof Cologne
- * @type Cologne.ILogger[]
+ * @type ILogger[]
* @default []
*/
this.loggers = [];
- Object.assign(this, config || {});
+ Object.assign(this, config);
}
/**
* @function addLogger
* @instance
* @memberof Cologne
- * @param {Cologne.ILogger} logger the logger to add
- * @return {undefined}
+ * @param {ILogger} logger the logger to add
*/
- addLogger (logger) {
+ addLogger(logger) {
+
this.loggers.push(logger);
}
* @function removeLogger
* @instance
* @memberof Cologne
- * @param {Cologne.ILogger} logger the logger to remove
- * @return {Cologne.ILogger[]} the removed log, inside an array.
+ * @param {ILogger} logger the logger to remove
+ * @return {ILogger[]} the removed log, inside an array.
*/
- removeLogger (logger) {
- let index;
+ removeLogger(logger) {
- index = this.loggers.indexOf(logger);
+ const 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.
+ * Given a message, it builds a cologne log object without logging it.
+ * If you send a cologne log object, it will only update the level.
+ *
+ * If the message is an object, the log object will be extended with
+ * its properties.
*
* @function buildLog
* @instance
* @memberof Cologne
- * @param {*} item The item to log
- * @return {Cologne.tCologneLog} a cologne log object
+ * @param {*} message The message to log
+ * @param {number} [level=6] The level of the message to log
+ * @return {tCologneLog} a cologne log object
*/
- buildLog (item, level, meta) {
- let logObject;
+ buildLog(rawMessage, level) {
+
+ if (typeof rawMessage === 'undefined' || rawMessage === null || !rawMessage._cologneLog) {
- logObject = {};
+ const message = typeof rawMessage === 'object' ? Utilities.stringify(rawMessage) : rawMessage;
- 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();
+ const logObject = {
+ message: String(message),
+ _cologneLog: internals.kLogVersion,
+ _from: this.from,
+ _level: level || 6,
+ _timestamp: Utilities.now()
+ };
- if (meta && typeof meta === 'object') {
- Object.assign(logObject, meta);
+ logObject._levelString = internals.kLevelStrings[logObject._level];
+
+ if (typeof rawMessage === 'object') {
+ Object.assign(logObject, rawMessage);
}
return logObject;
}
- if (item._cologneLog) {
- item._level = level || item._level || 6;
- item._levelString = this._levelString(item._level);
- }
+ rawMessage._level = level || rawMessage._level;
+ rawMessage._levelString = internals.kLevelStrings[rawMessage._level];
- return item;
+ return rawMessage;
}
/**
* @function log
* @instance
* @memberof Cologne
- * @return {undefined}
*/
- log () {
- this._log.apply(this, [null].concat(Array.prototype.slice.call(arguments)));
+ log(...logs) {
+
+ this._log(null, ...logs);
}
/**
* @function debug
* @instance
* @memberof Cologne
- * @return {undefined}
*/
- debug () {
- this._log.apply(this, [7].concat(Array.prototype.slice.call(arguments)));
+ debug(...logs) {
+
+ this._log(7, ...logs);
}
/**
* @function info
* @instance
* @memberof Cologne
- * @return {undefined}
*/
- info () {
- this._log.apply(this, [6].concat(Array.prototype.slice.call(arguments)));
+ info(...logs) {
+
+ this._log(6, ...logs);
}
/**
* @function notice
* @instance
* @memberof Cologne
- * @return {undefined}
*/
- notice () {
- this._log.apply(this, [5].concat(Array.prototype.slice.call(arguments)));
+ notice(...logs) {
+
+ this._log(5, ...logs);
}
/**
* @function warn
* @instance
* @memberof Cologne
- * @return {undefined}
*/
- warn () {
- this._log.apply(this, [4].concat(Array.prototype.slice.call(arguments)));
+ warn(...logs) {
+
+ this._log(4, ...logs);
}
/**
* @function error
* @instance
* @memberof Cologne
- * @return {undefined}
*/
- error () {
- this._log.apply(this, [3].concat(Array.prototype.slice.call(arguments)));
+ error(...logs) {
+
+ this._log(3, ...logs);
}
// 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));
- }
+ _log(level, ...logs) {
- for (logger of this.loggers) {
- logger.log.apply(logger, logObjectArray);
- }
- }
+ const structuredLogs = logs.map((log) => this.buildLog(log, level));
- // 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';
+ for (const logger of this.loggers) {
+ logger.log(...structuredLogs);
}
}
};
-// Version of the Cologne Log Format used.
-Cologne._version = '1.0.0';
-
/**
* Namespace that includes the built-in formatters.
*
- * @namespace Formatter
- * @memberof Cologne
+ * @namespace Formatters
*/
-Cologne.Formatter = {};
-Cologne.Formatter.Simple = require('./cologne/formatter/simple');
-Cologne.Formatter.Token = require('./cologne/formatter/token');
+const Formatters = {};
+Formatters.Simple = require('./formatters/simple');
+Formatters.Token = require('./formatters/token');
/**
* Namespace that includes the built-in loggers.
*
- * @namespace Logger
- * @memberof Cologne
+ * @namespace Loggers
*/
-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;
+const Loggers = {};
+Loggers.Console = require('./loggers/console');
+Loggers.File = require('./loggers/file');
+
+module.exports = {
+ Cologne,
+ Formatters,
+ Loggers,
+ Utilities
+};