2020-12-04 18:10:33 +00:00
|
|
|
import * as Logger from "js-logger";
|
2021-05-21 17:21:53 +00:00
|
|
|
import { ILogger, ILoggerOpts } from "js-logger";
|
2020-11-06 13:17:47 +00:00
|
|
|
import { SPLITCHAR } from "../helpers/objectMethods";
|
2020-12-04 18:10:33 +00:00
|
|
|
import { RUNNINGINNODE } from "../helpers/runtimeMethods";
|
|
|
|
|
|
|
|
const colors = {
|
|
|
|
Reset: "\x1b[0m",
|
|
|
|
Bright: "\x1b[1m",
|
|
|
|
Dim: "\x1b[2m",
|
|
|
|
Underscore: "\x1b[4m",
|
|
|
|
Blink: "\x1b[5m",
|
|
|
|
Reverse: "\x1b[7m",
|
|
|
|
Hidden: "\x1b[8m",
|
|
|
|
|
|
|
|
FgBlack: "\x1b[30m",
|
|
|
|
FgRed: "\x1b[31m",
|
|
|
|
FgGreen: "\x1b[32m",
|
|
|
|
FgYellow: "\x1b[33m",
|
|
|
|
FgBlue: "\x1b[34m",
|
|
|
|
FgMagenta: "\x1b[35m",
|
|
|
|
FgCyan: "\x1b[36m",
|
|
|
|
FgWhite: "\x1b[37m",
|
|
|
|
|
|
|
|
BgBlack: "\x1b[40m",
|
|
|
|
BgRed: "\x1b[41m",
|
|
|
|
BgGreen: "\x1b[42m",
|
|
|
|
BgYellow: "\x1b[43m",
|
|
|
|
BgBlue: "\x1b[44m",
|
|
|
|
BgMagenta: "\x1b[45m",
|
|
|
|
BgCyan: "\x1b[46m",
|
|
|
|
BgWhite: "\x1b[47m"
|
|
|
|
};
|
|
|
|
|
|
|
|
const colorMatching = {
|
|
|
|
ERROR: colors.FgRed,
|
|
|
|
WARN: colors.FgYellow,
|
|
|
|
INFO: colors.FgWhite,
|
|
|
|
DEBUG: colors.FgGreen,
|
|
|
|
TRACE: colors.FgCyan
|
|
|
|
};
|
|
|
|
|
|
|
|
const spacer = {
|
|
|
|
ERROR: "",
|
|
|
|
WARN: " ",
|
|
|
|
INFO: " ",
|
|
|
|
DEBUG: "",
|
|
|
|
TRACE: ""
|
|
|
|
};
|
|
|
|
|
|
|
|
Logger.useDefaults({
|
|
|
|
defaultLevel: Logger.DEBUG,
|
|
|
|
formatter: RUNNINGINNODE
|
|
|
|
? function (messages, context) {
|
|
|
|
messages.unshift(
|
|
|
|
colors.FgBlue,
|
|
|
|
new Date().toISOString(),
|
|
|
|
colors.Reset,
|
|
|
|
"-",
|
|
|
|
colorMatching[context.level.name],
|
|
|
|
context.level.name + spacer[context.level.name],
|
|
|
|
"-",
|
|
|
|
colors.BgWhite + colors.FgBlack,
|
|
|
|
context.name,
|
|
|
|
colors.Reset,
|
|
|
|
":"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
: function (messages, context) {
|
|
|
|
messages.unshift(
|
|
|
|
context.level.name + spacer[context.level.name],
|
|
|
|
"-",
|
|
|
|
context.name,
|
|
|
|
":"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
2020-11-06 13:17:47 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Contains the Valid Types of the Loger.
|
|
|
|
*/
|
2020-12-04 18:10:33 +00:00
|
|
|
export type LoggerLevel = "error" | "warn" | "info" | "debug" | "trace";
|
|
|
|
export const LoggerLevels = ["error", "warn", "info", "debug", "trace"];
|
|
|
|
|
|
|
|
const order: { [K in LoggerLevel]: number } = {
|
|
|
|
error: 8,
|
|
|
|
warn: 5,
|
|
|
|
info: 3,
|
|
|
|
debug: 2,
|
|
|
|
trace: 1
|
2020-11-23 06:09:31 +00:00
|
|
|
};
|
2020-11-07 10:55:29 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
const mapping: { [K in LoggerLevel]: any } = {
|
|
|
|
error: Logger.ERROR,
|
|
|
|
warn: Logger.WARN,
|
|
|
|
info: Logger.INFO,
|
|
|
|
debug: Logger.DEBUG,
|
|
|
|
trace: Logger.TRACE
|
|
|
|
};
|
2020-11-07 10:55:29 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
const reverseOrder: { [index: number]: LoggerLevel } = {};
|
|
|
|
Object.getOwnPropertyNames(order).map(
|
|
|
|
(key: LoggerLevel) => (reverseOrder[order[key]] = key)
|
|
|
|
);
|
2020-11-07 10:55:29 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
const reverseMapping: any = {};
|
|
|
|
Object.getOwnPropertyNames(mapping).map(
|
|
|
|
(key: LoggerLevel) => (reverseMapping[mapping[key]] = key)
|
|
|
|
);
|
2020-11-06 13:17:47 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
function _selectLevel(master: LoggerLevel, slave: LoggerLevel) {
|
|
|
|
const masterLevel = order[master];
|
|
|
|
const slaveLevel = order[slave];
|
2020-11-06 13:17:47 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
return reverseOrder[Math.max(masterLevel, slaveLevel)];
|
2020-11-06 13:17:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper Function, to create a Logger.
|
2020-12-04 18:10:33 +00:00
|
|
|
* Therefore it uses a specific Level and a Lable of the
|
2020-11-06 13:17:47 +00:00
|
|
|
* Logger
|
|
|
|
*
|
|
|
|
* @export
|
|
|
|
* @param {LoggerLevel} level The Level, which should be rendered
|
|
|
|
* @param {string} [label=''] An Lable for the Logger. Every Message beginns with that lable.
|
|
|
|
* @return {*} Returns a Logger.
|
|
|
|
*/
|
2020-12-04 18:10:33 +00:00
|
|
|
function _getLogger(level: LoggerLevel, label = ""): ILogger {
|
|
|
|
const logger = Logger.get(label);
|
|
|
|
logger.setLevel(mapping[level]);
|
|
|
|
return logger;
|
2020-11-06 13:17:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export class NopeLogger {
|
2020-12-04 18:10:33 +00:00
|
|
|
protected _logger: ILogger;
|
|
|
|
protected _loggers: Map<string, ILogger>;
|
2020-11-06 13:17:47 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
set level(value: LoggerLevel) {
|
|
|
|
if (!this.isLocked) {
|
|
|
|
this._level = value;
|
|
|
|
this.setLoglevel("core" + SPLITCHAR, value);
|
2020-11-06 13:17:47 +00:00
|
|
|
}
|
2020-12-04 18:10:33 +00:00
|
|
|
}
|
2020-11-06 13:17:47 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
get level(): LoggerLevel {
|
|
|
|
return this._level;
|
|
|
|
}
|
|
|
|
|
|
|
|
public _level: LoggerLevel = "debug";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create or returns the provided Logger
|
|
|
|
* @param name
|
|
|
|
* @param level
|
|
|
|
*/
|
|
|
|
getLogger(name = "", level: LoggerLevel = this.level): ILogger {
|
|
|
|
if (!this._loggers.has(name)) {
|
|
|
|
this._loggers.set(
|
|
|
|
name,
|
|
|
|
_getLogger(_selectLevel(this.level, level), name)
|
|
|
|
);
|
2020-11-06 13:17:47 +00:00
|
|
|
}
|
2020-12-04 18:10:33 +00:00
|
|
|
return this._loggers.get(name) as ILogger;
|
|
|
|
}
|
2020-11-06 13:17:47 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
/**
|
2021-05-21 17:21:53 +00:00
|
|
|
* Helper function, to update the Logger Defaults.
|
|
|
|
*
|
|
|
|
* @param {ILoggerOpts} defaults
|
|
|
|
* @memberof NopeLogger
|
2020-12-04 18:10:33 +00:00
|
|
|
*/
|
2021-05-21 17:21:53 +00:00
|
|
|
setDefaults(defaults: ILoggerOpts): void {
|
|
|
|
Logger.useDefaults(defaults);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Rewrites the Stream of the Logger to the
|
|
|
|
* given handler. Watch out, only one handler
|
|
|
|
* is active.
|
|
|
|
*
|
|
|
|
* @param {(msg, context) => void} handler
|
|
|
|
* @memberof NopeLogger
|
|
|
|
*/
|
|
|
|
setHandler(handler: (msg, context) => void): void {
|
|
|
|
Logger.setHandler(handler);
|
2020-12-04 18:10:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function to determine the Logger Level
|
|
|
|
* @param loggerGroup The specified group, which should be addressed
|
|
|
|
* @param level The Level to Set
|
|
|
|
*/
|
|
|
|
setLoglevel(loggerGroup: string, level: LoggerLevel): void {
|
|
|
|
if (!loggerGroup.startsWith("core" + SPLITCHAR)) {
|
|
|
|
loggerGroup = "core" + SPLITCHAR + loggerGroup;
|
2020-11-06 13:17:47 +00:00
|
|
|
}
|
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
if (!loggerGroup.endsWith(SPLITCHAR)) {
|
|
|
|
loggerGroup += SPLITCHAR;
|
2020-11-06 13:17:47 +00:00
|
|
|
}
|
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
/** Iterate over all Loggers and close the unused Loggers */
|
|
|
|
for (let [name, logger] of this._loggers.entries()) {
|
|
|
|
if (!name.startsWith("core" + SPLITCHAR)) {
|
|
|
|
name = "core" + SPLITCHAR + name;
|
|
|
|
}
|
2020-11-06 13:17:47 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
if (!name.endsWith(SPLITCHAR)) {
|
|
|
|
name += SPLITCHAR;
|
|
|
|
}
|
2020-11-06 13:17:47 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
if (name == loggerGroup || name.startsWith(loggerGroup)) {
|
|
|
|
/** Update the Level */
|
|
|
|
logger.setLevel(mapping[level]);
|
|
|
|
}
|
2020-11-06 13:17:47 +00:00
|
|
|
}
|
2020-12-04 18:10:33 +00:00
|
|
|
}
|
2020-11-06 13:17:47 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
/**
|
|
|
|
* Function, to check, whether a specific logger is logging or not
|
|
|
|
* @param loggerName Name of the Logger
|
|
|
|
* @param level The Log-Level to Test
|
|
|
|
*/
|
|
|
|
isLogging(loggerName: string, level: LoggerLevel): boolean {
|
|
|
|
return (
|
|
|
|
order[reverseMapping[this.getLogger(loggerName).getLevel().name]] >=
|
|
|
|
order[level]
|
|
|
|
);
|
|
|
|
}
|
2020-11-07 10:55:29 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
/**
|
|
|
|
* Creates A Logger-Manager
|
|
|
|
*/
|
|
|
|
constructor() {
|
|
|
|
this._loggers = new Map<string, ILogger>();
|
2020-11-07 10:55:29 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
this._logger = _getLogger("debug", "root");
|
|
|
|
this._loggers.set("", this._logger);
|
|
|
|
}
|
2020-11-06 13:17:47 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
protected _pw = "";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Lock the Logger Level with a password
|
|
|
|
*
|
|
|
|
* @param {string} pw The Password to Lock the Logger
|
|
|
|
* @memberof NopeLogger
|
|
|
|
*/
|
|
|
|
lock(pw: string): void {
|
|
|
|
if (this._pw !== "") {
|
|
|
|
this._loggers.get("").error("Please unlock before");
|
|
|
|
} else {
|
|
|
|
this._pw = pw;
|
2020-11-06 13:17:47 +00:00
|
|
|
}
|
2020-12-04 18:10:33 +00:00
|
|
|
}
|
2020-11-06 13:17:47 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
/**
|
|
|
|
* Unlock the Logger, therefore the password used for locking is
|
|
|
|
* required. After unlocking, the log-level can be adapted.
|
|
|
|
*
|
|
|
|
* @param {string} pw
|
|
|
|
* @memberof NopeLogger
|
|
|
|
*/
|
|
|
|
unlock(pw: string): void {
|
|
|
|
if (this._pw === pw) {
|
|
|
|
this._pw = "";
|
|
|
|
} else {
|
|
|
|
this._loggers.get("").error("Unlocking wasnt successfull");
|
2020-11-06 13:17:47 +00:00
|
|
|
}
|
2020-12-04 18:10:33 +00:00
|
|
|
}
|
2020-11-06 13:17:47 +00:00
|
|
|
|
2020-12-04 18:10:33 +00:00
|
|
|
/**
|
|
|
|
* Flag indicating, whether the logger is locked or not.
|
|
|
|
*
|
|
|
|
* @readonly
|
|
|
|
* @memberof NopeLogger
|
|
|
|
*/
|
|
|
|
public get isLocked(): boolean {
|
|
|
|
return this._pw !== "";
|
|
|
|
}
|
|
|
|
}
|