Skip to main content
Glama
sascodiego

MCP Vibe Coding Knowledge Graph

by sascodiego
logger.js4.25 kB
import winston from 'winston'; import path from 'path'; import fs from 'fs'; // Ensure logs directory exists const logsDir = './logs'; if (!fs.existsSync(logsDir)) { fs.mkdirSync(logsDir, { recursive: true }); } // Custom format for production logging const productionFormat = winston.format.combine( winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }), winston.format.errors({ stack: true }), winston.format.metadata({ fillExcept: ['message', 'level', 'timestamp'] }), winston.format.json() ); // Development format for console readability const developmentFormat = winston.format.combine( winston.format.timestamp({ format: 'HH:mm:ss.SSS' }), winston.format.errors({ stack: true }), winston.format.colorize(), winston.format.printf(({ timestamp, level, message, metadata, ...meta }) => { let metaStr = ''; if (metadata && Object.keys(metadata).length > 0) { metaStr = ` ${JSON.stringify(metadata)}`; } if (Object.keys(meta).length > 0) { metaStr += ` ${JSON.stringify(meta)}`; } return `${timestamp} [${level}]: ${message}${metaStr}`; }) ); // Create logger instance export const logger = winston.createLogger({ level: process.env.LOG_LEVEL || 'info', defaultMeta: { service: 'mcp-vibe-coding-kg', version: process.env.npm_package_version || '1.0.0', environment: process.env.NODE_ENV || 'development' }, transports: [ // Error log file (errors only) new winston.transports.File({ filename: path.join(logsDir, 'error.log'), level: 'error', format: productionFormat, maxsize: 10 * 1024 * 1024, // 10MB maxFiles: 5, tailable: true }), // Combined log file (all levels) new winston.transports.File({ filename: path.join(logsDir, 'combined.log'), format: productionFormat, maxsize: 50 * 1024 * 1024, // 50MB maxFiles: 10, tailable: true }), // Query log file (debug level, separate for performance analysis) new winston.transports.File({ filename: path.join(logsDir, 'queries.log'), level: 'debug', format: productionFormat, maxsize: 25 * 1024 * 1024, // 25MB maxFiles: 3 }) ], // Handle uncaught exceptions exceptionHandlers: [ new winston.transports.File({ filename: path.join(logsDir, 'exceptions.log'), format: productionFormat }) ], // Handle unhandled promise rejections rejectionHandlers: [ new winston.transports.File({ filename: path.join(logsDir, 'rejections.log'), format: productionFormat }) ] }); // Add console transport for development if (process.env.NODE_ENV !== 'production') { logger.add( new winston.transports.Console({ format: developmentFormat, level: process.env.LOG_LEVEL || 'debug' }) ); } // Add request logging method logger.logRequest = (req, res, duration) => { logger.info('HTTP Request', { method: req.method, url: req.url, statusCode: res.statusCode, duration: `${duration}ms`, userAgent: req.get('User-Agent'), ip: req.ip || req.connection.remoteAddress }); }; // Add query logging method logger.logQuery = (query, params, duration, success = true) => { logger.debug('Database Query', { query: query.substring(0, 200) + (query.length > 200 ? '...' : ''), params, duration: `${duration}ms`, success, timestamp: new Date().toISOString() }); }; // Add performance logging method logger.logPerformance = (operation, duration, metadata = {}) => { const level = duration > 5000 ? 'warn' : duration > 1000 ? 'info' : 'debug'; logger.log(level, `Performance: ${operation}`, { duration: `${duration}ms`, ...metadata }); }; // Add security logging method logger.logSecurity = (event, details = {}) => { logger.warn('Security Event', { event, timestamp: new Date().toISOString(), ...details }); }; // Utility function to create child logger with additional context logger.child = (metadata) => { return logger.child(metadata); }; export default logger;

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/sascodiego/KGsMCP'

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