UNPKG

@freemework/common

Version:

Common library of the Freemework Project.

300 lines 13.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FLoggerConsole = exports.FLoggerBaseWithLevel = exports.FLoggerBase = exports.FLogger = void 0; const f_exception_invalid_operation_js_1 = require("../exception/f_exception_invalid_operation.js"); const f_logger_level_js_1 = require("./f_logger_level.js"); const f_execution_context_js_1 = require("../execution_context/f_execution_context.js"); const f_logger_labels_execution_context_js_1 = require("./f_logger_labels_execution_context.js"); class FLogger { static _loggerFactory = null; static get loggerFactory() { if (this._loggerFactory === null) { console.error("Logging subsystem used before call FLogger.setLoggerFactory(). Use FLoggerConsole as default logger. Please, consider to call FLogger.setLoggerFactory() at bootstrap phase."); this._loggerFactory = (loggerName) => FLoggerConsole.create(loggerName, { level: f_logger_level_js_1.FLoggerLevel.TRACE }); } return this._loggerFactory; } static setLoggerFactory(factory) { if (FLogger._loggerFactory !== null) { throw new f_exception_invalid_operation_js_1.FExceptionInvalidOperation("Cannot redefine logger factory by call setLoggerFactory(). Logger factory already set."); } FLogger._loggerFactory = factory; } /** * Factory constructor */ static create(loggerName) { return FLogger.loggerFactory(loggerName); } } exports.FLogger = FLogger; class FLoggerBase extends FLogger { get isTraceEnabled() { return this.isLevelEnabled(f_logger_level_js_1.FLoggerLevel.TRACE); } get isDebugEnabled() { return this.isLevelEnabled(f_logger_level_js_1.FLoggerLevel.DEBUG); } get isInfoEnabled() { return this.isLevelEnabled(f_logger_level_js_1.FLoggerLevel.INFO); } get isWarnEnabled() { return this.isLevelEnabled(f_logger_level_js_1.FLoggerLevel.WARN); } get isErrorEnabled() { return this.isLevelEnabled(f_logger_level_js_1.FLoggerLevel.ERROR); } get isFatalEnabled() { return this.isLevelEnabled(f_logger_level_js_1.FLoggerLevel.FATAL); } get name() { return this._name; } trace(variant, messageOrMessageFactory, ex) { if (!this.isTraceEnabled) { return; } const loggerLabels = FLoggerBase._resolveLoggerLabels(variant); const message = FLoggerBase._resolveMessage(messageOrMessageFactory); this.writeToOutput(f_logger_level_js_1.FLoggerLevel.TRACE, loggerLabels, message, ex); } debug(variant, messageOrMessageFactory, ex) { if (!this.isDebugEnabled) { return; } const loggerLabels = FLoggerBase._resolveLoggerLabels(variant); const message = FLoggerBase._resolveMessage(messageOrMessageFactory); this.writeToOutput(f_logger_level_js_1.FLoggerLevel.DEBUG, loggerLabels, message, ex); } info(variant, messageOrMessageFactory) { if (!this.isInfoEnabled) { return; } const loggerLabels = FLoggerBase._resolveLoggerLabels(variant); const message = FLoggerBase._resolveMessage(messageOrMessageFactory); this.writeToOutput(f_logger_level_js_1.FLoggerLevel.INFO, loggerLabels, message); } warn(variant, messageOrMessageFactory) { if (!this.isWarnEnabled) { return; } const loggerLabels = FLoggerBase._resolveLoggerLabels(variant); const message = FLoggerBase._resolveMessage(messageOrMessageFactory); this.writeToOutput(f_logger_level_js_1.FLoggerLevel.WARN, loggerLabels, message); } error(variant, messageOrMessageFactory) { if (!this.isErrorEnabled) { return; } const loggerLabels = FLoggerBase._resolveLoggerLabels(variant); const message = FLoggerBase._resolveMessage(messageOrMessageFactory); this.writeToOutput(f_logger_level_js_1.FLoggerLevel.ERROR, loggerLabels, message); } fatal(variant, messageOrMessageFactory) { if (!this.isFatalEnabled) { return; } const loggerLabels = FLoggerBase._resolveLoggerLabels(variant); const message = FLoggerBase._resolveMessage(messageOrMessageFactory); this.writeToOutput(f_logger_level_js_1.FLoggerLevel.FATAL, loggerLabels, message); } log(executionContextOrLabels, level, messageOrMessageFactory, ex) { if (!this.isLevelEnabled(level)) { return; } const loggerLabels = FLoggerBase._resolveLoggerLabels(executionContextOrLabels); const message = FLoggerBase._resolveMessage(messageOrMessageFactory); this.writeToOutput(level, loggerLabels, message, ex); } constructor(loggerName) { super(); this._name = loggerName; } _name; static _resolveLoggerLabels(variant) { if (variant === null || variant === undefined) { // Sometime users pass undefined/null value. // It is contract violation, but not a reason to crash in logger return FLoggerBase._emptyLabelValues; } else if (variant instanceof f_execution_context_js_1.FExecutionContext) { const executionElement = f_logger_labels_execution_context_js_1.FLoggerLabelsExecutionContext .of(variant); if (executionElement !== null) { return executionElement.loggerLabelValues; } else { return FLoggerBase._emptyLabelValues; // No any logger properties on execution context chain } } else { return variant; } } static _resolveMessage(messageOrMessageFactory) { if (typeof messageOrMessageFactory === "function") { try { messageOrMessageFactory = messageOrMessageFactory(); if (typeof messageOrMessageFactory !== "string") { messageOrMessageFactory = `FLoggerMessageFactory contract violation detected: Non-string result. Force stringify message: ${messageOrMessageFactory}`; } } catch (e) { messageOrMessageFactory = "FLoggerMessageFactory contract violation detected: Exception was raised."; } } else { if (typeof messageOrMessageFactory !== "string") { messageOrMessageFactory = `FLogger contract violation detected: Non-string message passed. Force stringify message: ${messageOrMessageFactory}`; } } return messageOrMessageFactory; } static _emptyLabelValues = Object.freeze([]); } exports.FLoggerBase = FLoggerBase; class FLoggerBaseWithLevel extends FLoggerBase { static buildLoggerLevelsMap(level) { const levels = new Map(); levels.set(f_logger_level_js_1.FLoggerLevel.FATAL, level != null && level >= f_logger_level_js_1.FLoggerLevel.FATAL); levels.set(f_logger_level_js_1.FLoggerLevel.ERROR, level != null && level >= f_logger_level_js_1.FLoggerLevel.ERROR); levels.set(f_logger_level_js_1.FLoggerLevel.WARN, level != null && level >= f_logger_level_js_1.FLoggerLevel.WARN); levels.set(f_logger_level_js_1.FLoggerLevel.INFO, level != null && level >= f_logger_level_js_1.FLoggerLevel.INFO); levels.set(f_logger_level_js_1.FLoggerLevel.DEBUG, level != null && level >= f_logger_level_js_1.FLoggerLevel.DEBUG); levels.set(f_logger_level_js_1.FLoggerLevel.TRACE, level != null && level >= f_logger_level_js_1.FLoggerLevel.TRACE); return levels; } constructor(loggerName, level) { super(loggerName); // eslint-disable-next-line func-names const specificLogLevel = (function () { const logLevelEnvironmentKey = `LOG_LEVEL_${loggerName}`; if (logLevelEnvironmentKey in process.env) { const specificLogLevelStr = process.env[logLevelEnvironmentKey]; if (specificLogLevelStr !== undefined) { try { return f_logger_level_js_1.FLoggerLevel.parse(specificLogLevelStr.toUpperCase()); } catch (e) { console.error(`Unable to parse a value of environment variable '${logLevelEnvironmentKey}'.`); } } } return null; })(); this.levels = FLoggerBaseWithLevel.buildLoggerLevelsMap(specificLogLevel !== null ? specificLogLevel : level); } isLevelEnabled(level) { const isEnabled = this.levels.get(level); return isEnabled === true; } levels; } exports.FLoggerBaseWithLevel = FLoggerBaseWithLevel; class FLoggerConsole extends FLoggerBaseWithLevel { /** * Factory constructor */ static create(loggerName, opts) { const level = opts !== undefined && opts.level !== undefined ? opts.level : f_logger_level_js_1.FLoggerLevel.TRACE; const format = opts !== undefined && opts.format !== undefined ? opts.format : "text"; const output = opts !== undefined && opts.output !== undefined ? opts.output : null; if (format === "json") { return new FLoggerConsoleJsonImpl(loggerName, level, output); } else { return new FLoggerConsoleTextImpl(loggerName, level, output); } } } exports.FLoggerConsole = FLoggerConsole; class FLoggerConsoleTextImpl extends FLoggerConsole { output; constructor(loggerName, level, output) { super(loggerName, level); this.output = output; } writeToOutput(level, labelValues, message, ex) { let logMessageBuffer = `${new Date().toISOString()} ${this.name} [${level}]`; for (const { name, value } of labelValues) { logMessageBuffer += `(${name}:${value})`; } logMessageBuffer += (" "); logMessageBuffer += message; logMessageBuffer += "\n"; if (ex != undefined) { logMessageBuffer += ex.toString(); logMessageBuffer += "\n"; } if (this.output === null) { switch (level) { case f_logger_level_js_1.FLoggerLevel.TRACE: case f_logger_level_js_1.FLoggerLevel.DEBUG: console.debug(logMessageBuffer); break; case f_logger_level_js_1.FLoggerLevel.INFO: console.log(logMessageBuffer); break; case f_logger_level_js_1.FLoggerLevel.WARN: case f_logger_level_js_1.FLoggerLevel.ERROR: case f_logger_level_js_1.FLoggerLevel.FATAL: console.error(logMessageBuffer); break; default: throw new f_exception_invalid_operation_js_1.FExceptionInvalidOperation(`Unsupported log level '${level}'.`); } } else if (this.output === "stdout") { console.log(logMessageBuffer); } else if (this.output === "stderr") { console.error(logMessageBuffer); } } } class FLoggerConsoleJsonImpl extends FLoggerBaseWithLevel { static formatLogMessage(loggerName, level, labelValues, message, ex) { const logEntryBase = { name: loggerName, date: new Date().toISOString(), level: level.toString(), }; const labelsObj = {}; for (const { name, value } of labelValues) { labelsObj[`label.${name}`] = value; } const logEntry = { ...logEntryBase, ...labelsObj, message, }; if (ex !== undefined && ex != null) { logEntry["exception.name"] = ex.name; logEntry["exception.message"] = ex.message; if (ex.stack !== undefined) { logEntry["exception.stack"] = ex.stack; } } const logMessage = JSON.stringify(logEntry); return logMessage; } output; constructor(loggerName, level, output) { super(loggerName, level); this.output = output; } writeToOutput(level, labelValues, message, ex) { const logMessage = FLoggerConsoleJsonImpl.formatLogMessage(this.name, level, labelValues, message, ex); if (this.output === null) { switch (level) { case f_logger_level_js_1.FLoggerLevel.TRACE: case f_logger_level_js_1.FLoggerLevel.DEBUG: console.debug(logMessage); break; case f_logger_level_js_1.FLoggerLevel.INFO: console.log(logMessage); break; case f_logger_level_js_1.FLoggerLevel.WARN: case f_logger_level_js_1.FLoggerLevel.ERROR: case f_logger_level_js_1.FLoggerLevel.FATAL: console.error(logMessage); break; } } else if (this.output === "stdout") { console.log(logMessage); } else if (this.output === "stderr") { console.error(logMessage); } } } //# sourceMappingURL=f_logger.js.map