Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logging request/response in Nest.js

New to Nest.js,
I am trying to implement a simple logger for tracing HTTP requests like :

:method :url :status :res[content-length] - :response-time ms 

From my understanding the best place for that would be interceptors. But I Also use Guards and as mentionned, Guards are triggered after middlewares but before interceptors.

Meaning, my forrbidden accesses are not logged. I could write the logging part in two different places but rather not. Any idea?

Thanks!

My Interceptor code:

import { Injectable, NestInterceptor, ExecutionContext, HttpException, HttpStatus } from '@nestjs/common'; import { Observable, throwError } from 'rxjs'; import { catchError, tap } from 'rxjs/operators';  @Injectable() export class HTTPLoggingInterceptor implements NestInterceptor {    intercept(context: ExecutionContext, call$: Observable<any>): Observable<any> {     const now = Date.now();     const request = context.switchToHttp().getRequest();      const method = request.method;     const url = request.originalUrl;      return call$.pipe(       tap(() => {         const response = context.switchToHttp().getResponse();         const delay = Date.now() - now;         console.log(`${response.statusCode} | [${method}] ${url} - ${delay}ms`);       }),       catchError((error) => {         const response = context.switchToHttp().getResponse();         const delay = Date.now() - now;         console.error(`${response.statusCode} | [${method}] ${url} - ${delay}ms`);         return throwError(error);       }),     );   } } 
like image 935
Julien Avatar asked Mar 10 '19 22:03

Julien


People also ask

What is logging in Nestjs?

Nest comes with a built-in text-based logger which is used during application bootstrapping and several other circumstances such as displaying caught exceptions (i.e., system logging). This functionality is provided via the Logger class in the @nestjs/common package.

How do I return my nest JS status code?

To return a status code in nestjs, you need to include the @Res() in your parameters. Normally in nestjs the passthrough option on the Response object is set to false by default. This means anything you do will not passthrough into the Response object.

What is @body in Nestjs?

To instruct Nestjs that we need the body values from the request, we should use the @Body() decorator function from the @nestjs/common module before the body parameter. Doing this will bind the body values from the request to the body parameter in the createPost() method.

How do I redirect in Nestjs?

Redirection. To redirect a response to a specific URL, you can either use a @Redirect() decorator or a library-specific response object (and call res.redirect() directly). @Redirect() takes two arguments, url and statusCode , both are optional. The default value of statusCode is 302 ( Found ) if omitted.


1 Answers

https://github.com/julien-sarazin/nest-playground/issues/1#issuecomment-682588094

You can use middleware for that.

import { Injectable, NestMiddleware, Logger } from '@nestjs/common';  import { Request, Response, NextFunction } from 'express';  @Injectable() export class AppLoggerMiddleware implements NestMiddleware {   private logger = new Logger('HTTP');    use(request: Request, response: Response, next: NextFunction): void {     const { ip, method, path: url } = request;     const userAgent = request.get('user-agent') || '';      response.on('close', () => {       const { statusCode } = response;       const contentLength = response.get('content-length');        this.logger.log(         `${method} ${url} ${statusCode} ${contentLength} - ${userAgent} ${ip}`       );     });      next();   } } 

and in the AppModule

export class AppModule implements NestModule {   configure(consumer: MiddlewareConsumer): void {     consumer.apply(AppLoggerMiddleware).forRoutes('*');   } } 
like image 55
hojin Avatar answered Sep 23 '22 06:09

hojin