diff --git a/.serena/cache/typescript/document_symbols_cache_v20-05-25.pkl b/.serena/cache/typescript/document_symbols_cache_v20-05-25.pkl index b5aa38e..8a3db7e 100644 Binary files a/.serena/cache/typescript/document_symbols_cache_v20-05-25.pkl and b/.serena/cache/typescript/document_symbols_cache_v20-05-25.pkl differ diff --git a/apps/stock/config/src/config-instance.ts b/apps/stock/config/src/config-instance.ts index 15a0fdf..5c33725 100644 --- a/apps/stock/config/src/config-instance.ts +++ b/apps/stock/config/src/config-instance.ts @@ -1,85 +1,87 @@ -import { ConfigManager, createAppConfig } from '@stock-bot/config'; -import { stockAppSchema, type StockAppConfig } from './schemas'; -import * as path from 'path'; - -let configInstance: ConfigManager | null = null; - -/** - * Initialize the stock application configuration - * @param serviceName - Optional service name to override port configuration - */ -export function initializeStockConfig(serviceName?: 'dataIngestion' | 'dataPipeline' | 'webApi'): StockAppConfig { - try { - if (!configInstance) { - configInstance = createAppConfig(stockAppSchema, { - configPath: path.join(__dirname, '../config'), - }); - } - - const config = configInstance.initialize(stockAppSchema); - - // If a service name is provided, override the service port - if (serviceName && config.services?.[serviceName]) { - const kebabName = serviceName.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, ''); - return { - ...config, - service: { - ...config.service, - port: config.services[serviceName].port, - name: serviceName, // Keep original for backward compatibility - serviceName: kebabName // Standard kebab-case name - } - }; - } - - return config; - } catch (error: any) { - console.error('Failed to initialize stock configuration:', error.message); - if (error.errors) { - console.error('Validation errors:', JSON.stringify(error.errors, null, 2)); - } - throw error; - } -} - -/** - * Get the current stock configuration - */ -export function getStockConfig(): StockAppConfig { - if (!configInstance) { - // Auto-initialize if not already done - return initializeStockConfig(); - } - return configInstance.get(); -} - -/** - * Get configuration for a specific service - */ -export function getServiceConfig(service: 'dataIngestion' | 'dataPipeline' | 'webApi') { - const config = getStockConfig(); - return config.services?.[service]; -} - -/** - * Get configuration for a specific provider - */ -export function getProviderConfig(provider: 'eod' | 'ib' | 'qm' | 'yahoo') { - const config = getStockConfig(); - return config.providers[provider]; -} - -/** - * Check if a feature is enabled - */ -export function isFeatureEnabled(feature: keyof StockAppConfig['features']): boolean { - const config = getStockConfig(); - return config.features[feature]; -} - -/** - * Reset configuration (useful for testing) - */ -export function resetStockConfig(): void { - configInstance = null; +import { ConfigManager, createAppConfig } from '@stock-bot/config'; +import { stockAppSchema, type StockAppConfig } from './schemas'; +import * as path from 'path'; +import { getLogger } from '@stock-bot/logger'; + +let configInstance: ConfigManager | null = null; + +/** + * Initialize the stock application configuration + * @param serviceName - Optional service name to override port configuration + */ +export function initializeStockConfig(serviceName?: 'dataIngestion' | 'dataPipeline' | 'webApi'): StockAppConfig { + try { + if (!configInstance) { + configInstance = createAppConfig(stockAppSchema, { + configPath: path.join(__dirname, '../config'), + }); + } + + const config = configInstance.initialize(stockAppSchema); + + // If a service name is provided, override the service port + if (serviceName && config.services?.[serviceName]) { + const kebabName = serviceName.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, ''); + return { + ...config, + service: { + ...config.service, + port: config.services[serviceName].port, + name: serviceName, // Keep original for backward compatibility + serviceName: kebabName // Standard kebab-case name + } + }; + } + + return config; + } catch (error: any) { + const logger = getLogger('stock-config'); + logger.error('Failed to initialize stock configuration:', error.message); + if (error.errors) { + logger.error('Validation errors:', error.errors); + } + throw error; + } +} + +/** + * Get the current stock configuration + */ +export function getStockConfig(): StockAppConfig { + if (!configInstance) { + // Auto-initialize if not already done + return initializeStockConfig(); + } + return configInstance.get(); +} + +/** + * Get configuration for a specific service + */ +export function getServiceConfig(service: 'dataIngestion' | 'dataPipeline' | 'webApi') { + const config = getStockConfig(); + return config.services?.[service]; +} + +/** + * Get configuration for a specific provider + */ +export function getProviderConfig(provider: 'eod' | 'ib' | 'qm' | 'yahoo') { + const config = getStockConfig(); + return config.providers[provider]; +} + +/** + * Check if a feature is enabled + */ +export function isFeatureEnabled(feature: keyof StockAppConfig['features']): boolean { + const config = getStockConfig(); + return config.features[feature]; +} + +/** + * Reset configuration (useful for testing) + */ +export function resetStockConfig(): void { + configInstance = null; } \ No newline at end of file diff --git a/apps/stock/data-ingestion/src/handlers/qm/actions/session.action.ts b/apps/stock/data-ingestion/src/handlers/qm/actions/session.action.ts index ff0df45..2c1feea 100644 --- a/apps/stock/data-ingestion/src/handlers/qm/actions/session.action.ts +++ b/apps/stock/data-ingestion/src/handlers/qm/actions/session.action.ts @@ -19,7 +19,7 @@ export async function checkSessions(handler: BaseHandler): Promise<{ // Check which session IDs need more sessions and queue creation jobs let queuedCount = 0; for (const [sessionType, sessionId] of Object.entries(QM_SESSION_IDS)) { - console.log(`Checking session ID: ${sessionId}`); + handler.logger.debug(`Checking session ID: ${sessionId}`); if (sessionManager.needsMoreSessions(sessionId)) { const currentCount = sessionManager.getSessions(sessionId).length; const neededSessions = SESSION_CONFIG.MAX_SESSIONS - currentCount; diff --git a/apps/stock/data-ingestion/src/index.ts b/apps/stock/data-ingestion/src/index.ts index 45aeeea..aa9920b 100644 --- a/apps/stock/data-ingestion/src/index.ts +++ b/apps/stock/data-ingestion/src/index.ts @@ -15,7 +15,7 @@ import { createRoutes } from './routes/create-routes'; // Initialize configuration with service-specific overrides const config = initializeStockConfig('dataIngestion'); -console.log('Data Ingestion Service Configuration:', JSON.stringify(config, null, 2)); + // Create service application const app = new ServiceApplication( diff --git a/apps/stock/data-pipeline/src/index.ts b/apps/stock/data-pipeline/src/index.ts index b6fe633..9b5f9db 100644 --- a/apps/stock/data-pipeline/src/index.ts +++ b/apps/stock/data-pipeline/src/index.ts @@ -18,7 +18,7 @@ import { setupServiceContainer } from './container-setup'; // Initialize configuration with service-specific overrides const config = initializeStockConfig('dataPipeline'); -console.log('Data Pipeline Service Configuration:', JSON.stringify(config, null, 2)); + // Create service application const app = new ServiceApplication( diff --git a/apps/stock/web-api/src/index.ts b/apps/stock/web-api/src/index.ts index d4f6663..4058aab 100644 --- a/apps/stock/web-api/src/index.ts +++ b/apps/stock/web-api/src/index.ts @@ -21,7 +21,7 @@ if (config.queue) { config.queue.delayWorkerStart = true; } -console.log('Web API Service Configuration:', JSON.stringify(config, null, 2)); + // Create service application const app = new ServiceApplication( diff --git a/libs/core/config/src/config-manager.ts b/libs/core/config/src/config-manager.ts index 8dc2dde..5da0b44 100644 --- a/libs/core/config/src/config-manager.ts +++ b/libs/core/config/src/config-manager.ts @@ -3,6 +3,7 @@ import { z } from 'zod'; import { EnvLoader } from './loaders/env.loader'; import { FileLoader } from './loaders/file.loader'; import { ConfigError, ConfigValidationError } from './errors'; +import { getLogger } from '@stock-bot/logger'; import type { ConfigLoader, ConfigManagerOptions, @@ -12,6 +13,7 @@ import type { } from './types'; export class ConfigManager> { + private readonly logger = getLogger('config-manager'); private config: T | null = null; private loaders: ConfigLoader[]; private environment: Environment; @@ -81,8 +83,7 @@ export class ConfigManager> { received: (err as any).received, })); - console.error('Configuration validation failed:'); - console.error(JSON.stringify(errorDetails, null, 2)); + this.logger.error('Configuration validation failed:', errorDetails); throw new ConfigValidationError('Configuration validation failed', error.errors); } diff --git a/libs/core/di/src/registrations/cache.registration.ts b/libs/core/di/src/registrations/cache.registration.ts index 3c4737a..a9d7574 100644 --- a/libs/core/di/src/registrations/cache.registration.ts +++ b/libs/core/di/src/registrations/cache.registration.ts @@ -9,7 +9,7 @@ export function registerCacheServices( ): void { if (config.redis.enabled) { container.register({ - cache: asFunction(() => { + cache: asFunction(({ logger }) => { const { createServiceCache } = require('@stock-bot/queue'); // Get standardized service name from config const serviceName = config.service?.serviceName || config.service?.name || 'unknown'; @@ -20,11 +20,11 @@ export function registerCacheServices( port: config.redis.port, password: config.redis.password, db: config.redis.db, // This will be overridden by ServiceCache - }); + }, { logger }); }).singleton(), // Also provide global cache for shared data - globalCache: asFunction(() => { + globalCache: asFunction(({ logger }) => { const { createServiceCache } = require('@stock-bot/queue'); const serviceName = config.service?.serviceName || config.service?.name || 'unknown'; @@ -32,7 +32,7 @@ export function registerCacheServices( host: config.redis.host, port: config.redis.port, password: config.redis.password, - }, { global: true }); + }, { global: true, logger }); }).singleton(), }); } else { diff --git a/libs/core/di/src/service-application.ts b/libs/core/di/src/service-application.ts index 57d5547..a6e6a17 100644 --- a/libs/core/di/src/service-application.ts +++ b/libs/core/di/src/service-application.ts @@ -313,7 +313,7 @@ export class ServiceApplication { } } catch (error) { - console.error('DETAILED ERROR:', error); + this.logger.error('DETAILED ERROR:', error); this.logger.error('Failed to start service', { error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, diff --git a/libs/core/di/src/utils/lifecycle.ts b/libs/core/di/src/utils/lifecycle.ts index 528bb49..b415b85 100644 --- a/libs/core/di/src/utils/lifecycle.ts +++ b/libs/core/di/src/utils/lifecycle.ts @@ -1,5 +1,6 @@ import type { AwilixContainer } from 'awilix'; import type { ServiceDefinitions } from '../container/types'; +import { getLogger } from '@stock-bot/logger'; interface ServiceWithLifecycle { connect?: () => Promise; @@ -10,6 +11,7 @@ interface ServiceWithLifecycle { } export class ServiceLifecycleManager { + private readonly logger = getLogger('service-lifecycle'); private readonly services = [ { name: 'cache', key: 'cache' as const }, { name: 'mongoClient', key: 'mongoClient' as const }, @@ -40,7 +42,7 @@ export class ServiceLifecycleManager { } await Promise.all(initPromises); - console.log('✅ All services initialized successfully'); + this.logger.info('All services initialized successfully'); } async shutdownServices(container: AwilixContainer): Promise { @@ -56,20 +58,20 @@ export class ServiceLifecycleManager { } await Promise.allSettled(shutdownPromises); - console.log('✅ All services shut down'); + this.logger.info('All services shut down'); } private async initializeService(name: string, service: ServiceWithLifecycle): Promise { try { if (typeof service.connect === 'function') { await service.connect(); - console.log(`✅ ${name} connected`); + this.logger.info(`${name} connected`); } else if (typeof service.initialize === 'function') { await service.initialize(); - console.log(`✅ ${name} initialized`); + this.logger.info(`${name} initialized`); } } catch (error) { - console.error(`❌ Failed to initialize ${name}:`, error); + this.logger.error(`Failed to initialize ${name}:`, error); throw error; } } @@ -83,9 +85,9 @@ export class ServiceLifecycleManager { } else if (typeof service.shutdown === 'function') { await service.shutdown(); } - console.log(`✅ ${name} shut down`); + this.logger.info(`${name} shut down`); } catch (error) { - console.error(`❌ Error shutting down ${name}:`, error); + this.logger.error(`Error shutting down ${name}:`, error); } } @@ -94,4 +96,4 @@ export class ServiceLifecycleManager { setTimeout(() => reject(new Error(message)), timeout); }); } -} \ No newline at end of file +} diff --git a/libs/core/types/src/handler-registry.ts b/libs/core/types/src/handler-registry.ts index fa7710d..b300431 100644 --- a/libs/core/types/src/handler-registry.ts +++ b/libs/core/types/src/handler-registry.ts @@ -9,8 +9,10 @@ import type { JobHandler, ScheduledJob, } from './handlers'; +import { getLogger } from '@stock-bot/logger'; class HandlerRegistry { + private readonly logger = getLogger('handler-registry'); private handlers = new Map(); private handlerSchedules = new Map(); @@ -18,7 +20,7 @@ class HandlerRegistry { * Register a handler with its operations (simple config) */ register(handlerName: string, config: HandlerConfig): void { - console.log(`Registering handler: ${handlerName}`, { + this.logger.info(`Registering handler: ${handlerName}`, { operations: Object.keys(config), }); @@ -29,7 +31,7 @@ class HandlerRegistry { * Register a handler with scheduled jobs (enhanced config) */ registerWithSchedule(config: HandlerConfigWithSchedule): void { - console.log(`Registering handler with schedule: ${config.name}`, { + this.logger.info(`Registering handler with schedule: ${config.name}`, { operations: Object.keys(config.operations), scheduledJobs: config.scheduledJobs?.length || 0, }); diff --git a/libs/data/questdb/src/client.ts b/libs/data/questdb/src/client.ts index 8fac7a9..e7ead4b 100644 --- a/libs/data/questdb/src/client.ts +++ b/libs/data/questdb/src/client.ts @@ -38,11 +38,6 @@ export class QuestDBClient { }; // Debug: log the received config - console.log('DEBUG: QuestDB client constructor called with config:', { - ...config, - user: config.user || '[NOT PROVIDED]', - password: config.password ? '[PROVIDED]' : '[NOT PROVIDED]', - }); this.logger.debug('QuestDB client created with config:', { ...config, user: config.user || '[NOT PROVIDED]', @@ -435,27 +430,24 @@ export class QuestDBClient { // Only add user/password if they are provided if (this.config.user) { - console.log('DEBUG: Adding user to QuestDB pool config:', this.config.user); + this.logger.debug('Adding user to QuestDB pool config:', this.config.user); config.user = this.config.user; } else { - console.log('DEBUG: No user provided for QuestDB connection'); + this.logger.debug('No user provided for QuestDB connection'); } if (this.config.password) { - console.log('DEBUG: Adding password to QuestDB pool config'); + this.logger.debug('Adding password to QuestDB pool config'); config.password = this.config.password; } else { - console.log('DEBUG: No password provided for QuestDB connection'); + this.logger.debug('No password provided for QuestDB connection'); } - console.log('DEBUG: Final QuestDB pool config:', { - ...config, - password: config.password ? '[REDACTED]' : undefined, - }); + this.logger.debug('Final QuestDB pool config:', { ...config, password: config.password ? '[REDACTED]' : undefined, diff --git a/libs/services/queue/src/service-cache.ts b/libs/services/queue/src/service-cache.ts index f8ade29..5d3aae4 100644 --- a/libs/services/queue/src/service-cache.ts +++ b/libs/services/queue/src/service-cache.ts @@ -13,7 +13,8 @@ export class ServiceCache implements CacheProvider { constructor( serviceName: string, redisConfig: RedisConfig, - isGlobalCache: boolean = false + isGlobalCache: boolean = false, + logger?: any ) { // Get service configuration const serviceConfig = getServiceConfig(serviceName); @@ -42,6 +43,7 @@ export class ServiceCache implements CacheProvider { db, }, keyPrefix: prefix + ':', + logger, }; this.cache = createCache(cacheConfig); @@ -161,7 +163,7 @@ export class ServiceCache implements CacheProvider { export function createServiceCache( serviceName: string, redisConfig: RedisConfig, - options: { global?: boolean } = {} + options: { global?: boolean; logger?: any } = {} ): ServiceCache { - return new ServiceCache(serviceName, redisConfig, options.global); + return new ServiceCache(serviceName, redisConfig, options.global, options.logger); } \ No newline at end of file diff --git a/libs/services/shutdown/src/shutdown.ts b/libs/services/shutdown/src/shutdown.ts index 36e0276..d31a853 100644 --- a/libs/services/shutdown/src/shutdown.ts +++ b/libs/services/shutdown/src/shutdown.ts @@ -14,6 +14,7 @@ import type { ShutdownOptions, ShutdownResult, } from './types'; +import { getLogger } from '@stock-bot/logger'; // Global flag that works across all processes/workers declare global { @@ -22,6 +23,7 @@ declare global { export class Shutdown { private static instance: Shutdown | null = null; + private readonly logger = getLogger('shutdown'); private isShuttingDown = false; private signalReceived = false; // Track if shutdown signal was received private shutdownTimeout = 30000; // 30 seconds default @@ -200,7 +202,7 @@ export class Shutdown { } catch (error) { failed++; if (name) { - console.error(`✗ Shutdown failed: ${name} (priority: ${priority})`, error); + this.logger.error(`Shutdown failed: ${name} (priority: ${priority})`, error); } } }