Open source vector database with HNSW indexing, graph relationships, and metadata facets. Features CLI with professional augmentation registry integration for discovering extensions and capabilities.
217 lines
No EOL
7.7 KiB
JavaScript
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
|