UNPKG

@juspay/neurolink

Version:

Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and

201 lines (200 loc) 6.52 kB
/** * NeuroLink Unified Logger Utility * * Centralized logging for the entire NeuroLink ecosystem * Supports both CLI --debug flag and NEUROLINK_DEBUG environment variable * Migrated from MCP logging with enhanced features */ // Pre-computed uppercase log levels for performance optimization const UPPERCASE_LOG_LEVELS = { debug: "DEBUG", info: "INFO", warn: "WARN", error: "ERROR", }; class NeuroLinkLogger { logLevel = "info"; logs = []; maxLogs = 1000; isDebugMode; constructor() { // Cache debug mode check to avoid repeated array searches this.isDebugMode = process.argv.includes("--debug") || process.env.NEUROLINK_DEBUG === "true"; // Check NEUROLINK_LOG_LEVEL for consistency with the unified NeuroLink logger const envLevel = process.env.NEUROLINK_LOG_LEVEL?.toLowerCase(); if (envLevel && ["debug", "info", "warn", "error"].includes(envLevel)) { this.logLevel = envLevel; } } setLogLevel(level) { this.logLevel = level; } shouldLog(level) { // Dynamic debug mode check to handle CLI middleware timing const currentDebugMode = process.argv.includes("--debug") || process.env.NEUROLINK_DEBUG === "true"; // Hide all logs except errors unless debugging if (!currentDebugMode && level !== "error") { return false; } const levels = ["debug", "info", "warn", "error"]; return levels.indexOf(level) >= levels.indexOf(this.logLevel); } getLogPrefix(timestamp, level) { return `[${timestamp}] [NEUROLINK:${UPPERCASE_LOG_LEVELS[level]}]`; } /** * Outputs a log entry to the console based on the log level. * * @param level - The log level (debug, info, warn, error). * @param prefix - The formatted log prefix. * @param message - The log message. * @param data - Optional additional data to log. */ outputToConsole(level, prefix, message, data) { const logMethod = { debug: console.debug, info: console.info, warn: console.warn, error: console.error, }[level]; if (data !== undefined && data !== null) { logMethod(prefix, message, data); } else { logMethod(prefix, message); } } log(level, message, data) { if (!this.shouldLog(level)) { return; } const entry = { level, message, timestamp: new Date(), data, }; // Store log entry this.logs.push(entry); // Trim old logs if (this.logs.length > this.maxLogs) { this.logs = this.logs.slice(-this.maxLogs); } // Console output const timestamp = entry.timestamp.toISOString(); const prefix = this.getLogPrefix(timestamp, level); this.outputToConsole(level, prefix, message, data); } debug(message, data) { this.log("debug", message, data); } info(message, data) { this.log("info", message, data); } warn(message, data) { this.log("warn", message, data); } error(message, data) { this.log("error", message, data); } getLogs(level) { if (level) { return this.logs.filter((log) => log.level === level); } return [...this.logs]; } clearLogs() { this.logs = []; } /** * Logs messages unconditionally using `console.log`. * * This method is part of a legacy simple logger interface for backward compatibility. * It bypasses the structured logging mechanism and should only be used when * unstructured, unconditional logging is required. * * @param args - The arguments to log. These are passed directly to `console.log`. */ always(...args) { console.log(...args); } /** * Displays tabular data unconditionally using `console.table`. * * @param data - The data to display in table format */ table(data) { console.table(data); } } // Export singleton instance const neuroLinkLogger = new NeuroLinkLogger(); // Helper function to process arguments with minimal overhead function processLoggerArgs(args, logMethod) { if (args.length === 0) { return; } // Serialize the first argument robustly to handle complex objects const message = (() => { try { return typeof args[0] === "string" ? args[0] : JSON.stringify(args[0]); } catch { return "[Unserializable Object]"; } })(); const data = args.length === 2 ? args[1] : args.length > 2 ? args.slice(1) : undefined; logMethod(message, data); } // Main unified logger export export const logger = { debug: (...args) => { if (neuroLinkLogger.shouldLog("debug")) { processLoggerArgs(args, (message, data) => neuroLinkLogger.debug(message, data)); } }, info: (...args) => { if (neuroLinkLogger.shouldLog("info")) { processLoggerArgs(args, (message, data) => neuroLinkLogger.info(message, data)); } }, warn: (...args) => { if (neuroLinkLogger.shouldLog("warn")) { processLoggerArgs(args, (message, data) => neuroLinkLogger.warn(message, data)); } }, error: (...args) => { if (neuroLinkLogger.shouldLog("error")) { processLoggerArgs(args, (message, data) => neuroLinkLogger.error(message, data)); } }, always: (...args) => { neuroLinkLogger.always(...args); }, table: (data) => { neuroLinkLogger.table(data); }, // Expose structured logging methods setLogLevel: (level) => neuroLinkLogger.setLogLevel(level), getLogs: (level) => neuroLinkLogger.getLogs(level), clearLogs: () => neuroLinkLogger.clearLogs(), }; // MCP compatibility exports - all use the same unified logger export const mcpLogger = neuroLinkLogger; export const autoDiscoveryLogger = neuroLinkLogger; export const registryLogger = neuroLinkLogger; export const unifiedRegistryLogger = neuroLinkLogger; // Global log level setter export function setGlobalMCPLogLevel(level) { neuroLinkLogger.setLogLevel(level); } // Export LogLevel enum for runtime use export const LogLevels = { debug: "debug", info: "info", warn: "warn", error: "error", };