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); }), ); } }
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.
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.
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.
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.
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('*'); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With