mushcode-mcp-server
Version:
A specialized Model Context Protocol server for MUSHCODE development assistance. Provides AI-powered code generation, validation, optimization, and examples for MUD development.
299 lines • 8.91 kB
JavaScript
/**
* Comprehensive logging system for MUSHCODE MCP Server
* Provides structured logging with different levels and contexts
*/
export var LogLevel;
(function (LogLevel) {
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
LogLevel[LogLevel["INFO"] = 1] = "INFO";
LogLevel[LogLevel["WARN"] = 2] = "WARN";
LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
LogLevel[LogLevel["FATAL"] = 4] = "FATAL";
})(LogLevel || (LogLevel = {}));
/**
* Logger class with structured logging capabilities
*/
export class Logger {
static instance;
logLevel = LogLevel.INFO;
logEntries = [];
maxLogEntries = 1000;
constructor() {
// Set log level from environment variable
const envLogLevel = process.env['MUSHCODE_LOG_LEVEL']?.toLowerCase();
switch (envLogLevel) {
case 'debug':
this.logLevel = LogLevel.DEBUG;
break;
case 'info':
this.logLevel = LogLevel.INFO;
break;
case 'warn':
this.logLevel = LogLevel.WARN;
break;
case 'error':
this.logLevel = LogLevel.ERROR;
break;
case 'fatal':
this.logLevel = LogLevel.FATAL;
break;
default:
this.logLevel = LogLevel.INFO;
}
}
static getInstance() {
if (!Logger.instance) {
Logger.instance = new Logger();
}
return Logger.instance;
}
/**
* Set the minimum log level
*/
setLogLevel(level) {
this.logLevel = level;
}
/**
* Get current log level
*/
getLogLevel() {
return this.logLevel;
}
/**
* Log a debug message
*/
debug(message, context) {
this.log(LogLevel.DEBUG, message, context);
}
/**
* Log an info message
*/
info(message, context) {
this.log(LogLevel.INFO, message, context);
}
/**
* Log a warning message
*/
warn(message, context) {
this.log(LogLevel.WARN, message, context);
}
/**
* Log an error message
*/
error(message, error, context) {
const logEntry = {
timestamp: new Date().toISOString(),
level: LogLevel.ERROR,
message,
...(context && { context })
};
if (error) {
logEntry.error = {
name: error.name,
message: error.message,
...(error.stack && { stack: error.stack }),
...(error.code && { code: error.code })
};
}
this.addLogEntry(logEntry);
}
/**
* Log a fatal error message
*/
fatal(message, error, context) {
const logEntry = {
timestamp: new Date().toISOString(),
level: LogLevel.FATAL,
message,
...(context && { context })
};
if (error) {
logEntry.error = {
name: error.name,
message: error.message,
...(error.stack && { stack: error.stack }),
...(error.code && { code: error.code })
};
}
this.addLogEntry(logEntry);
}
/**
* Log performance metrics
*/
performance(operation, duration, context) {
const logEntry = {
timestamp: new Date().toISOString(),
level: LogLevel.INFO,
message: `Performance: ${operation} completed in ${duration}ms`,
...(context && { context }),
performance: {
duration,
operation
}
};
this.addLogEntry(logEntry);
}
/**
* Create a performance timer
*/
startTimer(operation, context) {
const startTime = Date.now();
return () => {
const duration = Date.now() - startTime;
this.performance(operation, duration, context);
};
}
/**
* Get recent log entries
*/
getRecentLogs(count = 100) {
return this.logEntries.slice(-count);
}
/**
* Get logs by level
*/
getLogsByLevel(level) {
return this.logEntries.filter(entry => entry.level === level);
}
/**
* Clear all log entries
*/
clearLogs() {
this.logEntries = [];
}
/**
* Get log statistics
*/
getLogStats() {
const stats = {
total: this.logEntries.length,
debug: 0,
info: 0,
warn: 0,
error: 0,
fatal: 0
};
for (const entry of this.logEntries) {
switch (entry.level) {
case LogLevel.DEBUG:
stats['debug'] = (stats['debug'] || 0) + 1;
break;
case LogLevel.INFO:
stats['info'] = (stats['info'] || 0) + 1;
break;
case LogLevel.WARN:
stats['warn'] = (stats['warn'] || 0) + 1;
break;
case LogLevel.ERROR:
stats['error'] = (stats['error'] || 0) + 1;
break;
case LogLevel.FATAL:
stats['fatal'] = (stats['fatal'] || 0) + 1;
break;
}
}
return stats;
}
/**
* Internal logging method
*/
log(level, message, context) {
if (level < this.logLevel) {
return;
}
const logEntry = {
timestamp: new Date().toISOString(),
level,
message,
...(context && { context })
};
this.addLogEntry(logEntry);
}
/**
* Add log entry and manage log rotation
*/
addLogEntry(entry) {
this.logEntries.push(entry);
// Rotate logs if we exceed max entries
if (this.logEntries.length > this.maxLogEntries) {
this.logEntries = this.logEntries.slice(-this.maxLogEntries);
}
// Output to console in development
if (process.env['NODE_ENV'] !== 'production') {
this.outputToConsole(entry);
}
}
/**
* Output log entry to console
*/
outputToConsole(entry) {
const levelName = LogLevel[entry.level];
const contextStr = entry.context ? ` [${JSON.stringify(entry.context)}]` : '';
const errorStr = entry.error ? ` Error: ${entry.error.message}` : '';
const perfStr = entry.performance ? ` (${entry.performance.duration}ms)` : '';
const logMessage = `[${entry.timestamp}] ${levelName}: ${entry.message}${contextStr}${errorStr}${perfStr}`;
switch (entry.level) {
case LogLevel.DEBUG:
console.debug(logMessage);
break;
case LogLevel.INFO:
console.info(logMessage);
break;
case LogLevel.WARN:
console.warn(logMessage);
break;
case LogLevel.ERROR:
case LogLevel.FATAL:
console.error(logMessage);
if (entry.error?.stack) {
console.error(entry.error.stack);
}
break;
}
}
}
/**
* Global logger instance
*/
export const logger = Logger.getInstance();
/**
* Decorator for logging method calls
*/
export function logMethodCall(target, propertyName, descriptor) {
const method = descriptor.value;
descriptor.value = function (...args) {
const className = target.constructor.name;
const methodName = propertyName;
const context = {
operation: `${className}.${methodName}`
};
logger.debug(`Calling ${className}.${methodName}`, context);
const timer = logger.startTimer(`${className}.${methodName}`, context);
try {
const result = method.apply(this, args);
// Handle async methods
if (result && typeof result.then === 'function') {
return result
.then((value) => {
timer();
logger.debug(`${className}.${methodName} completed successfully`, context);
return value;
})
.catch((error) => {
timer();
logger.error(`${className}.${methodName} failed`, error, context);
throw error;
});
}
timer();
logger.debug(`${className}.${methodName} completed successfully`, context);
return result;
}
catch (error) {
timer();
logger.error(`${className}.${methodName} failed`, error, context);
throw error;
}
};
}
//# sourceMappingURL=logger.js.map