diff --git a/server/controllers/logController.js b/server/controllers/logController.js new file mode 100644 index 000000000..00cf7bbcb --- /dev/null +++ b/server/controllers/logController.js @@ -0,0 +1,23 @@ +import { handleError } from "./controllerUtils.js"; + +const SERVICE_NAME = "JobQueueController"; + +class LogController { + constructor(logger) { + this.logger = logger; + } + + getLogs = async (req, res, next) => { + try { + const logs = await this.logger.getLogs(); + res.success({ + msg: "Logs fetched successfully", + data: logs, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "getMetrics")); + return; + } + }; +} +export default LogController; diff --git a/server/index.js b/server/index.js index 99be6de7a..4b74ef46c 100755 --- a/server/index.js +++ b/server/index.js @@ -36,6 +36,9 @@ import StatusPageController from "./controllers/statusPageController.js"; import QueueRoutes from "./routes/queueRoute.js"; import QueueController from "./controllers/queueController.js"; +import LogRoutes from "./routes/logRoutes.js"; +import LogController from "./controllers/logController.js"; + import NotificationRoutes from "./routes/notificationRoute.js"; import NotificationController from "./controllers/notificationController.js"; @@ -294,6 +297,8 @@ const startApp = async () => { ServiceRegistry.get(StringService.SERVICE_NAME) ); + const logController = new LogController(logger); + const statusPageController = new StatusPageController( ServiceRegistry.get(MongoDB.SERVICE_NAME), ServiceRegistry.get(StringService.SERVICE_NAME) @@ -320,6 +325,7 @@ const startApp = async () => { maintenanceWindowController ); const queueRoutes = new QueueRoutes(queueController); + const logRoutes = new LogRoutes(logController); const statusPageRoutes = new StatusPageRoutes(statusPageController); const notificationRoutes = new NotificationRoutes(notificationController); @@ -372,6 +378,7 @@ const startApp = async () => { app.use("/api/v1/checks", verifyJWT, checkRoutes.getRouter()); app.use("/api/v1/maintenance-window", verifyJWT, maintenanceWindowRoutes.getRouter()); app.use("/api/v1/queue", verifyJWT, queueRoutes.getRouter()); + app.use("/api/v1/logs", verifyJWT, logRoutes.getRouter()); app.use("/api/v1/status-page", statusPageRoutes.getRouter()); app.use("/api/v1/notifications", verifyJWT, notificationRoutes.getRouter()); app.use("/api/v1/diagnostic", verifyJWT, diagnosticRoutes.getRouter()); diff --git a/server/routes/logRoutes.js b/server/routes/logRoutes.js new file mode 100755 index 000000000..867826dde --- /dev/null +++ b/server/routes/logRoutes.js @@ -0,0 +1,18 @@ +import { Router } from "express"; +import { isAllowed } from "../middleware/isAllowed.js"; +class LogRoutes { + constructor(logController) { + this.router = Router(); + this.logController = logController; + this.initRoutes(); + } + initRoutes() { + this.router.get("/", isAllowed(["admin", "superadmin"]), this.logController.getLogs); + } + + getRouter() { + return this.router; + } +} + +export default LogRoutes; diff --git a/server/utils/logger.js b/server/utils/logger.js index 155adc957..f19694987 100755 --- a/server/utils/logger.js +++ b/server/utils/logger.js @@ -4,6 +4,8 @@ dotenv.config(); class Logger { constructor() { + this.logCache = []; + this.maxCacheSize = 500; const consoleFormat = format.printf( ({ level, message, service, method, details, timestamp, stack }) => { if (message instanceof Object) { @@ -72,11 +74,17 @@ class Logger { * @param {Object} config.details - Additional details. */ info(config) { - this.logger.info(config.message, { + const logEntry = { + level: "info", + message: config.message, service: config.service, method: config.method, details: config.details, - }); + timestamp: new Date().toISOString(), + }; + + this.cacheLog(logEntry); + this.logger.info(config.message, logEntry); } /** @@ -88,11 +96,17 @@ class Logger { * @param {Object} config.details - Additional details. */ warn(config) { - this.logger.warn(config.message, { + const logEntry = { + level: "warn", + message: config.message, service: config.service, method: config.method, details: config.details, - }); + timestamp: new Date().toISOString(), + }; + + this.cacheLog(logEntry); + this.logger.warn(config.message, logEntry); } /** @@ -104,12 +118,17 @@ class Logger { * @param {Object} config.details - Additional details. */ error(config) { - this.logger.error(config.message, { + const logEntry = { + level: "error", + message: config.message, service: config.service, method: config.method, details: config.details, - stack: config.stack, - }); + timestamp: new Date().toISOString(), + }; + + this.cacheLog(logEntry); + this.logger.error(config.message, logEntry); } /** * Logs a debug message. @@ -120,12 +139,28 @@ class Logger { * @param {Object} config.details - Additional details. */ debug(config) { - this.logger.debug(config.message, { + const logEntry = { + level: "debug", + message: config.message, service: config.service, method: config.method, details: config.details, - stack: config.stack, - }); + timestamp: new Date().toISOString(), + }; + + this.cacheLog(logEntry); + this.logger.debug(config.message, logEntry); + } + + cacheLog(entry) { + this.logCache.push(entry); + if (this.logCache.length > this.maxCacheSize) { + this.logCache.shift(); + } + } + + getLogs() { + return this.logCache; } }