Skip to content

Instantly share code, notes, and snippets.

@PhantomKnight287
Created October 3, 2024 17:13
Show Gist options
  • Select an option

  • Save PhantomKnight287/d5fd4735d768e3f84ff70daabb88db31 to your computer and use it in GitHub Desktop.

Select an option

Save PhantomKnight287/d5fd4735d768e3f84ff70daabb88db31 to your computer and use it in GitHub Desktop.
// A Nestjs filter which "filters" out all exceptions to add custom logging logic
import { Request, Response } from 'express';
import { IncomingMessage } from 'http';
import {
ArgumentsHost,
BadRequestException,
Catch,
ExceptionFilter,
HttpException,
HttpStatus,
} from '@nestjs/common';
// This is a rxjs subject
import { errorSubject$ } from '../../constants';
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
catch(exception: Error, host: ArgumentsHost) {
const req = host.getArgs()[0];
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status =
exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
const message =
exception instanceof HttpException
? exception instanceof BadRequestException
? Array.isArray((exception.getResponse() as any).message)
? (exception.getResponse() as any).message[0]
: exception.message
: exception.message
: 'Internal server error';
const detailedError =
exception instanceof Error
? exception.message
: 'Unexpected error occurred';
const errorMessage = {
statusCode: status,
message,
timestamp: new Date().toISOString(),
path: request.originalUrl,
};
console.error(exception.stack);
if (req instanceof IncomingMessage) {
errorSubject$.next({
statusCode: status,
path: request.originalUrl,
message: exception.message,
requestHeaders: request.headers,
requestBody: JSON.stringify(request.body),
responseHeader: response.getHeaders(),
responseBody: JSON.stringify(errorMessage),
stackTrace: exception.stack,
method: request.method,
name: exception.name,
});
}
response.status(status).json(errorMessage);
}
}
export const errorSubject$ = new Subject<any>();
import { NextFunction, Request, Response } from 'express';
import { Injectable, NestMiddleware } from '@nestjs/common';
import { errorSubject$ } from '../../constants';
@Injectable()
export class LoggingMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
const originalJson = res.json;
//@ts-expect-error correct types
res.json = function (body) {
if (res.statusCode < 400) {
errorSubject$.next({
statusCode: res.statusCode,
path: req.originalUrl,
requestHeaders: req.headers,
requestBody: JSON.stringify(req.body),
responseHeaders: JSON.parse(JSON.stringify(res.getHeaders())),
responseBody: JSON.stringify(body),
method: req.method,
});
}
originalJson.call(this, body);
};
next();
}
}
import { errorSubject$ } from '../../constants';
// Yes the logging is called "LogsTrap"
if (process.env.LOGSTRAP_KEY && process.env.LOGSTRAP_PATH)
errorSubject$.subscribe((payload) => {
fetch(process.env.LOGSTRAP_PATH, {
method: 'POST',
body: JSON.stringify(payload),
headers: {
'X-API-KEY': process.env.LOGSTRAP_KEY,
'content-type': 'application/json',
},
}).catch(() => {});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment