n1cat-discord-script-manager
Version:
A Discord.js plugin for dynamic script management and execution
131 lines (117 loc) • 3.62 kB
JavaScript
/**
* Centralized Logger Utility
* Provides consistent logging across the application
*/
const moment = require("moment");
class Logger {
/**
* Get caller information from the stack trace
* @returns {Object} Caller information
*/
static getCallerInfo() {
const stack = new Error().stack;
const callerLine = stack.split("\n")[3];
const match = callerLine.match(/at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)/);
if (match) {
const [, functionName, file, line, column] = match;
return {
function: functionName,
file: file.split(/[/\\]/).pop(),
line,
column,
};
}
return {
function: "unknown",
file: "unknown",
line: "unknown",
column: "unknown",
};
}
/**
* Format log message with color and context
* @param {string} message - Log message
* @param {Object} caller - Caller information
* @param {boolean} isError - Whether it's an error message
* @returns {string} Formatted log message
*/
static formatMessage(message, caller, isError = false) {
const timestamp = moment().format("YYYY-MM-DD HH:mm:ss.SSS");
let chalk;
try {
chalk = require("chalk");
} catch {
// Fallback to no-op coloring if chalk is not available
chalk = {
yellow: (text) => text,
red: (text) => text,
blue: (text) => text,
gray: (text) => text,
cyan: (text) => text,
};
}
return `${chalk.yellow(timestamp)} ${
isError ? chalk.red("ERROR") : chalk.blue("INFO")
} ${chalk.gray(`[${caller.file}:${caller.line}]`)} ${chalk.cyan(
`(${caller.function})`
)} ${isError ? chalk.red(message) : message}`;
}
/**
* Log messages with optional error handling
* @param {string} message - Message to log
* @param {boolean} [isError=false] - Whether it's an error message
* @param {Object} [options={}] - Additional logging options
*/
static log(message, isError = false, options = {}) {
const caller = this.getCallerInfo();
const debugMode = options.debug ?? false;
if (isError || debugMode) {
const formattedMessage = this.formatMessage(message, caller, isError);
const logMethod = isError ? console.error : console.log;
logMethod(formattedMessage);
// Optional stack trace for errors
if (isError && options.showStack) {
let chalk;
try {
chalk = require("chalk");
} catch {
chalk = {
red: (text) => text,
};
}
console.error(chalk.red("Stack Trace:"));
console.error(new Error().stack);
}
}
}
/**
* Create a logger instance with context
* @param {Object} context - Logging context
* @returns {Object} Logger with context
*/
static createContextLogger(context) {
return {
log: (message, isError) => this.log(message, isError, { ...context }),
error: (message, options = {}) =>
this.log(message, true, {
...context,
showStack: options.showStack ?? true,
}),
debug: (message) => this.log(message, false, { ...context, debug: true }),
};
}
/**
* Performance logging with timing
* @param {string} message - Log message
* @param {Function} fn - Function to measure
* @returns {any} Result of the function
*/
static performance(message, fn) {
const start = Date.now();
const result = fn();
const duration = Date.now() - start;
this.log(`${message} (${duration}ms)`, false, { debug: true });
return result;
}
}
module.exports = Logger;