UNPKG

revenium-middleware-litellm-node

Version:

Comprehensive middleware for Node.js applications using LiteLLM Proxy to automatically track LLM usage, costs, and performance metrics with Revenium

284 lines 9.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.defaultLogger = void 0; exports.loadConfigFromEnv = loadConfigFromEnv; exports.validateConfig = validateConfig; exports.getConfig = getConfig; exports.setConfig = setConfig; exports.getLogger = getLogger; exports.setLogger = setLogger; exports.resetConfig = resetConfig; exports.resetConfigManager = resetConfigManager; exports.initializeConfig = initializeConfig; const logger_types_1 = require("./utils/logger-types"); const validation_1 = require("./utils/validation"); /** * Type-safe console logger implementation */ class TypeSafeConsoleLogger { getLogLevel() { const envLevel = process.env.REVENIUM_LOG_LEVEL?.toUpperCase(); if (envLevel && Object.values(logger_types_1.LogLevel).includes(envLevel)) return envLevel; return process.env.REVENIUM_DEBUG === 'true' ? logger_types_1.LogLevel.DEBUG : logger_types_1.LogLevel.INFO; } formatMessage(level, message, context) { const timestamp = (0, logger_types_1.createTimestamp)(); const prefix = `[Revenium LiteLLM${level === logger_types_1.LogLevel.DEBUG ? ' Debug' : level === logger_types_1.LogLevel.WARNING ? ' Warning' : level === logger_types_1.LogLevel.ERROR ? ' Error' : ''}]`; const contextStr = (0, logger_types_1.formatLogContext)(context, false); return `${timestamp} ${prefix} ${message}${contextStr}`; } debug(message, context) { if ((0, logger_types_1.shouldLog)(logger_types_1.LogLevel.DEBUG, this.getLogLevel())) { console.debug(this.formatMessage(logger_types_1.LogLevel.DEBUG, message, context)); } } info(message, context) { if ((0, logger_types_1.shouldLog)(logger_types_1.LogLevel.INFO, this.getLogLevel())) { console.info(this.formatMessage(logger_types_1.LogLevel.INFO, message, context)); } } warn(message, context) { if ((0, logger_types_1.shouldLog)(logger_types_1.LogLevel.WARNING, this.getLogLevel())) { console.warn(this.formatMessage(logger_types_1.LogLevel.WARNING, message, context)); } } error(message, context) { if ((0, logger_types_1.shouldLog)(logger_types_1.LogLevel.ERROR, this.getLogLevel())) { console.error(this.formatMessage(logger_types_1.LogLevel.ERROR, message, context)); } } } /** * Legacy logger adapter for backward compatibility */ class LegacyLoggerAdapter { constructor() { this.typeSafeLogger = new TypeSafeConsoleLogger(); } debug(message, ...args) { // Convert legacy args to context - sanitize unknown data const context = args.length > 0 ? { legacyArgs: args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)) } : {}; this.typeSafeLogger.debug(message, context); } info(message, ...args) { const context = args.length > 0 ? { legacyArgs: args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)) } : {}; this.typeSafeLogger.info(message, context); } warn(message, ...args) { const context = args.length > 0 ? { legacyArgs: args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)) } : {}; this.typeSafeLogger.warn(message, context); } error(message, ...args) { const context = args.length > 0 ? { legacyArgs: args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)) } : {}; this.typeSafeLogger.error(message, context); } } /** * Default console logger implementation */ exports.defaultLogger = new LegacyLoggerAdapter(); /** * Load configuration from environment variables */ function loadConfigFromEnv() { const reveniumMeteringApiKey = process.env.REVENIUM_METERING_API_KEY; const reveniumMeteringBaseUrl = process.env.REVENIUM_METERING_BASE_URL || 'https://api.revenium.io/meter'; const litellmProxyUrl = process.env.LITELLM_PROXY_URL; const litellmApiKey = process.env.LITELLM_API_KEY; const organizationId = process.env.REVENIUM_ORGANIZATION_ID; const apiTimeout = process.env.REVENIUM_API_TIMEOUT ? parseInt(process.env.REVENIUM_API_TIMEOUT, 10) : undefined; const failSilent = process.env.REVENIUM_FAIL_SILENT !== 'false'; // Default to true const maxRetries = process.env.REVENIUM_MAX_RETRIES ? parseInt(process.env.REVENIUM_MAX_RETRIES, 10) : undefined; if (!reveniumMeteringApiKey || !litellmProxyUrl) return null; return { reveniumMeteringApiKey, reveniumMeteringBaseUrl, litellmProxyUrl, litellmApiKey, organizationId, apiTimeout, failSilent, maxRetries }; } /** * Validate Revenium configuration with enhanced error reporting */ function validateConfig(config) { const validation = (0, validation_1.validateReveniumConfig)(config); if (!validation.isValid) { // Log detailed validation errors getLogger().error('Configuration validation failed', { errors: validation.errors, warnings: validation.warnings, suggestions: validation.suggestions }); // Create detailed error message let errorMessage = 'Configuration validation failed:\n'; validation.errors.forEach((error, index) => { errorMessage += ` ${index + 1}. ${error}\n`; }); if (validation.suggestions && validation.suggestions.length > 0) { errorMessage += '\nSuggestions:\n'; validation.suggestions.forEach((suggestion, index) => { errorMessage += ` • ${suggestion}\n`; }); } throw new Error(errorMessage.trim()); } // Log warnings if any if (validation.warnings && validation.warnings.length > 0) { getLogger().warn('Configuration warnings', { warnings: validation.warnings }); } } /** * Configuration manager singleton for proper state management */ class ConfigurationManager { constructor() { this.config = null; this.logger = exports.defaultLogger; // Private constructor to enforce singleton pattern } /** * Get the singleton instance */ static getInstance() { if (!ConfigurationManager.instance) ConfigurationManager.instance = new ConfigurationManager(); return ConfigurationManager.instance; } /** * Reset the singleton instance (for testing) */ static resetInstance() { ConfigurationManager.instance = null; } /** * Get the current configuration */ getConfig() { return this.config; } /** * Set the configuration */ setConfig(config) { validateConfig(config); this.config = config; this.logger.debug('Revenium LiteLLM configuration updated', { reveniumMeteringBaseUrl: config.reveniumMeteringBaseUrl, litellmProxyUrl: config.litellmProxyUrl, hasApiKey: !!config.reveniumMeteringApiKey, hasProxyKey: !!config.litellmApiKey, organizationId: config.organizationId, apiTimeout: config.apiTimeout || 5000, failSilent: config.failSilent !== false, maxRetries: config.maxRetries || 3 }); } /** * Get the current logger */ getLogger() { return this.logger; } /** * Set a custom logger */ setLogger(logger) { this.logger = logger; this.logger.debug('Custom logger set for Revenium LiteLLM middleware'); } /** * Reset configuration and logger to defaults (for testing) */ reset() { this.config = null; this.logger = exports.defaultLogger; } /** * Check if configuration is valid and complete */ isConfigured() { return this.config !== null; } } ConfigurationManager.instance = null; /** * Get the current global configuration */ function getConfig() { return ConfigurationManager.getInstance().getConfig(); } /** * Set the global configuration */ function setConfig(config) { ConfigurationManager.getInstance().setConfig(config); } /** * Get the current logger */ function getLogger() { return ConfigurationManager.getInstance().getLogger(); } /** * Set a custom logger */ function setLogger(logger) { ConfigurationManager.getInstance().setLogger(logger); } /** * Reset configuration manager (for testing) */ function resetConfig() { ConfigurationManager.getInstance().reset(); } /** * Reset the entire configuration manager instance (for testing) */ function resetConfigManager() { ConfigurationManager.resetInstance(); } /** * Initialize configuration from environment variables */ function initializeConfig() { const envConfig = loadConfigFromEnv(); if (envConfig) { try { setConfig(envConfig); getLogger().debug('Revenium LiteLLM middleware initialized from environment variables'); return true; } catch (error) { getLogger().error('Failed to initialize Revenium LiteLLM configuration:', error); return false; } } // Log what's missing for easier debugging const missing = []; if (!process.env.REVENIUM_METERING_API_KEY) missing.push('REVENIUM_METERING_API_KEY'); if (!process.env.LITELLM_PROXY_URL) missing.push('LITELLM_PROXY_URL'); if (missing.length > 0) { getLogger().warn(`Revenium LiteLLM middleware not initialized. Missing environment variables: ${missing.join(', ')}`); getLogger().info('Check env.example for configuration guidance'); } return false; } //# sourceMappingURL=config.js.map