optivise
Version:
Optivise - The Ultimate Optimizely Development Assistant with AI-powered features, zero-config setup, and comprehensive development support
108 lines • 3.48 kB
JavaScript
/**
* 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