import { Injectable, Inject, Logger } from '@nestjs/common'; import type { LoggingInterface, StructuredLoggingInterface, StructuredLogData, RequestLogData, ResponseLogData, DatabaseQueryLogData, CacheOperationLogData, ExternalApiCallLogData, BusinessEventLogData, UserLogData, ErrorLogData, LoggingOptions, } from './logging.interface'; import { LogLevel } from './logging.interface'; /** * 日志服务 * 基于 NestJS 官方示例实现 * 参考: https://docs.nestjs.cn/fundamentals/dependency-injection * 对应 Java: 日志服务 */ @Injectable() export class LoggingService implements LoggingInterface, StructuredLoggingInterface { private readonly logger = new Logger(LoggingService.name); private currentLevel: LogLevel = LogLevel.INFO; constructor( @Inject('LOGGING_PROVIDER') private readonly loggingProvider: LoggingInterface, @Inject('STRUCTURED_LOGGING_PROVIDER') private readonly structuredLoggingProvider: StructuredLoggingInterface, ) {} // ==================== 基础日志接口 ==================== /** * 记录调试日志 */ debug(message: string, context?: string, meta?: Record): void { try { this.loggingProvider.debug(message, context, meta); } catch (error) { this.logger.error(`Failed to log debug message: ${message}`, error); } } /** * 记录信息日志 */ info(message: string, context?: string, meta?: Record): void { try { this.loggingProvider.info(message, context, meta); } catch (error) { this.logger.error(`Failed to log info message: ${message}`, error); } } /** * 记录警告日志 */ warn(message: string, context?: string, meta?: Record): void { try { this.loggingProvider.warn(message, context, meta); } catch (error) { this.logger.error(`Failed to log warn message: ${message}`, error); } } /** * 记录错误日志 */ error(message: string, context?: string, meta?: Record): void { try { this.loggingProvider.error(message, context, meta); } catch (error) { this.logger.error(`Failed to log error message: ${message}`, error); } } /** * 记录致命错误日志 */ fatal(message: string, context?: string, meta?: Record): void { try { this.loggingProvider.fatal(message, context, meta); } catch (error) { this.logger.error(`Failed to log fatal message: ${message}`, error); } } /** * 记录日志 */ log( level: LogLevel, message: string, context?: string, meta?: Record, ): void { try { this.loggingProvider.log(level, message, context, meta); } catch (error) { this.logger.error(`Failed to log message: ${message}`, error); } } /** * 设置日志级别 */ setLevel(level: LogLevel): void { try { this.currentLevel = level; this.loggingProvider.setLevel(level); } catch (error) { this.logger.error(`Failed to set log level: ${level}`, error); } } /** * 获取当前日志级别 */ getLevel(): LogLevel { return this.currentLevel; } /** * 创建子日志器 */ child(context: string): LoggingInterface { try { return this.loggingProvider.child(context); } catch (error) { this.logger.error(`Failed to create child logger: ${context}`, error); return this; } } // ==================== 结构化日志接口 ==================== /** * 记录结构化日志 */ logStructured( level: LogLevel, message: string, structuredData: StructuredLogData, ): void { try { this.structuredLoggingProvider.logStructured( level, message, structuredData, ); } catch (error) { this.logger.error(`Failed to log structured message: ${message}`, error); } } /** * 记录请求日志 */ logRequest( request: RequestLogData, response: ResponseLogData, duration: number, ): void { try { this.structuredLoggingProvider.logRequest(request, response, duration); } catch (error) { this.logger.error('Failed to log request', error); } } /** * 记录数据库查询日志 */ logDatabaseQuery( query: DatabaseQueryLogData, duration: number, result?: any, ): void { try { this.structuredLoggingProvider.logDatabaseQuery(query, duration, result); } catch (error) { this.logger.error('Failed to log database query', error); } } /** * 记录缓存操作日志 */ logCacheOperation( operation: CacheOperationLogData, hit: boolean, duration: number, ): void { try { this.structuredLoggingProvider.logCacheOperation( operation, hit, duration, ); } catch (error) { this.logger.error('Failed to log cache operation', error); } } /** * 记录外部API调用日志 */ logExternalApiCall( apiCall: ExternalApiCallLogData, response: any, duration: number, ): void { try { this.structuredLoggingProvider.logExternalApiCall( apiCall, response, duration, ); } catch (error) { this.logger.error('Failed to log external API call', error); } } /** * 记录业务事件日志 */ logBusinessEvent( event: BusinessEventLogData, user?: UserLogData, meta?: Record, ): void { try { this.structuredLoggingProvider.logBusinessEvent(event, user, meta); } catch (error) { this.logger.error('Failed to log business event', error); } } // ==================== 装饰器支持 ==================== /** * 日志装饰器实现 */ async logMethod( options: LoggingOptions, fn: () => T | Promise, args: any[] = [], ): Promise { const { level = LogLevel.INFO, context = 'Method', logArgs = false, logResult = false, logDuration = true, logError = true, enabled = true, message, meta = {}, } = options; if (!enabled) { return await fn(); } const startTime = Date.now(); const logMessage = message || `${context} execution`; const logMeta = { ...meta }; try { // 记录方法开始 if (logArgs) { logMeta.args = args; } this.log(level, `${logMessage} started`, context, logMeta); // 执行方法 const result = await fn(); // 记录方法完成 const duration = Date.now() - startTime; const successMeta = { ...logMeta }; if (logResult) { successMeta.result = result; } if (logDuration) { successMeta.duration = duration; } this.log(level, `${logMessage} completed`, context, successMeta); return result; } catch (error) { const duration = Date.now() - startTime; const errorMeta = { ...logMeta }; if (logDuration) { errorMeta.duration = duration; } if (logError) { errorMeta.error = this.serializeError(error); } this.error(`${logMessage} failed`, context, errorMeta); throw error; } } // ==================== 工具方法 ==================== /** * 序列化错误 */ private serializeError(error: any): ErrorLogData { if (error instanceof Error) { return { name: error.name, message: error.message, stack: error.stack, code: (error as any).code, cause: (error as any).cause, context: (error as any).context, }; } return { name: 'UnknownError', message: String(error), context: { originalError: error }, }; } /** * 记录HTTP请求 */ logHttpRequest( method: string, url: string, statusCode: number, duration: number, userAgent?: string, ip?: string, userId?: string, ): void { const request: RequestLogData = { method, url, headers: {}, ip, userAgent, userId, }; const response: ResponseLogData = { statusCode, headers: {}, }; this.logRequest(request, response, duration); } /** * 记录数据库操作 */ logDatabaseOperation( operation: string, table: string, query: string, duration: number, params?: any[], result?: any, ): void { const queryData: DatabaseQueryLogData = { operation, table, query, params, }; this.logDatabaseQuery(queryData, duration, result); } /** * 记录缓存操作 */ logCacheOperationSimple( operation: string, key: string, hit: boolean, duration: number, ttl?: number, size?: number, ): void { const operationData: CacheOperationLogData = { operation, key, ttl, size, }; this.logCacheOperation(operationData, hit, duration); } /** * 记录外部API调用 */ logExternalApiCallSimple( service: string, endpoint: string, method: string, statusCode: number, duration: number, headers?: Record, body?: any, ): void { const apiCall: ExternalApiCallLogData = { service, endpoint, method, headers: headers || {}, body, }; const response = { statusCode }; this.logExternalApiCall(apiCall, response, duration); } /** * 记录业务事件 */ logBusinessEventSimple( event: string, action: string, resource: string, resourceId?: string, result?: 'success' | 'failure' | 'partial', data?: Record, userId?: string, ): void { const eventData: BusinessEventLogData = { event, action, resource, resourceId, result, data, }; const userData: UserLogData | undefined = userId ? { id: userId } : undefined; this.logBusinessEvent(eventData, userData); } /** * 记录性能指标 */ logPerformance( operation: string, duration: number, context?: string, meta?: Record, ): void { const performanceMeta = { operation, duration, ...meta, }; if (duration > 1000) { this.warn(`Slow operation: ${operation}`, context, performanceMeta); } else if (duration > 500) { this.info(`Operation: ${operation}`, context, performanceMeta); } else { this.debug(`Operation: ${operation}`, context, performanceMeta); } } /** * 记录安全事件 */ logSecurityEvent( event: string, severity: 'low' | 'medium' | 'high' | 'critical', context?: string, meta?: Record, ): void { const securityMeta = { event, severity, ...meta, }; switch (severity) { case 'critical': this.fatal(`Security event: ${event}`, context, securityMeta); break; case 'high': this.error(`Security event: ${event}`, context, securityMeta); break; case 'medium': this.warn(`Security event: ${event}`, context, securityMeta); break; case 'low': this.info(`Security event: ${event}`, context, securityMeta); break; } } /** * 记录审计日志 */ logAudit( action: string, resource: string, resourceId?: string, userId?: string, result?: 'success' | 'failure', meta?: Record, ): void { const auditMeta = { action, resource, resourceId, userId, result, ...meta, }; this.info(`Audit: ${action} on ${resource}`, 'audit', auditMeta); } }