Files
legolog/src/logger.js
Benjamin Kyd 4a83c84d3d something
Former-commit-id: 41811c2d7d98c1d3ad65e0d1dd559de64f96845e
2022-03-25 15:57:12 +00:00

169 lines
4.9 KiB
JavaScript

// Better than Log4j2022 for now.
const net = require('net');
const fs = require('fs');
const moment = require('moment');
const clc = require('cli-color');
const LEVEL_VERBOSE = 0;
const LEVEL_DEBUG = 1;
const LEVEL_INFO = 2;
const LEVEL_WARN = 3;
const LEVEL_STICK = 9; // regardless, will log
let DoNetworkLogging = false;
// default values
let Options = {
logLevel: LEVEL_VERBOSE,
logToConsole: true,
logFile: null,
networkHost: null,
networkPort: null,
};
let Socket = null;
function getFormatedTimeString() {
return `[${moment().format('YYYY-MM-DD HH:mm:ss.SSS')}]`;
}
// levelSource is the level that the source will log at ie, if levelSource is
// LEVEL_WARN, it will only log if the current level is at or above LEVEL_WARN.
function internalLog(type, message, cConsoleColour, levelSource) {
if (Options.logToConsole && (Options.logLevel <= levelSource)) {
console.log(`${getFormatedTimeString()} [${cConsoleColour(type)}] ${message}`);
}
const m = `${getFormatedTimeString()} [${type}] ${message}`;
if (Options.logFile) {
fs.appendFileSync(Options.logFile, m + '\n');
}
if (Options.networkHost && DoNetworkLogging) {
Socket.write(m + '\n');
}
if (type === 'PANIC') {
Destroy();
process.exit(1);
}
}
const Info = (...messages) => internalLog('INFO', messages.join(' '), clc.greenBright, LEVEL_INFO);
const Warn = (...messages) => internalLog('WARN', messages.join(' '), clc.yellowBright, LEVEL_WARN);
const Error = (...messages) => internalLog('ERROR', messages.join(' '), clc.redBright, LEVEL_STICK);
const Panic = (...messages) => internalLog('PANIC', messages.join(' '), clc.bgRedBright, LEVEL_STICK);
const Debug = (...messages) => internalLog('DEBUG', messages.join(' '), clc.cyanBright, LEVEL_DEBUG);
const Module = (module, ...messages) => internalLog(`MODULE [${module}]`, ` ${messages.join(' ')}`, clc.blue, LEVEL_INFO);
const Database = (...messages) => internalLog('PSQL', `[DB] ${messages.join(' ')}`, clc.blue, LEVEL_INFO);
const ExpressLogger = (req, res, next) => {
internalLog('HTTP', `[${req.method}] ${req.originalUrl} FROM ${req.headers['x-forwarded-for'] || req.socket.remoteAddress}`, clc.magenta, LEVEL_VERBOSE);
next();
};
function startReconnection() {
const x = setInterval(async () => {
if (Options.networkHost && Options.networkPort && !DoNetworkLogging) {
const success = await initNetworkLogger(Options.networkHost, Options.networkPort);
if (success) {
clearInterval(x);
Info('Logger Reonnected');
}
}
}, 30000);
}
function initNetworkLogger(host, port) {
return new Promise((resolve) => {
Socket = net.connect({
port,
host,
family: 4,
onread: {
// Reuses a 4KiB Buffer for every read from the socket.
buffer: Buffer.alloc(4 * 1024),
callback: function (nread, buf) {
Warn(`LogSocket: ${buf.toString('utf8', 0, nread)}`);
},
},
}, () => {
Info('Logger Connected to Network');
DoNetworkLogging = true;
resolve(true);
}).on('error', (err) => {
Error('Logger Disconnected from Network: ', err);
DoNetworkLogging = false;
resolve(false);
});
});
}
function postInit() {
Socket.on('close', () => {
Error('Logger Network Connection Closed');
DoNetworkLogging = false;
startReconnection();
});
Socket.on('error', (err) => {
Error('Logger Disconnected from Network: ', err);
DoNetworkLogging = false;
startReconnection();
});
}
/**
* Initialises the logger
* Options:
* - logLevel: The level of logging to be used ONLY APPLIES TO CONSOLE.
* - logToConsole: Whether to log to the console.
* - logFile: The file to log to, if provided, will log.
* - networkHost: The address to log to, including port, if provided, will log.
* - networkPort: The port to log to, including port, if provided, will log.
* TODO: SSL
* @param {Object} options
*/
async function Init(options) {
Options = options;
if (Options.logFile) {
fs.openSync(Options.logFile, 'w');
fs.appendFileSync(Options.logFile, 'START OF SESSION' + '\n');
}
if (!Options.networkHost || !Options.networkPort) {
return;
}
await initNetworkLogger(Options.networkHost, Options.networkPort);
postInit();
}
function Destroy() {
if (Options.logFile) {
fs.appendFileSync(Options.logFile, 'END OF SESSION' + '\n');
fs.closeSync(Options.logFile);
}
if (Options.networkHost) {
Socket.destroy();
}
}
module.exports = {
LEVEL_VERBOSE,
LEVEL_DEBUG,
LEVEL_INFO,
LEVEL_WARN,
Init,
Destroy,
Info,
Warn,
Error,
Panic,
Debug,
Module,
Database,
ExpressLogger,
};