2020-11-06 13:17:47 +00:00
|
|
|
import { createLogger, format, Logger, transports } from "winston";
|
|
|
|
import { SPLITCHAR } from "../helpers/objectMethods";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Contains the Valid Types of the Loger.
|
|
|
|
*/
|
2020-11-07 10:55:29 +00:00
|
|
|
export type LoggerLevel = 'error' | 'warn' | 'info' | 'http' | 'verbose' | 'debug' | 'silly';
|
|
|
|
|
|
|
|
const order: {[K in LoggerLevel]: number} = {
|
|
|
|
error: 0,
|
|
|
|
warn: 1,
|
|
|
|
info: 2,
|
|
|
|
http: 3,
|
|
|
|
verbose: 4,
|
|
|
|
debug: 5,
|
|
|
|
silly: 6
|
|
|
|
}
|
|
|
|
|
|
|
|
const reverseOrder: {[index:number]: LoggerLevel} = {};
|
|
|
|
Object.getOwnPropertyNames(order).map((key: LoggerLevel) => reverseOrder[order[key]] = key);
|
|
|
|
|
|
|
|
function _selectLevel(master: LoggerLevel, slave: LoggerLevel){
|
|
|
|
const masterLevel = order[master];
|
|
|
|
const slaveLevel = order[slave];
|
|
|
|
|
|
|
|
return reverseOrder[Math.min(masterLevel,slaveLevel)];
|
|
|
|
}
|
2020-11-06 13:17:47 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper Function to generate default Logger Options.
|
|
|
|
* This results in creating a Logger with a specific label,
|
|
|
|
* and rendering format.
|
|
|
|
*
|
|
|
|
* @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 {*} The Loger-Options as Object
|
|
|
|
*/
|
|
|
|
function _generateLoggerOptions(level: LoggerLevel, label: string = '') {
|
|
|
|
let readableFormat: any;
|
|
|
|
|
|
|
|
if (label) {
|
|
|
|
readableFormat = format.printf(({ level, message, timestamp, label }) => {
|
|
|
|
return `[${timestamp} ${level}] - ${label}: ${message}`;
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
readableFormat = format.printf(({ level, message, timestamp }) => {
|
|
|
|
return `[${timestamp} ${level}]: ${message}`;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
level,
|
|
|
|
format: label ? format.combine(
|
|
|
|
format.timestamp({
|
|
|
|
format: 'YYYY-MM-DD HH:mm:ss:ms'
|
|
|
|
}),
|
|
|
|
format.label({ label }),
|
|
|
|
format.errors({ stack: true }),
|
|
|
|
readableFormat
|
|
|
|
) : format.combine(
|
|
|
|
format.timestamp({
|
|
|
|
format: 'YYYY-MM-DD HH:mm:ss:ms'
|
|
|
|
}),
|
|
|
|
format.errors({ stack: true }),
|
|
|
|
readableFormat
|
|
|
|
),
|
|
|
|
exitOnError: false,
|
|
|
|
transports: [
|
|
|
|
new (transports.Console)({
|
|
|
|
format: format.combine(
|
|
|
|
format.colorize(),
|
|
|
|
readableFormat
|
|
|
|
)
|
|
|
|
}),
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper Function, to create a Logger.
|
|
|
|
* Therefore it uses a specific Level and a Lable of the
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
function _getLogger(level: LoggerLevel, label: string = '') {
|
|
|
|
return createLogger(_generateLoggerOptions(level, label));
|
|
|
|
}
|
|
|
|
|
|
|
|
export class NopeLogger {
|
|
|
|
|
|
|
|
protected _logger: Logger;
|
|
|
|
protected _loggers: Map<string, Logger>;
|
|
|
|
|
|
|
|
set level(value: LoggerLevel) {
|
|
|
|
if (!this.isLocked) {
|
|
|
|
this._level = value;
|
|
|
|
this.setLoglevel('core' + SPLITCHAR, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
get level() {
|
|
|
|
return this._level;
|
|
|
|
}
|
|
|
|
|
|
|
|
public _level: LoggerLevel = 'debug';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create or returns the provided Logger
|
|
|
|
* @param name
|
|
|
|
* @param level
|
|
|
|
*/
|
|
|
|
getLogger(name: string = '', level: LoggerLevel = this.level) {
|
|
|
|
if (!this._loggers.has(name)) {
|
|
|
|
this._loggers.set(
|
|
|
|
name,
|
2020-11-07 10:55:29 +00:00
|
|
|
_getLogger(_selectLevel(this.level, level), name)
|
2020-11-06 13:17:47 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
return this._loggers.get(name) as Logger;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function to a Stream to the Logger
|
|
|
|
* @param stream
|
|
|
|
*/
|
|
|
|
addStream(stream) {
|
|
|
|
// Store the Stream for new Streams
|
|
|
|
this._logger.add(stream)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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) {
|
|
|
|
if (!loggerGroup.startsWith('core' + SPLITCHAR)) {
|
|
|
|
loggerGroup = 'core' + SPLITCHAR + loggerGroup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!loggerGroup.endsWith(SPLITCHAR)) {
|
|
|
|
loggerGroup += SPLITCHAR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!name.endsWith(SPLITCHAR)) {
|
|
|
|
name += SPLITCHAR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name == loggerGroup || name.startsWith(loggerGroup)) {
|
|
|
|
/** Update the Level */
|
|
|
|
logger.level = level;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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) {
|
2020-11-07 10:55:29 +00:00
|
|
|
return order[this.getLogger(loggerName).level] >= order[level];
|
2020-11-06 13:17:47 +00:00
|
|
|
}
|
|
|
|
|
2020-11-07 10:55:29 +00:00
|
|
|
|
|
|
|
|
2020-11-06 13:17:47 +00:00
|
|
|
/**
|
|
|
|
* Creates A Logger-Manager
|
|
|
|
*/
|
|
|
|
constructor() {
|
|
|
|
this._loggers = new Map<string, Logger>();
|
|
|
|
|
|
|
|
this._logger = _getLogger('debug', 'root');
|
|
|
|
this._loggers.set('', this._logger);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected _pw: string = '';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Lock the Logger Level with a password
|
|
|
|
*
|
|
|
|
* @param {string} pw The Password to Lock the Logger
|
|
|
|
* @memberof NopeLogger
|
|
|
|
*/
|
|
|
|
lock(pw: string) {
|
|
|
|
if (this._pw !== '') {
|
|
|
|
this._loggers.get('').error('Please unlock before');
|
|
|
|
} else {
|
|
|
|
this._pw = pw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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) {
|
|
|
|
if (this._pw === pw) {
|
|
|
|
this._pw = '';
|
|
|
|
} else {
|
|
|
|
this._loggers.get('').error('Unlocking wasnt successfull');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Flag indicating, whether the logger is locked or not.
|
|
|
|
*
|
|
|
|
* @readonly
|
|
|
|
* @memberof NopeLogger
|
|
|
|
*/
|
|
|
|
public get isLocked() {
|
|
|
|
return this._pw !== '';
|
|
|
|
}
|
|
|
|
}
|