From f466f102181d9aaba63fdac1aed44beea2a53546 Mon Sep 17 00:00:00 2001 From: ocamilomontealegre Date: Thu, 19 Dec 2024 09:44:16 -0500 Subject: [PATCH] feat: show error stack trace in logs --- .../http-exception.filter.ts | 44 ++++--- src/common/interceptors/http.interceptor.ts | 122 +++++++++--------- 2 files changed, 85 insertions(+), 81 deletions(-) diff --git a/src/common/exception-filters/http-exception.filter.ts b/src/common/exception-filters/http-exception.filter.ts index 584f51c..f92fe5c 100644 --- a/src/common/exception-filters/http-exception.filter.ts +++ b/src/common/exception-filters/http-exception.filter.ts @@ -1,21 +1,23 @@ -import { StatusCodes } from "http-status-codes"; -import { HTTPException } from "@common/exceptions/"; -import { HTTPUtils } from "@common/utils"; -import { HTTPResponseModel } from "@common/models"; -import type { NextFunction, Request, Response } from "express"; - -export class HTTPExceptionFilter { - public catch(err: Error, req: Request, res: Response, _: NextFunction): void { - const statusCode = - err instanceof HTTPException ? err.statusCode : StatusCodes.INTERNAL_SERVER_ERROR; - const message = err.message ?? HTTPUtils.getHttpMessage(statusCode); - - const errorResponse = new HTTPResponseModel({ - status: statusCode, - success: false, - message, - }); - - res.status(statusCode).json(errorResponse); - } -} +import { StatusCodes } from "http-status-codes"; +import { HTTPException } from "@common/exceptions/"; +import { HTTPUtils } from "@common/utils"; +import { HTTPResponseModel } from "@common/models"; +import type { NextFunction, Request, Response } from "express"; + +export class HTTPExceptionFilter { + public catch(err: Error, req: Request, res: Response, _: NextFunction): void { + const statusCode = + err instanceof HTTPException ? err.statusCode : StatusCodes.INTERNAL_SERVER_ERROR; + const message = err.message ?? HTTPUtils.getHttpMessage(statusCode); + + const errorResponse = new HTTPResponseModel({ + status: statusCode, + success: false, + message, + }); + + res.locals.error = err; + res.status(statusCode).json(errorResponse); + } +} + diff --git a/src/common/interceptors/http.interceptor.ts b/src/common/interceptors/http.interceptor.ts index 5536e57..a0eed05 100644 --- a/src/common/interceptors/http.interceptor.ts +++ b/src/common/interceptors/http.interceptor.ts @@ -1,60 +1,62 @@ -import { StatusCodes } from "http-status-codes"; -import { Logger } from "@common/logger/logger.config"; -import { HTTPUtils } from "@common/utils"; -import { HTTPResponseModel } from "@common/models"; -import { appConfig } from "@common/env"; -import type { NextFunction, Request, Response, Send } from "express"; -import type { GenericObject } from "@common/types"; - -export class HttpInterceptor { - private readonly _logger: Logger; - - public constructor() { - this._logger = new Logger(HttpInterceptor.name); - } - - private _overrideResMethod(res: Response, method: Send): Send { - return (body: GenericObject): Response => { - if (res.statusCode >= StatusCodes.BAD_REQUEST) { - res.locals.httpResponse = body; - return method.call(res, body); - } - - const httpResponse = new HTTPResponseModel({ - message: HTTPUtils.getHttpMessage(res.statusCode), - data: body, - }); - res.locals.httpResponse = httpResponse; - - return method.call(res, httpResponse); - }; - } - - public intercept = (req: Request, res: Response, next: NextFunction): void => { - const { method, url, headers } = req; - - const requestBody = req.body ? JSON.stringify(req.body) : ""; - - if (url.includes(`${appConfig.appDocsEndpoint}`)) { - return next(); - } - - const originalJson = res.json.bind(res); - res.json = this._overrideResMethod(res, originalJson); - - res.on("finish", () => { - const { statusCode, locals } = res; - - const logBody = `Incoming request: METHOD: ${method} | URL: ${url} | HEADERS: ${JSON.stringify( - headers, - )} | REQUEST-BODY: ${requestBody} | Outgoing response: STATUS_CODE: ${statusCode} | RESPONSE-BODY: ${JSON.stringify( - locals.httpResponse, - )}`; - - if (statusCode >= StatusCodes.BAD_REQUEST) this._logger.error(logBody); - else this._logger.info(logBody); - }); - - next(); - }; -} +import { StatusCodes } from "http-status-codes"; +import { Logger } from "@common/logger/logger.config"; +import { HTTPUtils } from "@common/utils"; +import { HTTPResponseModel } from "@common/models"; +import { appConfig } from "@common/env"; +import type { NextFunction, Request, Response, Send } from "express"; +import type { GenericObject } from "@common/types"; + +export class HttpInterceptor { + private readonly logger: Logger; + + public constructor() { + this.logger = new Logger(HttpInterceptor.name); + } + + private overrideResMethod(res: Response, method: Send): Send { + return (body: GenericObject): Response => { + if (res.statusCode >= StatusCodes.BAD_REQUEST) { + res.locals.httpResponse = body; + return method.call(res, body); + } + + const httpResponse = new HTTPResponseModel({ + message: HTTPUtils.getHttpMessage(res.statusCode), + data: body, + }); + res.locals.httpResponse = httpResponse; + + return method.call(res, httpResponse); + }; + } + + public intercept = (req: Request, res: Response, next: NextFunction): void => { + const { method, url, headers } = req; + + const requestBody = req.body ? JSON.stringify(req.body) : ""; + + if (url.includes(`${appConfig.appDocsEndpoint}`)) { + return next(); + } + + const originalJson = res.json.bind(res); + res.json = this.overrideResMethod(res, originalJson); + + res.on("finish", () => { + const { statusCode, locals } = res; + + const logBody = `Incoming request: METHOD: ${method} | URL: ${url} | HEADERS: ${JSON.stringify( + headers, + )} | REQUEST-BODY: ${requestBody} | Outgoing response: STATUS_CODE: ${statusCode} | RESPONSE-BODY: ${JSON.stringify( + locals.httpResponse, + )}`; + + if (statusCode >= StatusCodes.BAD_REQUEST) + this.logger.error(`${logBody} | ERROR: ${res.locals?.error.stack}`); + else this.logger.info(logBody); + }); + + next(); + }; +} +