@spaik/mcp-server-roi
Version:
MCP server for AI ROI prediction and tracking with Monte Carlo simulations
144 lines • 5.31 kB
JavaScript
export var LogLevel;
(function (LogLevel) {
LogLevel[LogLevel["ERROR"] = 0] = "ERROR";
LogLevel[LogLevel["WARN"] = 1] = "WARN";
LogLevel[LogLevel["INFO"] = 2] = "INFO";
LogLevel[LogLevel["DEBUG"] = 3] = "DEBUG";
LogLevel[LogLevel["TRACE"] = 4] = "TRACE";
})(LogLevel || (LogLevel = {}));
class Logger {
static instance;
logLevel;
isProduction;
constructor() {
this.logLevel = this.parseLogLevel(process.env.LOG_LEVEL || 'INFO');
this.isProduction = process.env.NODE_ENV === 'production';
}
static getInstance() {
if (!Logger.instance) {
Logger.instance = new Logger();
}
return Logger.instance;
}
parseLogLevel(level) {
switch (level.toUpperCase()) {
case 'ERROR': return LogLevel.ERROR;
case 'WARN': return LogLevel.WARN;
case 'INFO': return LogLevel.INFO;
case 'DEBUG': return LogLevel.DEBUG;
case 'TRACE': return LogLevel.TRACE;
default: return LogLevel.INFO;
}
}
shouldLog(level) {
return level <= this.logLevel;
}
formatMessage(entry) {
const levelStr = LogLevel[entry.level].padEnd(5);
if (this.isProduction) {
// Structured JSON logging for production
return JSON.stringify({
timestamp: entry.timestamp,
level: LogLevel[entry.level],
message: entry.message,
...(entry.context && { context: entry.context }),
...(entry.error && {
error: {
name: entry.error.name,
message: entry.error.message,
stack: entry.error.stack
}
})
});
}
else {
// Human-readable format for development
let output = `[${entry.timestamp}] ${levelStr} ${entry.message}`;
if (entry.context && Object.keys(entry.context).length > 0) {
output += ` | ${JSON.stringify(entry.context)}`;
}
if (entry.error) {
output += `\n Error: ${entry.error.message}`;
if (entry.error.stack) {
output += `\n Stack: ${entry.error.stack}`;
}
}
return output;
}
}
log(level, message, context, error) {
if (!this.shouldLog(level))
return;
const entry = {
timestamp: new Date().toISOString(),
level,
message,
context,
error
};
const formattedMessage = this.formatMessage(entry);
// Write to stderr to avoid mixing with MCP protocol messages on stdout
console.error(formattedMessage);
}
error(message, error, context) {
this.log(LogLevel.ERROR, message, context, error);
}
warn(message, context) {
this.log(LogLevel.WARN, message, context);
}
info(message, context) {
this.log(LogLevel.INFO, message, context);
}
debug(message, context) {
this.log(LogLevel.DEBUG, message, context);
}
trace(message, context) {
this.log(LogLevel.TRACE, message, context);
}
// Helper method for timing operations
time(label) {
const start = Date.now();
this.debug(`Timer started: ${label}`);
return () => {
const duration = Date.now() - start;
this.debug(`Timer completed: ${label}`, { duration_ms: duration });
};
}
// Helper method for logging method entry/exit
methodEntry(className, methodName, args) {
this.trace(`Entering ${className}.${methodName}`, { args });
}
methodExit(className, methodName, result) {
this.trace(`Exiting ${className}.${methodName}`, { result });
}
// Helper method for logging async operations
async asyncOperation(operationName, operation, context) {
const endTimer = this.time(operationName);
this.debug(`Starting async operation: ${operationName}`, context);
try {
const result = await operation();
this.debug(`Completed async operation: ${operationName}`, { ...context, success: true });
return result;
}
catch (error) {
this.error(`Failed async operation: ${operationName}`, error, context);
throw error;
}
finally {
endTimer();
}
}
}
// Export singleton instance
export const logger = Logger.getInstance();
// Export helper function for child loggers with context
export function createLogger(context) {
return {
error: (message, error, additionalContext) => logger.error(message, error, { ...context, ...additionalContext }),
warn: (message, additionalContext) => logger.warn(message, { ...context, ...additionalContext }),
info: (message, additionalContext) => logger.info(message, { ...context, ...additionalContext }),
debug: (message, additionalContext) => logger.debug(message, { ...context, ...additionalContext }),
trace: (message, additionalContext) => logger.trace(message, { ...context, ...additionalContext })
};
}
//# sourceMappingURL=logger.js.map