'use strict'; 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 * * @interface ILogger */ /** * Receives any number of cologne log objects and logs them. * * @memberof ILogger * @function * @name log */ /** * Main interface for Cologne Formatters * * @interface IFormatter */ /** * Receives a cologne log object and returns a formatted string. * * @memberof IFormatter * @function * @name format * @param {tCologneLog} logObject the log to be formatted * @returns {string} the formatted log */ /** * The main cologne log format. * * @typedef {object} tCologneLog * @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. * @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. */ /** * The main logger class. It can be instantiated with loggers in order to * send messages to different destinations. * * @class Cologne */ const 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 ILogger[] * @default [] */ this.loggers = []; Object.assign(this, config); } /** * Adds a logger to the current instance. * * @function addLogger * @instance * @memberof Cologne * @param {ILogger} logger the logger to add */ addLogger(logger) { this.loggers.push(logger); } /** * Removes a logger from the current instance. * * @function removeLogger * @instance * @memberof Cologne * @param {ILogger} logger the logger to remove * @return {ILogger[]} the removed log, inside an array. */ removeLogger(logger) { const index = this.loggers.indexOf(logger); if (index >= 0) { this.loggers.splice(index, 1); } } /** * 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 {*} message The message to log * @param {number} [level=6] The level of the message to log * @return {tCologneLog} a cologne log object */ buildLog(rawMessage, level) { if (typeof rawMessage === 'undefined' || rawMessage === null || !rawMessage._cologneLog) { const message = typeof rawMessage === 'object' ? Utilities.stringify(rawMessage) : rawMessage; const logObject = { message: String(message), _cologneLog: internals.kLogVersion, _from: this.from, _level: level || 6, _timestamp: Utilities.now() }; logObject._levelString = internals.kLevelStrings[logObject._level]; if (typeof rawMessage === 'object') { Object.assign(logObject, rawMessage); } return logObject; } rawMessage._level = level || rawMessage._level; rawMessage._levelString = internals.kLevelStrings[rawMessage._level]; return rawMessage; } /** * 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 */ log(...logs) { this._log(null, ...logs); } /** * Logs with debug level * * @function debug * @instance * @memberof Cologne */ debug(...logs) { this._log(7, ...logs); } /** * Logs with info level * * @function info * @instance * @memberof Cologne */ info(...logs) { this._log(6, ...logs); } /** * Logs with notice level * * @function notice * @instance * @memberof Cologne */ notice(...logs) { this._log(5, ...logs); } /** * Logs with warn level * * @function warn * @instance * @memberof Cologne */ warn(...logs) { this._log(4, ...logs); } /** * Logs with error level * * @function error * @instance * @memberof Cologne */ error(...logs) { this._log(3, ...logs); } // Private method that builds all the logs and sends them to the loggers. _log(level, ...logs) { const structuredLogs = logs.map((log) => this.buildLog(log, level)); for (const logger of this.loggers) { logger.log(...structuredLogs); } } }; /** * Namespace that includes the built-in formatters. * * @namespace Formatters */ const Formatters = {}; Formatters.Simple = require('./formatters/simple'); Formatters.Token = require('./formatters/token'); /** * Namespace that includes the built-in loggers. * * @namespace Loggers */ const Loggers = {}; Loggers.Console = require('./loggers/console'); Loggers.File = require('./loggers/file'); module.exports = { Cologne, Formatters, Loggers, Utilities };