import { createLogger, format, transports } from 'winston'; import { DATABASE_LOG_CONFIG, PERFORMANCE_THRESHOLDS, LOG_FILTERS, getEnvironmentConfig } from './LoggingConfig'; // Database operation logger export const dbLogger = createLogger(DATABASE_LOG_CONFIG); // Apply environment-specific configuration const envConfig = getEnvironmentConfig(); dbLogger.level = envConfig.level; // Performance monitoring export class PerformanceMonitor { private static timers: Map = new Map(); static startTimer(operationId: string): void { this.timers.set(operationId, Date.now()); } static endTimer(operationId: string, operation: string, entityName: string): number { const startTime = this.timers.get(operationId); if (!startTime) { dbLogger.warn('Timer not found for operation', { operationId, operation, entityName }); return 0; } const duration = Date.now() - startTime; this.timers.delete(operationId); // Log based on performance thresholds if (duration > PERFORMANCE_THRESHOLDS.VERY_SLOW_OPERATION) { dbLogger.error('Very slow database operation detected', { operation, entityName, duration, operationId, threshold: PERFORMANCE_THRESHOLDS.VERY_SLOW_OPERATION, severity: 'critical' }); } else if (duration > PERFORMANCE_THRESHOLDS.SLOW_OPERATION) { dbLogger.warn('Slow database operation detected', { operation, entityName, duration, operationId, threshold: PERFORMANCE_THRESHOLDS.SLOW_OPERATION, severity: 'warning' }); } else { dbLogger.debug('Database operation completed', { operation, entityName, duration, operationId }); } return duration; } static generateOperationId(): string { return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; } } // Database operation types for logging export enum DBOperation { CREATE = 'CREATE', READ = 'READ', UPDATE = 'UPDATE', DELETE = 'DELETE', SOFT_DELETE = 'SOFT_DELETE', BULK_CREATE = 'BULK_CREATE', BULK_UPDATE = 'BULK_UPDATE', BULK_DELETE = 'BULK_DELETE', FIND = 'FIND', SEARCH = 'SEARCH', COUNT = 'COUNT', AGGREGATE = 'AGGREGATE', TRANSACTION = 'TRANSACTION' } // Logging decorators export function LogDBOperation(operation: DBOperation, entityName: string) { return function (target: any, propertyName: string, descriptor: PropertyDescriptor) { const method = descriptor.value; descriptor.value = async function (...args: any[]) { const operationId = PerformanceMonitor.generateOperationId(); const startTime = Date.now(); PerformanceMonitor.startTimer(operationId); dbLogger.info('Database operation started', { operation, entityName, method: propertyName, operationId, args: args.length > 0 ? 'provided' : 'none' }); try { const result = await method.apply(this, args); const duration = PerformanceMonitor.endTimer(operationId, operation, entityName); dbLogger.info('Database operation successful', { operation, entityName, method: propertyName, operationId, duration, resultCount: Array.isArray(result) ? result.length : result ? 1 : 0 }); return result; } catch (error) { const duration = Date.now() - startTime; dbLogger.error('Database operation failed', { operation, entityName, method: propertyName, operationId, duration, error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined }); throw error; } }; }; } // Connection logging export function logDatabaseConnection(status: 'connecting' | 'connected' | 'disconnected' | 'error', details?: any) { const logData = { event: 'database_connection', status, timestamp: new Date().toISOString(), ...details }; if (status === 'error') { dbLogger.error('Database connection error', logData); } else { dbLogger.info('Database connection status', logData); } } // Query logging export function logQuery(query: string, parameters?: any[], duration?: number) { const envConfig = getEnvironmentConfig(); if (!envConfig.logQueries) return; const sanitizedQuery = LOG_FILTERS.sanitizeQuery(query); const sanitizedParams = parameters ? LOG_FILTERS.sanitizeParameters(parameters) : []; const logData = { event: 'database_query', query: sanitizedQuery, parameters: sanitizedParams, duration: duration || 0, timestamp: new Date().toISOString() }; if (duration && duration > PERFORMANCE_THRESHOLDS.VERY_SLOW_QUERY) { dbLogger.error('Very slow query detected', { ...logData, severity: 'critical', threshold: PERFORMANCE_THRESHOLDS.VERY_SLOW_QUERY }); } else if (duration && duration > PERFORMANCE_THRESHOLDS.SLOW_QUERY) { dbLogger.warn('Slow query detected', { ...logData, severity: 'warning', threshold: PERFORMANCE_THRESHOLDS.SLOW_QUERY }); } else { dbLogger.debug('Database query executed', logData); } }