@freemework/common
Version:
Common library of the Freemework Project.
300 lines • 13.3 kB
JavaScript
;
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