swaf/src/Logger.ts

122 lines
3.8 KiB
TypeScript

import config from "config";
import {v4 as uuid} from "uuid";
import Log from "./models/Log";
const LOG_LEVEL: LogLevelKeys = <LogLevelKeys>config.get<string>('log_level');
const DB_LOG_LEVEL: LogLevelKeys = <LogLevelKeys>config.get<string>('db_log_level');
export default class Logger {
public static silentError(error: Error, ...message: any[]): string {
return this.log('ERROR', message, error, true) || '';
}
public static error(error: Error, ...message: any[]): string {
return this.log('ERROR', message, error) || '';
}
public static warn(...message: any[]) {
this.log('WARN', message);
}
public static info(...message: any[]) {
this.log('INFO', message);
}
public static debug(...message: any[]) {
this.log('DEBUG', message);
}
public static dev(...message: any[]) {
this.log('DEV', message);
}
private static log(level: LogLevelKeys, message: any[], error?: Error, silent: boolean = false): string | null {
const levelIndex = LogLevel[level];
if (levelIndex <= LogLevel[LOG_LEVEL]) {
if (error) {
if (levelIndex > LogLevel.ERROR) this.warn(`Wrong log level ${level} with attached error.`);
} else {
if (levelIndex <= LogLevel.ERROR) this.warn(`No error attached with log level ${level}.`);
}
const computedMsg = message.map(v => {
if (typeof v === 'string') {
return v;
} else {
return JSON.stringify(v, (key: string, value: any) => {
if (value instanceof Object) {
if (value.type === 'Buffer') {
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(' ');
const log = new Log({});
log.setLevel(level);
log.message = computedMsg;
log.setError(error);
let logID = Buffer.alloc(16);
uuid({}, logID);
log.setLogID(logID);
let output = `[${level}] `;
let pad = output.length;
if (levelIndex <= LogLevel[DB_LOG_LEVEL]) output += `${log.getLogID()} - `;
output += computedMsg.replace(/\n/g, '\n' + ' '.repeat(pad));
switch (level) {
case "ERROR":
if (silent || !error) {
console.error(output);
} else {
console.error(output, error);
}
break;
case "WARN":
console.warn(output);
break;
case "INFO":
console.info(output);
break;
case "DEBUG":
case "DEV":
console.debug(output);
break;
}
if (levelIndex <= LogLevel[DB_LOG_LEVEL]) {
log.save().catch(err => {
if (!silent && err.message.indexOf('ECONNREFUSED') < 0) {
console.error({save_err: err, error});
}
});
}
return log.getLogID();
}
return null;
}
private constructor() {
}
}
export enum LogLevel {
ERROR,
WARN,
INFO,
DEBUG,
DEV,
}
export type LogLevelKeys = keyof typeof LogLevel;