@memory-bank/mcp
Version:
Memory-enabled Co-Pilot (MCP) server for managing project documentation and context
163 lines • 6.29 kB
JavaScript
/**
* Unified Logger utility
*
* Provides a consistent logging interface with structured context support
* This is the recommended logging implementation for all application components
*/
/**
* Log level priorities for filtering
*/
export const LOG_LEVEL_PRIORITY = {
debug: 0,
info: 1,
warn: 2,
error: 3,
};
/**
* Create a console logger
* @param level Minimum log level to display
* @returns Logger instance
*/
// Allow passing initial default context
export function createConsoleLogger(level = 'info', initialDefaultContext) {
let currentLevel = level;
let defaultContext = initialDefaultContext || {}; // Use initial context if provided
/**
* Check if a log level should be displayed
* @param msgLevel Level of the message
* @returns Whether the message should be logged
*/
function shouldLog(msgLevel) {
return LOG_LEVEL_PRIORITY[msgLevel] >= LOG_LEVEL_PRIORITY[currentLevel];
}
/**
* Format the log entry with level prefix and timestamp
*/
// Removed: formatLogEntry as we now output JSON
/**
* Prepare context with defaults and auto-populated fields
*/
function prepareContext(context) {
const timestamp = new Date().toISOString();
return {
...defaultContext,
...context,
timestamp: context?.timestamp || timestamp
};
}
const logger = {
debug(message, ...args) {
if (shouldLog('debug')) {
let context = {};
if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null && !Array.isArray(args[0])) {
context = args[0];
}
else if (args.length > 0) {
// Treat multiple arguments as an array in the context
context = { args };
}
const logEntry = { level: 'debug', message, ...prepareContext(context) };
// Output JSON string to stderr to avoid interfering with MCP communication
console.error(JSON.stringify(logEntry));
}
},
info(message, ...args) {
if (shouldLog('info')) {
let context = {};
if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null && !Array.isArray(args[0])) {
context = args[0];
}
else if (args.length > 0) {
context = { args };
}
const logEntry = { level: 'info', message, ...prepareContext(context) };
// Output JSON string to stderr to avoid interfering with MCP communication
console.error(JSON.stringify(logEntry));
}
},
warn(message, ...args) {
if (shouldLog('warn')) {
let context = {};
if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null && !Array.isArray(args[0])) {
context = args[0];
}
else if (args.length > 0) {
context = { args };
}
const logEntry = { level: 'warn', message, ...prepareContext(context) };
// Output JSON string to stderr to avoid interfering with MCP communication
console.error(JSON.stringify(logEntry));
}
},
error(message, ...args) {
if (shouldLog('error')) {
let context = {};
// Ensure error details are captured correctly in context
const errorArg = args.find(arg => arg instanceof Error);
if (errorArg) {
context.error = {
message: errorArg.message,
stack: errorArg.stack,
name: errorArg.name,
};
// Filter out the error object from args if it exists
args = args.filter(arg => arg !== errorArg);
}
if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null && !Array.isArray(args[0])) {
// Merge remaining args[0] if it's an object context
context = { ...context, ...args[0] };
}
else if (args.length > 0) {
// Add remaining args if any
context.args = args;
}
const logEntry = { level: 'error', message, ...prepareContext(context) };
// Output JSON string to stderr to avoid interfering with MCP communication
console.error(JSON.stringify(logEntry));
}
},
log(level, message, ...args) {
switch (level) {
case 'debug':
this.debug(message, ...args);
break;
case 'info':
this.info(message, ...args);
break;
case 'warn':
this.warn(message, ...args);
break;
case 'error':
this.error(message, ...args);
break;
}
},
setLevel(level) {
currentLevel = level;
},
getLevel() {
return currentLevel;
},
withContext(context) {
// Create child logger passing the combined context
const combinedContext = { ...defaultContext, ...context };
const childLogger = createConsoleLogger(currentLevel, combinedContext);
return childLogger;
}
};
// Remove the Object.defineProperty for _defaultContext as it's handled internally now
return logger;
}
/**
* Default logger instance configured with warn level
* Use this for direct imports across the application
* For component-specific logging, create a contextualized logger with withContext
*
* Example:
* ```
* const componentLogger = logger.withContext({ component: 'UserRepository' });
* componentLogger.info('User data retrieved', { userId: 123 });
* ```
*/
export const logger = createConsoleLogger('error');
//# sourceMappingURL=logger.js.map