import { Injectable, NestInterceptor, ExecutionContext, CallHandler, Logger, } from '@nestjs/common'; import { Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; @Injectable() export class LoggingInterceptor implements NestInterceptor { private readonly logger = new Logger('HTTP'); intercept(context: ExecutionContext, next: CallHandler): Observable { const request = context.switchToHttp().getRequest(); const { method, url, ip } = request; const userAgent = request.get('user-agent') || ''; const userId = request.user?.sub || 'anonymous'; const now = Date.now(); return next.handle().pipe( tap({ next: () => { const response = context.switchToHttp().getResponse(); const { statusCode } = response; const duration = Date.now() - now; this.logger.log( `${method} ${url} ${statusCode} ${duration}ms - ${userId} - ${ip} - ${userAgent}`, ); }, error: (error) => { const duration = Date.now() - now; this.logger.error( `${method} ${url} ${error.status || 500} ${duration}ms - ${userId} - ${ip} - ${error.message}`, ); }, }), ); } }