diff --git a/server.js b/server.js index 8acba572a..a92ab7241 100644 --- a/server.js +++ b/server.js @@ -153,18 +153,13 @@ const connectToRedisCluster = async () => { } else { // Use the Dockerized Redis cluster in development if (isEmpty(process.env?.REDIS_URL) || !isString(process.env?.REDIS_URL)) { - logger.log(`[${process.env.NODE_ENV}] No or Malformed REDIS_URL present.`, "ERROR", "redis", "api"); + logger.log(`No or Malformed REDIS_URL present.`, "ERROR", "redis", "api"); process.exit(1); } try { redisServers = JSON.parse(process.env.REDIS_URL); } catch (error) { - logger.log( - `[${process.env.NODE_ENV}] Failed to parse REDIS_URL: ${error.message}. Exiting...`, - "ERROR", - "redis", - "api" - ); + logger.log(`Failed to parse REDIS_URL: ${error.message}. Exiting...`, "ERROR", "redis", "api"); process.exit(1); } } @@ -172,12 +167,7 @@ const connectToRedisCluster = async () => { const clusterRetryStrategy = (times) => { const delay = Math.min(CLUSTER_RETRY_BASE_DELAY + times * 50, CLUSTER_RETRY_MAX_DELAY) + Math.random() * CLUSTER_RETRY_JITTER; - logger.log( - `[${process.env.NODE_ENV}] Redis cluster not yet ready. Retrying in ${delay.toFixed(2)}ms`, - "WARN", - "redis", - "api" - ); + logger.log(`Redis cluster not yet ready. Retrying in ${delay.toFixed(2)}ms`, "WARN", "redis", "api"); return delay; }; @@ -194,12 +184,12 @@ const connectToRedisCluster = async () => { return new Promise((resolve, reject) => { redisCluster.on("ready", () => { - logger.log(`[${process.env.NODE_ENV}] Redis cluster connection established.`, "INFO", "redis", "api"); + logger.log(`Redis cluster connection established.`, "INFO", "redis", "api"); resolve(redisCluster); }); redisCluster.on("error", (err) => { - logger.log(`[${process.env.NODE_ENV}] Redis cluster connection failed: ${err.message}`, "ERROR", "redis", "api"); + logger.log(`Redis cluster connection failed: ${err.message}`, "ERROR", "redis", "api"); reject(err); }); }); @@ -215,7 +205,7 @@ const applySocketIO = async ({ server, app }) => { // Handle errors redisCluster.on("error", (err) => { - logger.log(`[${process.env.NODE_ENV}] Redis ERROR`, "ERROR", "redis", "api"); + logger.log(`Redis ERROR`, "ERROR", "redis", "api"); }); const pubClient = redisCluster; @@ -249,7 +239,7 @@ const applySocketIO = async ({ server, app }) => { }); if (isString(process.env.REDIS_ADMIN_PASS) && !isEmpty(process.env.REDIS_ADMIN_PASS)) { - logger.log(`[${process.env.NODE_ENV}] Initializing Redis Admin UI....`, "INFO", "redis", "api"); + logger.log(`Initializing Redis Admin UI....`, "INFO", "redis", "api"); instrument(ioRedis, { auth: { type: "basic", @@ -312,9 +302,9 @@ const main = async () => { try { await server.listen(port); - logger.log(`[${process.env.NODE_ENV}] Server started on port ${port}`, "INFO", "api"); + logger.log(`Server started on port ${port}`, "INFO", "api"); } catch (error) { - logger.log(`[${process.env.NODE_ENV}] Server failed to start on port ${port}`, "ERROR", "api", error); + logger.log(`Server failed to start on port ${port}`, "ERROR", "api", error); } }; diff --git a/server/utils/logger.js b/server/utils/logger.js index 3a1742432..1344c34ac 100644 --- a/server/utils/logger.js +++ b/server/utils/logger.js @@ -8,6 +8,7 @@ const InstanceManager = require("../utils/instanceMgr").default; const winston = require("winston"); const WinstonCloudWatch = require("winston-cloudwatch"); const { isString, isEmpty } = require("lodash"); +const { networkInterfaces } = require("node:os"); const createLogger = () => { try { @@ -42,6 +43,19 @@ const createLogger = () => { })(); }; + const getPrivateIP = () => { + const interfaces = networkInterfaces(); + for (const name of Object.keys(interfaces)) { + for (const iface of interfaces[name]) { + // Find an IPv4 address that's not internal (like localhost) + if (iface.family === "IPv4" && !iface.internal) { + return iface.address; + } + } + } + return "127.0.0.1"; + }; + const createProductionTransport = (level, logStreamName, filters) => { return new WinstonCloudWatch({ level, @@ -51,17 +65,26 @@ const createLogger = () => { }); }; + const hostname = process.env?.HOSTNAME || getPrivateIP(); + const getDevelopmentTransports = () => [ new winston.transports.Console({ level: "silly", format: winston.format.combine( winston.format.colorize(), winston.format.timestamp(), - winston.format.printf(({ level, message, timestamp, user, record, object }) => { - return `${timestamp} [${level}]: ${message} ${ - user ? `| user: ${JSON.stringify(user)}` : "" - } ${record ? `| record: ${JSON.stringify(record)}` : ""} ${ - object ? `| object: ${JSON.stringify(object, null, 2)}` : "" + winston.format.printf(({ level, message, timestamp, user, record, meta }) => { + const hostnameColor = `\x1b[34m${hostname}\x1b[0m`; // Blue + const timestampColor = `\x1b[36m${timestamp}\x1b[0m`; // Cyan + const labelColor = "\x1b[33m"; // Yellow + const separatorColor = "\x1b[35m|\x1b[0m"; // Magenta for separators + + return `${timestampColor} [${hostnameColor}] [${level}]: ${message} ${ + user ? `${separatorColor} ${labelColor}user:\x1b[0m ${JSON.stringify(user)}` : "" + } ${record ? `${separatorColor} ${labelColor}record:\x1b[0m ${JSON.stringify(record)}` : ""}${ + meta + ? `\n${separatorColor} ${labelColor}meta:\x1b[0m ${JSON.stringify(meta, null, 2)} ${separatorColor}` + : "" }`; }) ) @@ -89,6 +112,7 @@ const createLogger = () => { message, user, record, + hostname, meta }); }; diff --git a/server/web-sockets/redisSocketEvents.js b/server/web-sockets/redisSocketEvents.js index a19953311..0e8a3a449 100644 --- a/server/web-sockets/redisSocketEvents.js +++ b/server/web-sockets/redisSocketEvents.js @@ -8,7 +8,6 @@ const redisSocketEvents = ({ }) => { // Logging helper functions const createLogEvent = (socket, level, message) => { - //console.log(`[IOREDIS LOG EVENT] - ${socket?.user?.email} - ${socket.id} - ${message}`); logger.log("ioredis-log-event", level, socket?.user?.email, null, { wsmessage: message }); }; @@ -33,7 +32,6 @@ const redisSocketEvents = ({ next(new Error("Authentication error - no authorization token.")); } } catch (error) { - //console.log("Uncaught connection error:::", error); logger.log("websocket-connection-error", "error", null, null, { ...error }); @@ -43,7 +41,7 @@ const redisSocketEvents = ({ // Register Socket Events const registerSocketEvents = (socket) => { - createLogEvent(socket, "DEBUG", `Registering RedisIO Socket Events.`); + createLogEvent(socket, "debug", `Registering RedisIO Socket Events.`); // Token Update Events const registerUpdateEvents = (socket) => { @@ -56,7 +54,7 @@ const redisSocketEvents = ({ // If We ever want to persist user Data across workers // await setSessionData(socket.id, "user", user); - createLogEvent(socket, "INFO", "Token updated successfully"); + createLogEvent(socket, "debug", "Token updated successfully"); socket.emit("token-updated", { success: true }); } catch (error) { @@ -67,7 +65,7 @@ const redisSocketEvents = ({ error: "Stale token." }); } else { - createLogEvent(socket, "ERROR", `Token update failed: ${error.message}`); + createLogEvent(socket, "error", `Token update failed: ${error.message}`); socket.emit("token-updated", { success: false, error: error.message }); // For any other errors, optionally disconnect the socket socket.disconnect(); @@ -82,9 +80,9 @@ const redisSocketEvents = ({ try { const room = getBodyshopRoom(bodyshopUUID); socket.join(room); - createLogEvent(socket, "DEBUG", `Client joined bodyshop room: ${room}`); + createLogEvent(socket, "debug", `Client joined bodyshop room: ${room}`); } catch (error) { - createLogEvent(socket, "ERROR", `Error joining room: ${error}`); + createLogEvent(socket, "error", `Error joining room: ${error}`); } }; @@ -92,9 +90,9 @@ const redisSocketEvents = ({ try { const room = getBodyshopRoom(bodyshopUUID); socket.leave(room); - createLogEvent(socket, "DEBUG", `Client left bodyshop room: ${room}`); + createLogEvent(socket, "debug", `Client left bodyshop room: ${room}`); } catch (error) { - createLogEvent(socket, "ERROR", `Error joining room: ${error}`); + createLogEvent(socket, "error", `Error joining room: ${error}`); } }; @@ -102,9 +100,10 @@ const redisSocketEvents = ({ try { const room = getBodyshopRoom(bodyshopUUID); io.to(room).emit("bodyshop-message", message); - createLogEvent(socket, "DEBUG", `Broadcast message to bodyshop ${room}`); + // We do not need this as these can be debugged live + // createLogEvent(socket, "debug", `Broadcast message to bodyshop ${room}`); } catch (error) { - createLogEvent(socket, "ERROR", `Error getting room: ${error}`); + createLogEvent(socket, "error", `Error getting room: ${error}`); } }; @@ -115,7 +114,7 @@ const redisSocketEvents = ({ // Disconnect Events const registerDisconnectEvents = (socket) => { const disconnect = () => { - createLogEvent(socket, "DEBUG", `User disconnected.`); + createLogEvent(socket, "debug", `User disconnected.`); const rooms = Array.from(socket.rooms).filter((room) => room !== socket.id); for (const room of rooms) { socket.leave(room);