Exploring the world of logging in Nestjs to capture response data objects

I'm eager to implement logging for incoming requests and outgoing responses in NestJs. I gathered insights from various sources including a post on StackOverflow and a document on NestJs Aspect Interception.

I'd love to achieve this without relying on external packages, so I'm keen on finding a native "Nest" solution.

Currently, I have the following code for request logging:

@Injectable()
export class RequestInterceptor implements NestInterceptor {
  private logger: Logger = new Logger(RequestInterceptor.name);

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const {
      originalUrl,
      method,
      params,
      query,
      body,
    } = context.switchToHttp().getRequest();

    this.logger.log({
      originalUrl,
      method,
      params,
      query,
      body,
    });

    return next.handle();
  }
}

This setup would log details for a GET /users request.

https://i.sstatic.net/Zlv2g.png

In addition to request logging, I also desire to log outgoing responses. Here is the interceptor I'm currently using:

@Injectable()
export class ResponseInterceptor implements NestInterceptor {
  private logger: Logger = new Logger(ResponseInterceptor.name);

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const { statusCode } = context.switchToHttp().getResponse();

    return next.handle().pipe(
      tap(() =>
        this.logger.log({
          statusCode,
        }),
      ),
    );
  }
}

This configuration would log details for a GET /users response.

https://i.sstatic.net/j9CsQ.png

However, I am now wondering about how to access the data that was sent back to the client. Any insights on this would be greatly appreciated.

Answer №1

To enhance the efficiency of your code, I recommend consolidating all the logging operations into a single logger.

Additionally, in order to access the data being sent back to the client, you should include a parameter in your tap function. Typically, this parameter is named data and allows you to track the information being sent back. Although the functionality of the observable may seem unclear due to Nest, you can achieve the desired outcome with code similar to the following:

@Injectable()
export class AspectLogger implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler) {
    const req = context.switchToHttp().getRequest();
    const { statusCode } = context.switchToHttp().getResponse();
    const { originalUrl, method, params, query, body } = req;

    console.log({
      originalUrl,
      method,
      params,
      query,
      body,
    });

    return next.handle().pipe(
      tap((data) =>
        console.log({
          statusCode,
          data,
        })
      )
    );
  }
}

This approach is applicable even if you later decide to separate the interceptors again. However, having a unified interceptor can simplify the process of determining call time.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating a new route in a Express JS server to specifically handle POST requests

Just starting to learn the ropes of Javascript, and I'm diving into express to create an application that will enable users to craft new recipes, explore existing ones, and view details about each recipe. To get things moving, I've launched my s ...

Bypass VueJs Typescript errors within the template section with Typescript

My VueJs App is functioning properly, but there is one thing that bothers me - a TypeScript error in my template block. Is there a way to handle this similar to how I would in my script block? <script setup lang="ts"> //@ignore-ts this li ...

What is the process of creating a color range in Java?

I am looking for a way to input a 6-digit RGB-hex number and then be able to click on a button that will display the corresponding color name. Unfortunately, I have not been able to find a color library in Java that can provide me with the names of arbitra ...

Building a div element within a React function

For an exercise, I need to create an input field and a button. The goal is to display the text from the input field in a div/span below when the button is clicked. If I change the text in the input field and click the button again, the displayed text shoul ...

Error encountered while trying to display the react-bootstrap table

I am having trouble rendering sample data using react-bootstrap tables. Every time I try, I encounter the error: TypeError: Cannot read property 'filter' of undefined I've searched on various platforms and visited multiple links, but I ca ...

Uncaught TypeError: Cannot create new instances of User - Node.js server not recognizing User as a constructor

I encountered an issue while attempting to save a user to MongoDB database using a post request. The error message "TypeError: User is not a constructor" keeps popping up despite the straightforward setup of my code. I have double-checked but can't se ...

A guide to selecting the bookmark with a URL that is on a currently opened page

To gain a clearer understanding of my goal, follow these steps: Open the Chrome Browser and go to a URL, such as https://www.google.com. Once the page loads, locate and click on the bookmark labeled "ABC", which contains the URL ({window.open('/ ...

What causes an error when the App is enclosed within a Provider component?

What is causing the error when wrapping the App in Provider? Are there any additional changes or additions needed? Error: "could not find react-redux context value; please ensure the component is wrapped in a @Provider@" import React from ' ...

How do I utilize ng-repeat in Angular to pass a variable that specifies the number of repetitions?

When working on my app, I encountered a situation where I needed to retrieve elements from a database and display them using ng-reat. Everything was going smoothly until I realized that within this list, there was another set of data that required a separa ...

Executing an Ajax SPARQL request in Firefox

I've been attempting to run an asynchronous Ajax sparql query on dbpedia using Firefox, but I encountered a strange issue that I can't seem to figure out. Surprisingly, the query works perfectly fine in Chrome, Edge, and Internet Explorer, but wh ...

Can a web application be developed utilizing JavaScript to access the torch feature in Safari?

Currently working on a website that needs to utilize the flashlight feature on both android and IOS devices. Found a method to activate the torch from an android device using Chrome (link). However, this same code does not seem to be functional on my IOS d ...

The function res.download() triggers an error when the request is aborted

I am facing a challenge with my Express application where I am trying to download a file before loading the page. The issue appears to be caused by stopping res.download with res.render, but I am struggling to find a resolution. I did attempt to place re ...

Transfer PHP's uniqid() function to real-time using JavaScript with jQuery

Seeking a compact JavaScript(jQuery) code snippet to achieve this: date("r",hexdec(substr(uniqid(),0,8))); Your assistance is highly appreciated. Thank you. ...

Changing the method from POST to GET after adding the data to the database

Currently, I am utilizing Mongoose and Express.js to handle my Post request. Below is the code for my Post request: $('#update').on('click', function() { var uname = $('#username').val(); var name = $('# ...

Performing unit tests in Angular 2 with karma

Trying to grasp the concept of unit testing in Angular has been quite a challenge for me, especially since I am still navigating through Angular 2 and its syntax. Understanding testing becomes even more intricate. I attempt to follow the examples provided ...

Limiting input to specific characters is effective on Chrome, but unfortunately does not function on Firefox

This code snippet is designed to restrict user input to lowercase letters from a-z, numbers from 0-9, and the dash character "-". While it functions correctly in Chrome, it does not allow any input in Firefox. What could be causing this issue? $('#sl ...

I am experiencing an issue with Array.some not functioning properly within my React component, whereas Array.map is working

I am attempting to utilize Array.prototype.some() within my React component to check if a particular value exists in my array of objects. However, I keep encountering the error message data.some(...) is not a function. Interestingly, Array.prototype.map() ...

Trouble with a basic array duplication function

function duplicateArray(arr) { var len = arr.length; var dup = new Array(); var j; for (j = 0; j < len; j++) { dup[j] = arr[j]; } console.log(dup); } return; duplicateArray([2, 3, 5]); I appreciate your assistance, There are no errors ...

Deliver the Filestream to the Client for download using Express

I'm currently working on a Node.js project where I need to take a string as input, process it with a certain function that returns a Filestream. What is the best way to send this Filestream via Express for the client to download, specifying a particul ...

Tips for avoiding double reservations and creating time slots with nextjs and prisma

Welcome to my NextJS app booking system. As a beginner, I'm exploring how to create a website for simple bookings and have successfully connected it to Netlify. Currently, I can gather booking details such as time and name using Netlify forms. Howeve ...