brainy/dist/utils/logger.js
David Snelling f8c45f2d8d Initial commit: Brainy - Multi-Dimensional AI Database
Open source vector database with HNSW indexing, graph relationships,
and metadata facets. Features CLI with professional augmentation registry
integration for discovering extensions and capabilities.
2025-08-18 17:35:06 -07:00

217 lines
No EOL
7.7 KiB
JavaScript

/**
* Centralized logging utility for Brainy
* Provides configurable log levels and consistent logging across the codebase
* Automatically reduces logging in production environments to minimize costs
*/
import { isProductionEnvironment, getLogLevel } from './environment.js';
export var LogLevel;
(function (LogLevel) {
LogLevel[LogLevel["ERROR"] = 0] = "ERROR";
LogLevel[LogLevel["WARN"] = 1] = "WARN";
LogLevel[LogLevel["INFO"] = 2] = "INFO";
LogLevel[LogLevel["DEBUG"] = 3] = "DEBUG";
LogLevel[LogLevel["TRACE"] = 4] = "TRACE";
})(LogLevel || (LogLevel = {}));
class Logger {
constructor() {
this.config = {
level: LogLevel.ERROR, // Default to ERROR in production for cost optimization
timestamps: false, // Disable timestamps in production to reduce log size
includeModule: true
};
// Auto-detect production environment and set appropriate defaults
this.applyEnvironmentDefaults();
// Set log level from environment variable if available (overrides auto-detection)
const envLogLevel = process.env.BRAINY_LOG_LEVEL;
if (envLogLevel) {
const level = LogLevel[envLogLevel.toUpperCase()];
if (level !== undefined) {
this.config.level = level;
}
}
// Parse module-specific log levels
const moduleLogLevels = process.env.BRAINY_MODULE_LOG_LEVELS;
if (moduleLogLevels) {
try {
this.config.modules = JSON.parse(moduleLogLevels);
}
catch (e) {
// Ignore parsing errors
}
}
}
applyEnvironmentDefaults() {
const envLogLevel = getLogLevel();
// Convert environment log level to Logger LogLevel
switch (envLogLevel) {
case 'silent':
this.config.level = -1; // Below ERROR to silence all logs
break;
case 'error':
this.config.level = LogLevel.ERROR;
this.config.timestamps = false; // Minimize log size in production
break;
case 'warn':
this.config.level = LogLevel.WARN;
this.config.timestamps = false;
break;
case 'info':
this.config.level = LogLevel.INFO;
this.config.timestamps = true;
break;
case 'verbose':
this.config.level = LogLevel.DEBUG;
this.config.timestamps = true;
break;
}
// In production environments, be extra conservative to minimize costs
if (isProductionEnvironment()) {
this.config.level = Math.min(this.config.level, LogLevel.ERROR);
this.config.timestamps = false;
this.config.includeModule = false; // Reduce log size
}
}
static getInstance() {
if (!Logger.instance) {
Logger.instance = new Logger();
}
return Logger.instance;
}
configure(config) {
this.config = { ...this.config, ...config };
}
shouldLog(level, module) {
// Check module-specific level first
if (this.config.modules && this.config.modules[module] !== undefined) {
return level <= this.config.modules[module];
}
// Otherwise use global level
return level <= this.config.level;
}
formatMessage(level, module, message) {
const parts = [];
if (this.config.timestamps) {
parts.push(`[${new Date().toISOString()}]`);
}
parts.push(`[${LogLevel[level]}]`);
if (this.config.includeModule) {
parts.push(`[${module}]`);
}
parts.push(message);
return parts.join(' ');
}
log(level, module, message, ...args) {
if (!this.shouldLog(level, module)) {
return;
}
if (this.config.handler) {
this.config.handler(level, module, message, ...args);
return;
}
const formattedMessage = this.formatMessage(level, module, message);
switch (level) {
case LogLevel.ERROR:
console.error(formattedMessage, ...args);
break;
case LogLevel.WARN:
console.warn(formattedMessage, ...args);
break;
case LogLevel.INFO:
console.info(formattedMessage, ...args);
break;
case LogLevel.DEBUG:
case LogLevel.TRACE:
console.log(formattedMessage, ...args);
break;
}
}
error(module, message, ...args) {
this.log(LogLevel.ERROR, module, message, ...args);
}
warn(module, message, ...args) {
this.log(LogLevel.WARN, module, message, ...args);
}
info(module, message, ...args) {
this.log(LogLevel.INFO, module, message, ...args);
}
debug(module, message, ...args) {
this.log(LogLevel.DEBUG, module, message, ...args);
}
trace(module, message, ...args) {
this.log(LogLevel.TRACE, module, message, ...args);
}
// Create a module-specific logger
createModuleLogger(module) {
return {
error: (message, ...args) => this.error(module, message, ...args),
warn: (message, ...args) => this.warn(module, message, ...args),
info: (message, ...args) => this.info(module, message, ...args),
debug: (message, ...args) => this.debug(module, message, ...args),
trace: (message, ...args) => this.trace(module, message, ...args)
};
}
}
// Export singleton instance
export const logger = Logger.getInstance();
// Export convenience function for creating module loggers
export function createModuleLogger(module) {
return logger.createModuleLogger(module);
}
// Export function to configure logger
export function configureLogger(config) {
logger.configure(config);
}
/**
* Smart console replacement that automatically reduces logging in production
* Dramatically reduces Google Cloud Run logging costs
*
* Usage: Replace console.log with smartConsole.log, etc.
*/
export const smartConsole = {
log: (message, ...args) => {
if (logger['shouldLog'](LogLevel.INFO, 'console')) {
console.log(message, ...args);
}
},
info: (message, ...args) => {
if (logger['shouldLog'](LogLevel.INFO, 'console')) {
console.info(message, ...args);
}
},
warn: (message, ...args) => {
if (logger['shouldLog'](LogLevel.WARN, 'console')) {
console.warn(message, ...args);
}
},
error: (message, ...args) => {
if (logger['shouldLog'](LogLevel.ERROR, 'console')) {
console.error(message, ...args);
}
},
debug: (message, ...args) => {
if (logger['shouldLog'](LogLevel.DEBUG, 'console')) {
console.debug(message, ...args);
}
},
trace: (message, ...args) => {
if (logger['shouldLog'](LogLevel.TRACE, 'console')) {
console.trace(message, ...args);
}
}
};
/**
* Production-optimized logging functions
* These only log in non-production environments or when explicitly enabled
*/
export const prodLog = {
// Only log errors in production (always visible)
error: (message, ...args) => {
console.error(message, ...args);
},
// These are suppressed in production unless BRAINY_LOG_LEVEL is set
warn: (message, ...args) => smartConsole.warn(message, ...args),
info: (message, ...args) => smartConsole.info(message, ...args),
debug: (message, ...args) => smartConsole.debug(message, ...args),
log: (message, ...args) => smartConsole.log(message, ...args)
};
//# sourceMappingURL=logger.js.map