UNPKG

@codai/romai-mcp

Version:

ROMAI Ultimate MCP Server - All-in-One Enterprise Solution with 26+ Integrated Tools

222 lines (220 loc) 6.66 kB
import { randomUUID } from 'crypto'; // src/logging/enterprise-logger.ts var EnterpriseLogger = class _EnterpriseLogger { static instance; metrics = []; auditTrail = []; constructor() { } static getInstance() { if (!_EnterpriseLogger.instance) { _EnterpriseLogger.instance = new _EnterpriseLogger(); } return _EnterpriseLogger.instance; } /** * Create a new request context with correlation ID */ createRequestContext(method, userId, organizationId) { return { requestId: randomUUID(), userId, organizationId, method, timestamp: (/* @__PURE__ */ new Date()).toISOString(), source: "mcp-server", version: "0.2.0" }; } /** * Log MCP request with structured data */ logRequest(context, params) { const logEntry = { level: "info", ...context, type: "mcp_request", params: this.sanitizeParams(params), message: `MCP Request: ${context.method}` }; console.log(JSON.stringify(logEntry)); this.recordAuditEvent({ eventId: randomUUID(), eventType: "request", severity: "info", details: { params }, context }); } /** * Log MCP response with performance metrics */ logResponse(context, result, duration) { const logEntry = { level: "info", ...context, type: "mcp_response", result: this.sanitizeResult(result), duration_ms: duration, message: `MCP Response: ${context.method} (${duration}ms)` }; console.log(JSON.stringify(logEntry)); this.recordMetric({ name: "mcp_request_duration", value: duration, unit: "ms", labels: { method: context.method, userId: context.userId || "anonymous", organizationId: context.organizationId || "default" }, timestamp: (/* @__PURE__ */ new Date()).toISOString() }); this.recordAuditEvent({ eventId: randomUUID(), eventType: "response", severity: "info", details: { duration, success: true }, context }); } /** * Log error with full context and stack trace */ logError(context, error, details) { const logEntry = { level: "error", ...context, type: "mcp_error", error: { name: error.name, message: error.message, stack: error.stack }, details: details || {}, message: `MCP Error: ${context.method} - ${error.message}` }; console.error(JSON.stringify(logEntry)); this.recordMetric({ name: "mcp_request_errors", value: 1, unit: "count", labels: { method: context.method, errorType: error.name, userId: context.userId || "anonymous", organizationId: context.organizationId || "default" }, timestamp: (/* @__PURE__ */ new Date()).toISOString() }); this.recordAuditEvent({ eventId: randomUUID(), eventType: "error", severity: "error", details: { error: error.message, stack: error.stack, ...details }, context }); } /** * Record performance metric for analytics */ recordMetric(metric) { this.metrics.push(metric); if (this.metrics.length > 1e3) { this.metrics = this.metrics.slice(-1e3); } } /** * Record audit event for compliance */ recordAuditEvent(event) { this.auditTrail.push(event); if (this.auditTrail.length > 500) { this.auditTrail = this.auditTrail.slice(-500); } } /** * Get performance analytics */ getAnalytics(timeWindow = 36e5) { const cutoff = new Date(Date.now() - timeWindow); const recentMetrics = this.metrics.filter((m) => new Date(m.timestamp) > cutoff); const requestMetrics = recentMetrics.filter((m) => m.name === "mcp_request_duration"); const errorMetrics = recentMetrics.filter((m) => m.name === "mcp_request_errors"); const methodCounts = requestMetrics.reduce((acc, metric) => { const method = metric.labels.method; acc[method] = (acc[method] || 0) + 1; return acc; }, {}); const topMethods = Object.entries(methodCounts).map(([method, count]) => ({ method, count })).sort((a, b) => b.count - a.count).slice(0, 5); return { requestCount: requestMetrics.length, averageResponseTime: requestMetrics.length > 0 ? requestMetrics.reduce((sum, m) => sum + m.value, 0) / requestMetrics.length : 0, errorRate: requestMetrics.length > 0 ? errorMetrics.length / requestMetrics.length * 100 : 0, topMethods, performanceMetrics: recentMetrics }; } /** * Get audit trail for compliance */ getAuditTrail(timeWindow = 36e5) { const cutoff = new Date(Date.now() - timeWindow); return this.auditTrail.filter((event) => new Date(event.context.timestamp) > cutoff); } /** * Generate compliance report */ generateComplianceReport() { const last24h = 24 * 60 * 60 * 1e3; const recentEvents = this.getAuditTrail(last24h); const totalRequests = recentEvents.filter((e) => e.eventType === "request").length; const authenticatedRequests = recentEvents.filter( (e) => e.eventType === "request" && e.context.userId ).length; const errorEvents = recentEvents.filter((e) => e.eventType === "error").length; const criticalEvents = recentEvents.filter((e) => e.severity === "critical").length; return { totalRequests, authenticatedRequests, errorEvents, criticalEvents, dataIntegrity: true, // Enhanced validation in production auditCoverage: totalRequests > 0 ? recentEvents.length / totalRequests * 100 : 100 }; } /** * Sanitize sensitive data from parameters */ sanitizeParams(params) { if (!params || typeof params !== "object") return params; const sanitized = { ...params }; const sensitiveFields = ["password", "token", "key", "secret", "apiKey"]; for (const field of sensitiveFields) { if (sanitized[field]) { sanitized[field] = "[REDACTED]"; } } return sanitized; } /** * Sanitize sensitive data from results */ sanitizeResult(result) { if (!result || typeof result !== "object") return result; const resultStr = JSON.stringify(result); if (resultStr.length > 1e3) { return { _truncated: true, _size: resultStr.length, preview: resultStr.substring(0, 200) + "..." }; } return result; } }; var enterpriseLogger = EnterpriseLogger.getInstance(); export { EnterpriseLogger, enterpriseLogger }; //# sourceMappingURL=enterprise-logger.js.map //# sourceMappingURL=enterprise-logger.js.map