@codai/romai-mcp
Version:
ROMAI Ultimate MCP Server - All-in-One Enterprise Solution with 26+ Integrated Tools
222 lines (220 loc) • 6.66 kB
JavaScript
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