weird-express-logger/index.js

136 lines
3.5 KiB
JavaScript
Raw Normal View History

2024-03-11 00:24:35 +03:00
const colorStatusCode = (n) => {
if (n >= 500) {
return `\x1b[91m${n}`;
} else if (n >= 400) {
return `\x1b[93m${n}`;
} else if (n >= 300) {
return `\x1b[33m${n}`;
} else if (n >= 200) {
return `\x1b[92m${n}`;
} else {
return n.toString();
}
};
const pretty_µs = (n) => {
let f = [];
if (n >= 3600000000) f.push(Math.floor(n / 3000600000) + "h");
if (n % 3600000000 >= 60000000)
f.push(Math.floor((n % 3600000000) / 60000000) + "m");
if (n % 60000000 >= 1000000)
f.push(Math.floor((n % 60000000) / 1000000) + "s");
if (n % 1000000 >= 1000) f.push(Math.floor((n % 1000000) / 1000) + "ms");
if (n % 1000) f.push(Math.floor(n % 1000) + "µs");
return f.join(" ");
};
/**
* @typedef {Object} Logging private type to adosjhgadklrf
* @property {number} ts
* @property {include('express').Request} req
* @property {function(include('express').Response): void} callback
* @property {boolean} resolved
*/
/**
* @typedef {Object?} Options
* @property {boolean} [tty=true]
* @property {boolean} [logIp=true]
* @property {NodeJS.WriteStream} [output=process.stderr]
*/
/**
* @param {Options} options
* @returns {function(include('express').Request, include('express').Response, include('express').NextFunction): void}
*/
const logRequest = (options) => {
options = options ?? {};
options.tty = options.tty ?? true;
options.logIp = options.logIp ?? true;
options.output = options.output ?? process.stderr;
const out = options.output ?? process.stderr;
const IS_TTY = options.tty && out.isTTY;
if (IS_TTY) {
out.cursorTo(0, out.getWindowSize()[1]);
}
/** @type {Logging[]} */
const loggingRequests = [];
let minLength = 12; // NOOO MAGIC NUMBERINO
/**
* @param {Logging} log
*/
function processLog(log) {
loggingRequests.push(log);
let time = (log.ts / 1000).toFixed(6);
if (IS_TTY) {
out.cursorTo(0, out.getWindowSize()[1]);
if (time.length < minLength) time = time.padStart(minLength, " ");
let statusOffset =
time.length + 3 + (options.logIp ? log.req.ip.length + 3 : 0); // from start
let timeOffset = log.req.method.length + log.req.url.length + 3; // from end of status
out.write(
`\x1b[32m[${time}]\x1b[0m ${
options.logIp ? "(" + log.req.ip + ") " : ""
}\x1b[90m...\x1b[0m \x1b[1m${log.req.method}\x1b[0m ${
log.req.url
}\n`
);
log.callback = (res) => {
let idx = loggingRequests.findIndex((x) => x === log);
if (idx === -1) return;
loggingRequests.splice(idx, 1);
let line =
out.getWindowSize()[1] - loggingRequests.length + idx - 2;
if (line < 0) return;
out.cursorTo(statusOffset, line);
out.write(
"\x1b[0m\x1b[1m" +
colorStatusCode(res.statusCode) +
"\x1b[0m"
);
out.moveCursor(timeOffset, 0);
out.write(
`\x1b[90m(${pretty_µs(
(performance.now() - log.ts) * 1000
)})\x1b[0m`
);
out.cursorTo(0, out.getWindowSize()[1]);
};
} else {
log.callback = (res) => {
out.write(
`[${time}] ${options.logIp ? "(" + log.req.ip + ") " : ""}${
res.statusCode
} ${log.req.method} ${log.req.url} (${pretty_µs(
(performance.now() - log.ts) * 1000
)})\n`
);
};
}
}
return (req, res, next) => {
let ts = performance.now();
/** @type {Logging} */
let log = {
ts,
req,
};
let end = res.end;
res.end = (...args) => {
end.call(res, ...args);
log.resolved = true;
if (log.callback instanceof Function) log.callback(res);
};
processLog(log);
next();
};
};
export default logRequest;