nope/lib/logger/nopeLogger.ts

230 lines
5.9 KiB
TypeScript
Raw Normal View History

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 !== '';
}
}