import winston, { addColors } from "winston"; import path from "path"; /** * Destructures specific formats from the winston library for logging purposes. * @returns An object containing the destructured formats for logging. */ const { combine, timestamp, json, errors, colorize } = winston.format; const consoleFormat = winston.format.printf((info) => { /** * Formats log information into a string with timestamp, log level, metadata, message, and duration. * @param {object} info - The log information object containing timestamp, level, meta, message, and durationMs. * @returns {string} A formatted log message string. */ return `[${info.timestamp}][${info.level.toUpperCase()}](${info.meta}) ${info.message}${ info.durationMs ? ` Duration: ${info.durationMs}ms` : "" }`; }); const consoleTransport = new winston.transports.Console({ /** * Configures the format of the logs by combining timestamp, consoleFormat, and colorize options. * @param {Object} timestamp - The timestamp configuration object. * @param {Object} consoleFormat - The console format configuration object. * @param {Object} colorize - The colorize configuration object. * @returns None */ format: combine(timestamp({ format: "YY-MM-DD HH:mm:ss" }), consoleFormat, colorize({ all: true })), handleExceptions: true, }); /** * Configures a Winston logger with specified settings and transports for logging. * @param {string} logger - The name of the logger. * @param {object} options - The configuration options for the logger. * @param {string} options.level - The logging level for the logger. * @param {Array} options.transports - An array of transports for logging. * @param {Array} options.exceptionHandlers - An array of exception handlers for logging. * @param {Array} options.rejectionHandlers - An array of rejection handlers for logging. * @param {boolean} options.exitOnError - Determines if the process should exit on error. * @returns None */ winston.loggers.add("logger", { level: "debug", transports: [ consoleTransport, new winston.transports.File({ filename: "./logs/runtimeLog.json", format: combine(timestamp(), errors({ stack: true }), json()), tailable: true, maxsize: 1000000, //1mb handleExceptions: true, }), ], exceptionHandlers: [ //consoleTransport, new winston.transports.File({ filename: "./logs/exception.log" }), ], rejectionHandlers: [ //consoleTransport, new winston.transports.File({ filename: "./logs/rejections.log" }), ], exitOnError: false, }); const _getCallerFile = () => { /** * Generates a formatted string representing the file path and line number of the caller. * @returns {string} A string in the format "directory/filename:lineNumber" */ const err = new Error(); Error.prepareStackTrace = (_, stack) => stack; const stack = err.stack; Error.prepareStackTrace = undefined; const dir = path.dirname(stack[2].getFileName()).split("/").pop(); const filename = path.basename(stack[2].getFileName()).replace(".js", ""); return `${dir}/${filename}:${stack[2].getLineNumber()}`; }; /** * Retrieves the logger instance from Winston loggers. * @returns The logger instance for logging purposes. */ export const logger = winston.loggers.get("logger"); /** * Add color styles to different log levels for console output. * @param {Object} colors - An object containing color styles for different log levels. * Colors should be specified in the format "style color" (e.g. "bold red"). * Available styles: bold, italic * Available colors: black, red, green, yellow, blue, magenta, cyan, white * @returns None */ addColors({ info: "bold green", warn: "bold italic yellow", error: "bold red", debug: "magenta", }); /** * Set the exitOnError property of the logger to false. * This property determines whether the logger should exit the process when an error occurs. */ logger.exitOnError = false; /** * Logs a debug message along with metadata about the caller file. * @param {string} message - The message to be logged. * @returns None */ export const Debug = (message) => { logger.debug({ message, meta: _getCallerFile() }); }; /** * Logs a message using the logger with the caller file information. * @param {string} message - The message to be logged. * @returns None */ export const Log = (message) => { logger.info({ message, meta: _getCallerFile() }); }; /** * Logs a warning message along with metadata about the caller file. * @param {string} message - The warning message to be logged. * @returns None */ export const Warn = (message) => { logger.warn({ message, meta: _getCallerFile() }); }; /** * Logs an error message along with metadata about the caller file. * @param {string} message - The error message to be logged. * @returns None */ export const Err = (message) => { logger.error({ message, meta: _getCallerFile() }); }; /** * Marks the end of profiling and adds metadata about the caller file to the profiler message. * @param {Profiler} profiler - The profiler object used for profiling. * @param {object} message - The message object containing profiling data. * @returns None */ export const profilerDone = (profiler, message) => { profiler.done({ ...message, meta: _getCallerFile() }); };