diff --git a/index.js b/index.js index f0a484d..ae109b2 100644 --- a/index.js +++ b/index.js @@ -3,13 +3,16 @@ const fs = require("fs"); const bodyParser = require("body-parser"); const ws = require('ws'); const helper = require("./helpers.js"); +const loggy = require("./logging") +loggy.init(true) -console.log("Preparing server..."); +loggy.log("Preparing server", "info", "Server"); const app = express(); +loggy.log("Preparing static routes", "info", "Server"); app.use(express.static("static")); -app.use(express.static("node_modules")); +loggy.log("Preparing middlewares", "info", "Server"); app.use(bodyParser.json()); app.use( bodyParser.urlencoded({ @@ -20,6 +23,7 @@ app.use( let loadedData = {} +loggy.log("Loading config", "info", "Config"); if (fs.existsSync("data-persistence.json")) { const loadedDataRaw = fs.readFileSync("data-persistence.json", "utf8"); loadedData = JSON.parse(loadedDataRaw); @@ -54,7 +58,7 @@ currentState = Object.assign({}, currentState, loadedData); currentState.textColors = currentState.colorSegments - +loggy.log("Preparing websocket", "info", "Websocket"); const wsServer = new ws.Server({ noServer: true }); wsServer.on('connection', socket => { socket.on('message', function incoming(data) { @@ -81,7 +85,7 @@ function updatedData() { setTimeout(updatedData, 5000); } -console.log("Preparing routes..."); +loggy.log("Preparing routes", "info", "Server"); app.get("/", function (req, res) { const data = fs.readFileSync("templates/newAdminPanel.html", "utf8"); res.send(data); @@ -297,6 +301,7 @@ app.get("/api/v1/storage/delete", function (req, res) { app.use(function(req, res, next) { res.status(404); + loggy.log("Server responded with 404 error", "warn", "Server", true); // respond with html page if (req.accepts('html')) { @@ -318,8 +323,20 @@ app.use(function(req, res, next) { -console.log("Starting server..."); +loggy.log("Starting server", "info", "Server"); + + const port = 3005 + +process.on('SIGINT', function () { + loggy.log("Caught interrupt signal and shutting down gracefully", "info", "Shutdown"); + server.close(); // Make the express server stop + loggy.log("Goodbye! 👋", "magic", "Shutdown", true) + loggy.close() + process.exit(); // Quit the application + +}); + const server = app.listen(port); server.on('upgrade', (request, socket, head) => { wsServer.handleUpgrade(request, socket, head, socket => { @@ -328,7 +345,8 @@ server.on('upgrade', (request, socket, head) => { }); - -console.info("Server running on port " + port); -console.info("Visit localhost:" + port + "/timer for the timer page"); -console.info("Visit localhost:" + port + " for the admin page"); +loggy.log("=======================", "info", "", true); +loggy.log("Server running on port " + port, "magic", "", true); +loggy.log("Visit http://localhost:" + port + "/timer for the timer view", "magic", "", true); +loggy.log("Visit http://localhost:" + port + " for the admin view", "magic", "", true); +loggy.log("=======================", "info", "", true); \ No newline at end of file diff --git a/log-journal.json b/log-journal.json new file mode 100644 index 0000000..0c3da15 --- /dev/null +++ b/log-journal.json @@ -0,0 +1 @@ +[{"timestamp":"2022-03-29 20:16:25.083","level":"info","module":"Logging","message":"2022-03-29 20:16:25.083 [info] [Logging] Logging initialized"},{"timestamp":"2022-03-29 20:16:25.084","level":"info","module":"Server","message":"2022-03-29 20:16:25.084 [info] [Server] Preparing server"},{"timestamp":"2022-03-29 20:16:25.085","level":"info","module":"Server","message":"2022-03-29 20:16:25.085 [info] [Server] Preparing static routes"},{"timestamp":"2022-03-29 20:16:25.087","level":"info","module":"Server","message":"2022-03-29 20:16:25.087 [info] [Server] Preparing middlewares"},{"timestamp":"2022-03-29 20:16:25.088","level":"info","module":"Config","message":"2022-03-29 20:16:25.088 [info] [Config] Loading config"},{"timestamp":"2022-03-29 20:16:25.088","level":"info","module":"Websocket","message":"2022-03-29 20:16:25.088 [info] [Websocket] Preparing websocket"},{"timestamp":"2022-03-29 20:16:25.089","level":"info","module":"Server","message":"2022-03-29 20:16:25.089 [info] [Server] Preparing routes"},{"timestamp":"2022-03-29 20:16:25.091","level":"info","module":"Server","message":"2022-03-29 20:16:25.091 [info] [Server] Starting server"},{"timestamp":"2022-03-29 20:16:35.159","level":"info","module":"Shutdown","message":"2022-03-29 20:16:35.159 [info] [Shutdown] Caught interrupt signal and shutting down gracefully"}] \ No newline at end of file diff --git a/logging.js b/logging.js new file mode 100644 index 0000000..5a6ce4e --- /dev/null +++ b/logging.js @@ -0,0 +1,61 @@ +const colors = require('colors'); +const util = require('util') +const fs = require('fs'); + +let logToFileJson = false; +let logJournal = []; + +function init(logToFile = false) { + logToFileJson = logToFile; + log("Logging initialized", "info", "Logging"); +} + +function close(){ + if(logToFileJson){ + const tempString = JSON.stringify(logJournal); + try { + fs.writeFileSync("log-journal.json", tempString); + } catch (error) { + log("Error while closing log file: " + error, "error", "Logging"); + } + } + log("Saved log", "info", "Logging"); +} + +/** + * A simple logging function + * @param {String} message A messaged to be logged + * @param {String} level Logleve, may either be warn, error, magic or info + * @param {String} module Kinda the source + */ +function log(message, level, module, ignore = false) { + if (level == undefined) { + level = "info"; + } + if (module == undefined) { + module = "Unknown"; + } + if(String(message) == "[object Object]"){ + message = util.inspect(message, false, null, false); + } + const timestamp = new Date().toISOString().replace("T", " ").replace("Z", ""); + var message = timestamp + " [" + String(level) + "] " + " [" + String(module) + "] " + String(message); + if (level == "warn") { + console.warn(message.yellow); + } else if (level == "error") { + console.error(message.red); + } else if (level == "magic") { + console.error(message.magenta); + } else if (level == "info") { + console.info(message.white); + } else { + console.log(message.gray); + } + + if(logToFileJson && ignore == false){ + jsonObject = {timestamp: timestamp, level: level, module: module, message: message}; + logJournal.push(jsonObject); + } +} + +module.exports = { log, init, close}; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0f8f883..68f645e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "bootstrap": "^5.1.3", "bootstrap-duration-picker": "^2.1.3", "bootstrap-icons": "^1.8.1", + "colors": "^1.4.0", "darkreader": "^4.9.44", "express": "^4.17.3", "flatpickr": "^4.6.11", @@ -103,6 +104,14 @@ "node": ">= 0.8" } }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -789,6 +798,11 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", diff --git a/package.json b/package.json index 0026266..0583105 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "bootstrap": "^5.1.3", "bootstrap-duration-picker": "^2.1.3", "bootstrap-icons": "^1.8.1", + "colors": "^1.4.0", "darkreader": "^4.9.44", "express": "^4.17.3", "flatpickr": "^4.6.11",