Skip to main content
Glama
logger.ts3.38 kB
/** * Singleton logger instance for the MCP Server * Provides file and console logging using Winston */ import { createLogger, format, transports, Logger as WinstonLogger } from 'winston'; import { mkdirSync, existsSync } from 'fs'; import { dirname } from 'path'; class LoggerService { private logger: WinstonLogger | null = null; private isInitialized = false; private enableDebugConsole = false; /** * Initialize the logger with configuration * Must be called before using logger methods */ initialize(options: { level: string; logFileName: string; enableConsole: boolean; enableDebugConsole: boolean; }): void { if (this.isInitialized) { return; } this.enableDebugConsole = options.enableDebugConsole; const logDir = dirname(options.logFileName); if (!existsSync(logDir)) { mkdirSync(logDir, { recursive: true }); } const fileTransport = new transports.File({ filename: options.logFileName, level: options.level, maxsize: 10 * 1024 * 1024, // 10MB maxFiles: 5, tailable: true, }); const consoleTransport = new transports.Console({ format: format.combine( format.timestamp(), format((info) => { // Filter out debug logs if DEBUG=false if (info.isDebug && !this.enableDebugConsole) { return false; } return info; })(), format.json() ), }); this.logger = createLogger({ level: options.level, format: format.combine( format.timestamp(), format.json() ), transports: [ fileTransport, ...(options.enableConsole ? [consoleTransport] : []), ], }); this.isInitialized = true; } /** * Get the logger instance * Throws error if not initialized */ getLogger(): WinstonLogger { if (!this.logger) { throw new Error('Logger not initialized. Call logger.initialize() first.'); } return this.logger; } /** * Log info message (always to console + file) */ info(message: string, meta?: Record<string, unknown>): void { if (!this.logger) { throw new Error('Logger not initialized. Call logger.initialize() first.'); } this.logger.info(message, meta); } /** * Log warning message (always to console + file) */ warn(message: string, meta?: Record<string, unknown>): void { if (!this.logger) { throw new Error('Logger not initialized. Call logger.initialize() first.'); } this.logger.warn(message, meta); } /** * Log error message (always to console + file) */ error(message: string, meta?: Record<string, unknown>): void { if (!this.logger) { throw new Error('Logger not initialized. Call logger.initialize() first.'); } this.logger.error(message, meta); } /** * Log debug message (file always, console controlled by DEBUG env var) */ debug(message: string, meta?: Record<string, unknown>): void { if (!this.logger) { throw new Error('Logger not initialized. Call logger.initialize() first.'); } this.logger.info(message, { ...meta, isDebug: true }); } /** * Check if logger is initialized */ isReady(): boolean { return this.isInitialized; } } // Export as singleton instance export const logger = new LoggerService();

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/masseater/gemini-rag-mcp'

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