]> git.r.bdr.sh - rbdr/cologne/blobdiff - lib/cologne.js
Merge branch 'rbdr-address-sonarqube-issues' into 'master'
[rbdr/cologne] / lib / cologne.js
index 646fe79fc368f1515ee1a05256ad9246b5730dfb..392b452210ccd3fc07fdb732e9eac21e9d9591ba 100644 (file)
@@ -1,49 +1,64 @@
 '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.
@@ -54,32 +69,14 @@ let LogUtilities = require('./cologne/log_utilities');
  */
 
 /**
- * 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
@@ -99,12 +96,12 @@ let Cologne = class Cologne {
      * @name loggers
      * @instance
      * @memberof Cologne
-     * @type Cologne.ILogger[]
+     * @type ILogger[]
      * @default []
      */
     this.loggers = [];
 
-    Object.assign(this, config || {});
+    Object.assign(this, config);
   }
 
   /**
@@ -113,10 +110,10 @@ let Cologne = class Cologne {
    * @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);
   }
 
@@ -126,55 +123,58 @@ let Cologne = class Cologne {
    * @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;
   }
 
   /**
@@ -184,10 +184,10 @@ let Cologne = class Cologne {
    * @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);
   }
 
   /**
@@ -196,10 +196,10 @@ let Cologne = class Cologne {
    * @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);
   }
 
   /**
@@ -208,10 +208,10 @@ let Cologne = class Cologne {
    * @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);
   }
 
   /**
@@ -220,10 +220,10 @@ let Cologne = class Cologne {
    * @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);
   }
 
   /**
@@ -232,10 +232,10 @@ let Cologne = class Cologne {
    * @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);
   }
 
   /**
@@ -244,85 +244,45 @@ let Cologne = class Cologne {
    * @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
+};