Skip to main content
Glama

Gradle Tomcat MCP Server

by lkb2k
log-manager.js4.21 kB
import fs from 'fs'; import path from 'path'; export class LogManager { constructor(config) { this.config = config; this.logBuffer = []; this.maxBufferSize = config.maxLogBufferSize || 1000; this.logDir = config.logDir || './logs'; this.ensureLogDirectory(); } ensureLogDirectory() { if (!fs.existsSync(this.logDir)) { fs.mkdirSync(this.logDir, { recursive: true }); } } addLogEntry(source, message, level = 'INFO') { const timestamp = new Date().toISOString(); const logEntry = { timestamp, level: this.inferLogLevel(message, level), source, message: message.trim(), thread: this.extractThread(message) }; this.logBuffer.push(logEntry); if (this.logBuffer.length > this.maxBufferSize) { this.logBuffer.shift(); } this.writeToFile(logEntry); return logEntry; } inferLogLevel(message, defaultLevel = 'INFO') { const upperMessage = message.toUpperCase(); if (upperMessage.includes('ERROR') || upperMessage.includes('EXCEPTION') || upperMessage.includes('FAILED')) { return 'ERROR'; } else if (upperMessage.includes('WARN')) { return 'WARN'; } else if (upperMessage.includes('DEBUG')) { return 'DEBUG'; } else if (upperMessage.includes('INFO') || upperMessage.includes('STARTED') || upperMessage.includes('COMPLETED')) { return 'INFO'; } return defaultLevel; } extractThread(message) { const threadMatch = message.match(/\[([^\]]+)\]/); return threadMatch ? threadMatch[1] : null; } writeToFile(logEntry) { try { const logFile = path.join(this.logDir, `tomcat-${new Date().toISOString().split('T')[0]}.log`); const logLine = `${logEntry.timestamp} [${logEntry.level}] ${logEntry.source}: ${logEntry.message}\n`; fs.appendFileSync(logFile, logLine); } catch (error) { console.error('Failed to write log to file:', error); } } getLogs(options = {}) { const { lines = 100, level = null, since = null, source = null } = options; let filteredLogs = [...this.logBuffer]; if (level) { const levelPriority = { 'DEBUG': 0, 'INFO': 1, 'WARN': 2, 'ERROR': 3 }; const minPriority = levelPriority[level.toUpperCase()] || 0; filteredLogs = filteredLogs.filter(log => (levelPriority[log.level] || 0) >= minPriority ); } if (since) { const sinceDate = new Date(since); filteredLogs = filteredLogs.filter(log => new Date(log.timestamp) >= sinceDate ); } if (source) { filteredLogs = filteredLogs.filter(log => log.source === source ); } return filteredLogs.slice(-lines); } getRecentLogs(count = 50) { return this.logBuffer.slice(-count); } clearLogs() { this.logBuffer = []; try { const files = fs.readdirSync(this.logDir); for (const file of files) { if (file.endsWith('.log')) { fs.unlinkSync(path.join(this.logDir, file)); } } return { success: true, message: 'Logs cleared successfully' }; } catch (error) { return { success: false, message: `Failed to clear log files: ${error.message}` }; } } getLogStats() { const stats = { bufferSize: this.logBuffer.length, maxBufferSize: this.maxBufferSize, levelCounts: { DEBUG: 0, INFO: 0, WARN: 0, ERROR: 0 }, sourceCounts: { stdout: 0, stderr: 0 } }; for (const log of this.logBuffer) { stats.levelCounts[log.level] = (stats.levelCounts[log.level] || 0) + 1; stats.sourceCounts[log.source] = (stats.sourceCounts[log.source] || 0) + 1; } return stats; } tailLogs(callback, options = {}) { const { lines = 10 } = options; const initialLogs = this.getRecentLogs(lines); callback(initialLogs); const originalAddLogEntry = this.addLogEntry.bind(this); this.addLogEntry = (source, message, level) => { const logEntry = originalAddLogEntry(source, message, level); callback([logEntry]); return logEntry; }; return () => { this.addLogEntry = originalAddLogEntry; }; } }

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/lkb2k/mcp-gradle'

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