如何为NestJS的HttpService记录请求、响应及错误日志?
Hey there! Great question—this is a common scenario when working with NestJS's HttpService and wanting to add logging without affecting your controllers or other services. Let's break down two clean, NestJS-native approaches to solve this:
1. Create a Wrapper Service for HttpService with Interceptors
This approach lets you encapsulate the logging logic in a dedicated service, so you can reuse it wherever you need the logging-enabled HttpService.
First, generate a new service (e.g., LoggingHttpService):
import { Injectable, HttpService } from '@nestjs/common'; @Injectable() export class LoggingHttpService { constructor(private readonly httpService: HttpService) { // Add request interceptor this.httpService.axiosRef.interceptors.request.use( (config) => { console.log(`[REQUEST] Method: ${config.method}, URL: ${config.url}`); // You can also log headers, body, etc. as needed return config; }, (error) => { console.error('[REQUEST ERROR]', error); return Promise.reject(error); }, ); // Add response interceptor this.httpService.axiosRef.interceptors.response.use( (response) => { console.log(`[RESPONSE] Status: ${response.status}, URL: ${response.config.url}`); // Log response data or headers if required return response; }, (error) => { console.error('[RESPONSE ERROR]', error.response?.data || error.message); return Promise.reject(error); }, ); } // Delegate all core HttpService methods to the wrapped instance get<T = any>(url: string, config?: any) { return this.httpService.get<T>(url, config); } post<T = any>(url: string, data?: any, config?: any) { return this.httpService.post<T>(url, data, config); } // Add other HTTP methods (put, delete, patch, etc.) as needed }
Then, wire it up in your module:
import { Module } from '@nestjs/common'; import { HttpModule } from '@nestjs/axios'; import { LoggingHttpService } from './logging-http.service'; @Module({ imports: [HttpModule], providers: [LoggingHttpService], exports: [LoggingHttpService], // Export if you need this service in other modules }) export class AppModule {}
Now, whenever you need to make HTTP calls with logging, inject LoggingHttpService instead of the default HttpService. This keeps your logging logic isolated—your controllers and other services won't be impacted unless you explicitly use this wrapper.
2. Configure Axios Interceptors Directly in HttpModule Registration
If you want logging to apply to the default HttpService instance (no wrapper needed), use HttpModule.registerAsync() to customize the axios instance during module initialization.
Here's how to set it up:
import { Module } from '@nestjs/common'; import { HttpModule } from '@nestjs/axios'; import axios from 'axios'; @Module({ imports: [ HttpModule.registerAsync({ useFactory: () => { const axiosInstance = axios.create(); // Request interceptor axiosInstance.interceptors.request.use( (config) => { console.log(`[REQUEST] Method: ${config.method}, URL: ${config.url}`); return config; }, (error) => { console.error('[REQUEST ERROR]', error); return Promise.reject(error); }, ); // Response interceptor axiosInstance.interceptors.response.use( (response) => { console.log(`[RESPONSE] Status: ${response.status}, URL: ${response.config.url}`); return response; }, (error) => { console.error('[RESPONSE ERROR]', error.response?.data || error.message); return Promise.reject(error); }, ); return { axiosInstance, }; }, }), ], }) export class AppModule {}
This way, every instance of HttpService injected in your app will use this pre-configured axios instance with logging interceptors. Perfect if you want logging to apply globally to all HttpService usage.
Quick Tips
- Both approaches follow NestJS's dependency injection and modularity rules—no messy workarounds.
- Replace
console.log/console.errorwith your production-grade logging library (like Winston or Pino) for better scalability. - Use the wrapper service if you need logging only for specific HTTP calls; use
registerAsyncfor globalHttpServicelogging.
内容的提问来源于stack exchange,提问作者Ian Gregson

