UNPKG

optivise

Version:

Optivise - The Ultimate Optimizely Development Assistant with AI-powered features, zero-config setup, and comprehensive development support

108 lines 3.48 kB
/** * Logger Utility * Simple structured logging for Optivise */ import { getCorrelationId } from './correlation.js'; class SimpleLogger { level; levelValues = { debug: 0, info: 1, warn: 2, error: 3 }; constructor(level = 'info') { this.level = level; } debug(message, meta) { this.log('debug', message, meta); } info(message, meta) { this.log('info', message, meta); } warn(message, meta) { this.log('warn', message, meta); } error(message, error, meta) { const errorMeta = error ? { error: { name: error.name, message: error.message, stack: error.stack }, ...meta } : meta; this.log('error', message, errorMeta); } log(level, message, meta) { // Silent mode for MCP - no output unless debug is explicitly enabled if (process.env.OPTIDEV_DEBUG !== 'true' && process.env.OPTIVISE_MODE !== 'server') { // In MCP mode, completely silent unless debug is enabled return; } // Always log debug messages when OPTIDEV_DEBUG is set if (process.env.OPTIDEV_DEBUG === 'true') { // Continue with logging regardless of level } else if (this.levelValues[level] < this.levelValues[this.level]) { return; } const timestamp = new Date().toISOString(); const corr = getCorrelationId(); const logEntry = { timestamp, level: level.toUpperCase(), message, ...(corr ? { correlationId: corr } : {}), ...(meta && Object.keys(meta).length > 0 ? { meta: this.redact(meta) } : {}) }; // Emit as compact JSON on stderr to avoid MCP stdout interference const output = JSON.stringify(logEntry); switch (level) { case 'error': console.error(output); break; case 'warn': console.warn(output); break; case 'debug': console.error(output); // Use stderr for debug messages too break; default: console.error(output); // Use stderr for info messages to avoid interfering with MCP protocol } } formatLogEntry(_entry) { // Deprecated; kept for API compatibility return JSON.stringify(_entry); } redact(obj) { const json = JSON.stringify(obj, (_k, v) => v, 2); const redacted = json // redact obvious keys .replace(/(api[_-]?key"\s*:\s*")[^"]+(")/gi, '$1[REDACTED]$2') .replace(/(authorization"\s*:\s*")[^"]+(")/gi, '$1[REDACTED]$2') .replace(/(password"\s*:\s*")[^"]+(")/gi, '$1[REDACTED]$2') // redact bearer tokens .replace(/Bearer\s+[A-Za-z0-9-_.]+/g, 'Bearer [REDACTED]') // redact email-like .replace(/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g, '[REDACTED_EMAIL]'); try { return JSON.parse(redacted); } catch { return obj; } } setLevel(level) { this.level = level; } getLevel() { return this.level; } } export { SimpleLogger }; export function createLogger(level = 'info') { return new SimpleLogger(level); } //# sourceMappingURL=logger.js.map