Skip to main content
Glama
logger.js3.42 kB
/** * Logger module - First-class logging as per design guidelines * Implements configurable logging levels with no third-party dependencies */ const LOG_LEVELS = { ERROR: 0, WARN: 1, INFO: 2, DEBUG: 3, TRACE: 4, }; const LOG_COLORS = { ERROR: '\x1b[31m', // Red WARN: '\x1b[33m', // Yellow INFO: '\x1b[36m', // Cyan DEBUG: '\x1b[90m', // Gray TRACE: '\x1b[35m', // Magenta RESET: '\x1b[0m', }; class Logger { constructor(module = 'MongTap', options = {}) { this.module = module; this.level = options.level || process.env.LOG_LEVEL || 'INFO'; this.enabled = options.enabled !== false; this.useColors = options.colors !== false && process.stdout.isTTY; this.logToFile = options.file || null; this.timestamps = options.timestamps !== false; } setLevel(level) { if (LOG_LEVELS[level] !== undefined) { this.level = level; } } enable() { this.enabled = true; } disable() { this.enabled = false; } _shouldLog(level) { return this.enabled && LOG_LEVELS[level] <= LOG_LEVELS[this.level]; } _formatMessage(level, message, meta) { const timestamp = this.timestamps ? new Date().toISOString() : ''; const levelStr = level.padEnd(5); const moduleStr = `[${this.module}]`; let formatted = ''; if (this.useColors) { formatted = `${LOG_COLORS[level]}${levelStr}${LOG_COLORS.RESET}`; } else { formatted = levelStr; } if (timestamp) { formatted = `${timestamp} ${formatted}`; } formatted += ` ${moduleStr} ${message}`; if (meta && Object.keys(meta).length > 0) { formatted += ` ${JSON.stringify(meta)}`; } return formatted; } _log(level, message, meta) { if (!this._shouldLog(level)) { return; } const formatted = this._formatMessage(level, message, meta); // Output to console if (level === 'ERROR') { console.error(formatted); } else if (level === 'WARN') { console.warn(formatted); } else { console.error(formatted); } // TODO: Add file logging when needed if (this.logToFile) { // Will implement file logging without third-party dependencies } } error(message, meta) { this._log('ERROR', message, meta); } warn(message, meta) { this._log('WARN', message, meta); } info(message, meta) { this._log('INFO', message, meta); } debug(message, meta) { this._log('DEBUG', message, meta); } trace(message, meta) { this._log('TRACE', message, meta); } // Create a child logger with a specific module name child(module) { return new Logger(`${this.module}:${module}`, { level: this.level, enabled: this.enabled, colors: this.useColors, file: this.logToFile, timestamps: this.timestamps, }); } // Performance logging helper startTimer(label) { const start = process.hrtime.bigint(); return { end: (message, meta = {}) => { const end = process.hrtime.bigint(); const duration = Number(end - start) / 1000000; // Convert to milliseconds this.debug(`${message} (${duration.toFixed(2)}ms)`, { ...meta, duration }); }, }; } } // Create singleton instance for default export const defaultLogger = new Logger(); // Export both the class and default instance export { Logger, defaultLogger as default };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/smallmindsco/MongTap'

If you have feedback or need assistance with the MCP directory API, please join our Discord server