A fix to log missed errors and create a log file for all console.log/error
On Bot-Hosting.net people often miss errors in their console. Therefor this fix and with the bonus of it creating a log file for all console.log/error in their code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
const fs = require("node:fs");
const path = require("node:path");
// Logging
const maxFileSize = 1 * 1024 * 1024; // 1 MB limit
const logFilePath = path.join(__dirname, "bot.log");
const backupFilePath = path.join(__dirname, "bot.log.old");
const timeFormatter = new Intl.DateTimeFormat("en-US", {
timeZone: "America/New_York", // Change to your preferred time zone
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false, // Use false for 24-hour format, true for AM/PM
});
let logStream = fs.createWriteStream(logFilePath, { flags: "a" });
function checkLogSize() {
try {
if (fs.existsSync(logFilePath)) {
const stats = fs.statSync(logFilePath);
if (stats.size >= maxFileSize) {
logStream.end();
if (fs.existsSync(backupFilePath)) fs.unlinkSync(backupFilePath);
fs.renameSync(logFilePath, backupFilePath);
logStream = fs.createWriteStream(logFilePath, { flags: "a" });
}
}
} catch (err) {
process.stderr.write(`[LOG ROTATION ERROR] ${err.message}\n`);
}
}
function formatLogArgs(message, args) {
const allItems = [message, ...args];
return allItems
.map((item) => {
if (item instanceof Error) {
return item.stack;
}
if (typeof item === "object") {
return JSON.stringify(item, null, 2);
}
return item;
})
.join(" ");
}
// Helper to find where console.log/error was called
function getCallerFile() {
const logTrace = new Error();
if (!logTrace.stack) return "unknown";
const stackLines = logTrace.stack.split("\n");
const callerLine = stackLines[3] || "";
const match = callerLine.match(/\((.*)\)/) || callerLine.match(/at\s+(.*)/);
return match ? path.basename(match[1]) : "unknown";
}
// Override console.log
console.log = function (message, ...args) {
checkLogSize();
const timestamp = timeFormatter.format(new Date());
const traceInfo = getCallerFile();
const content = formatLogArgs(message, args);
const formattedMessage = `[${timestamp}] [INFO] [${traceInfo}]\n${content}\n`;
logStream.write(formattedMessage);
process.stdout.write(formattedMessage);
};
// Override console.error
console.error = function (message, ...args) {
checkLogSize();
const timestamp = timeFormatter.format(new Date());
const traceInfo = getCallerFile();
const content = formatLogArgs(message, args);
const formattedMessage = `[${timestamp}] [ERROR] [${traceInfo}]\n${content}\n\n`;
logStream.write(formattedMessage);
process.stderr.write(formattedMessage);
};
// Catches regular synchronous or code-level runtime errors
process.on("uncaughtException", (error, origin) => {
console.error(`[CRITICAL ERROR] Uncaught Exception at: ${origin}`);
console.error(error.stack || error);
});
// Catches unhandled async/await promise rejections (very common if Discord APIs time out)
process.on("unhandledRejection", (reason, promise) => {
console.error(`[CRITICAL ERROR] Unhandled Promise Rejection at:`, promise);
console.error(`Reason:`, reason?.stack || reason);
});
This post is licensed under CC BY 4.0 by the author.