2020-04-22 15:52:17 +02:00
|
|
|
import config from "config";
|
|
|
|
import {v4 as uuid} from "uuid";
|
|
|
|
import Log from "./models/Log";
|
2020-09-25 23:42:15 +02:00
|
|
|
import {bufferToUuid} from "./Utils";
|
|
|
|
import ModelFactory from "./db/ModelFactory";
|
2020-04-22 15:52:17 +02:00
|
|
|
|
2020-09-25 23:42:15 +02:00
|
|
|
export enum LogLevel {
|
|
|
|
ERROR,
|
|
|
|
WARN,
|
|
|
|
INFO,
|
|
|
|
DEBUG,
|
|
|
|
DEV,
|
|
|
|
}
|
|
|
|
|
|
|
|
export type LogLevelKeys = keyof typeof LogLevel;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* TODO: make logger not static
|
|
|
|
*/
|
2020-04-22 15:52:17 +02:00
|
|
|
export default class Logger {
|
2020-09-25 23:42:15 +02:00
|
|
|
private static logLevel: LogLevel = LogLevel[<LogLevelKeys>config.get<string>('log.level')];
|
|
|
|
private static dbLogLevel: LogLevel = LogLevel[<LogLevelKeys>config.get<string>('log.db_level')];
|
2020-09-25 22:19:13 +02:00
|
|
|
private static verboseMode: boolean = config.get<boolean>('log.verbose');
|
2020-06-05 14:32:39 +02:00
|
|
|
|
2020-09-25 23:42:15 +02:00
|
|
|
public static verbose(): void {
|
2020-06-14 21:47:36 +02:00
|
|
|
this.verboseMode = true;
|
2020-09-25 23:42:15 +02:00
|
|
|
if (LogLevel[this.logLevel + 1]) this.logLevel++;
|
|
|
|
if (LogLevel[this.dbLogLevel + 1]) this.dbLogLevel++;
|
2020-06-14 11:43:00 +02:00
|
|
|
Logger.info('Verbose mode');
|
2020-06-05 14:32:39 +02:00
|
|
|
}
|
|
|
|
|
2020-06-14 21:47:36 +02:00
|
|
|
public static isVerboseMode(): boolean {
|
|
|
|
return this.verboseMode;
|
|
|
|
}
|
|
|
|
|
2020-09-25 23:42:15 +02:00
|
|
|
public static silentError(error: Error, ...message: unknown[]): string {
|
|
|
|
return this.log(LogLevel.ERROR, message, error, true) || '';
|
2020-04-22 15:52:17 +02:00
|
|
|
}
|
|
|
|
|
2020-09-25 23:42:15 +02:00
|
|
|
public static error(error: Error, ...message: unknown[]): string {
|
|
|
|
return this.log(LogLevel.ERROR, message, error) || '';
|
2020-04-22 15:52:17 +02:00
|
|
|
}
|
|
|
|
|
2020-09-25 23:42:15 +02:00
|
|
|
public static warn(...message: unknown[]): void {
|
|
|
|
this.log(LogLevel.WARN, message);
|
2020-04-22 15:52:17 +02:00
|
|
|
}
|
|
|
|
|
2020-09-25 23:42:15 +02:00
|
|
|
public static info(...message: unknown[]): void {
|
|
|
|
this.log(LogLevel.INFO, message);
|
2020-04-22 15:52:17 +02:00
|
|
|
}
|
|
|
|
|
2020-09-25 23:42:15 +02:00
|
|
|
public static debug(...message: unknown[]): void {
|
|
|
|
this.log(LogLevel.DEBUG, message);
|
2020-04-22 15:52:17 +02:00
|
|
|
}
|
|
|
|
|
2020-09-25 23:42:15 +02:00
|
|
|
public static dev(...message: unknown[]): void {
|
|
|
|
this.log(LogLevel.DEV, message);
|
2020-04-22 15:52:17 +02:00
|
|
|
}
|
|
|
|
|
2020-09-25 23:42:15 +02:00
|
|
|
private static log(level: LogLevel, message: unknown[], error?: Error, silent: boolean = false): string | null {
|
|
|
|
if (level <= this.logLevel) {
|
2020-04-22 15:52:17 +02:00
|
|
|
if (error) {
|
2020-09-25 23:42:15 +02:00
|
|
|
if (level > LogLevel.ERROR) this.warn(`Wrong log level ${level} with attached error.`);
|
2020-04-22 15:52:17 +02:00
|
|
|
} else {
|
2020-09-25 23:42:15 +02:00
|
|
|
if (level <= LogLevel.ERROR) this.warn(`No error attached with log level ${level}.`);
|
2020-04-22 15:52:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const computedMsg = message.map(v => {
|
|
|
|
if (typeof v === 'string') {
|
|
|
|
return v;
|
|
|
|
} else {
|
2020-09-25 23:42:15 +02:00
|
|
|
return JSON.stringify(v, (key: string, value: string | unknown[] | Record<string, unknown>) => {
|
|
|
|
if (!Array.isArray(value) && value instanceof Object) {
|
|
|
|
if (value.type === 'Buffer' && typeof value.data === 'string') {
|
2020-04-22 15:52:17 +02:00
|
|
|
return `Buffer<${Buffer.from(value.data).toString('hex')}>`;
|
|
|
|
} else if (value !== v) {
|
|
|
|
return `[object Object]`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (typeof value === 'string' && value.length > 96) {
|
|
|
|
return value.substr(0, 96) + '...';
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}, 4);
|
|
|
|
}
|
|
|
|
}).join(' ');
|
|
|
|
|
2020-09-25 23:42:15 +02:00
|
|
|
const shouldSaveToDB = level <= this.dbLogLevel;
|
2020-04-22 15:52:17 +02:00
|
|
|
|
2020-10-02 11:11:01 +02:00
|
|
|
let output = `[${LogLevel[level]}] `;
|
2020-07-24 15:40:10 +02:00
|
|
|
const pad = output.length;
|
2020-04-22 15:52:17 +02:00
|
|
|
|
2020-09-25 23:42:15 +02:00
|
|
|
const logId = Buffer.alloc(16);
|
|
|
|
uuid({}, logId);
|
|
|
|
const strLogId = bufferToUuid(logId);
|
|
|
|
if (shouldSaveToDB) output += `${strLogId} - `;
|
2020-04-22 15:52:17 +02:00
|
|
|
|
|
|
|
output += computedMsg.replace(/\n/g, '\n' + ' '.repeat(pad));
|
|
|
|
|
|
|
|
switch (level) {
|
2020-09-25 23:42:15 +02:00
|
|
|
case LogLevel.ERROR:
|
2020-04-22 15:52:17 +02:00
|
|
|
if (silent || !error) {
|
|
|
|
console.error(output);
|
|
|
|
} else {
|
|
|
|
console.error(output, error);
|
|
|
|
}
|
|
|
|
break;
|
2020-09-25 23:42:15 +02:00
|
|
|
case LogLevel.WARN:
|
2020-04-22 15:52:17 +02:00
|
|
|
console.warn(output);
|
|
|
|
break;
|
2020-09-25 23:42:15 +02:00
|
|
|
case LogLevel.INFO:
|
2020-04-22 15:52:17 +02:00
|
|
|
console.info(output);
|
|
|
|
break;
|
2020-09-25 23:42:15 +02:00
|
|
|
case LogLevel.DEBUG:
|
|
|
|
case LogLevel.DEV:
|
2020-04-22 15:52:17 +02:00
|
|
|
console.debug(output);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-09-25 23:42:15 +02:00
|
|
|
if (shouldSaveToDB && ModelFactory.has(Log)) {
|
2020-07-27 10:52:39 +02:00
|
|
|
const log = Log.create({});
|
2020-07-24 15:40:10 +02:00
|
|
|
log.setLevel(level);
|
|
|
|
log.message = computedMsg;
|
|
|
|
log.setError(error);
|
2020-09-25 23:42:15 +02:00
|
|
|
log.setLogId(logId);
|
2020-04-22 15:52:17 +02:00
|
|
|
log.save().catch(err => {
|
|
|
|
if (!silent && err.message.indexOf('ECONNREFUSED') < 0) {
|
|
|
|
console.error({save_err: err, error});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2020-09-25 23:42:15 +02:00
|
|
|
return strLogId;
|
2020-04-22 15:52:17 +02:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private constructor() {
|
2020-09-25 23:42:15 +02:00
|
|
|
// disable constructor
|
2020-04-22 15:52:17 +02:00
|
|
|
}
|
|
|
|
}
|