Refactor requestErrorHandler, adjust request errors to appropriate pino log level

This commit is contained in:
Tuan Dang
2023-11-01 10:10:39 +02:00
parent ad4513f926
commit 3b0bd362c9
8 changed files with 175 additions and 118 deletions
+25 -33
View File
@@ -3,52 +3,44 @@ import { ErrorRequestHandler } from "express";
import { TokenExpiredError } from "jsonwebtoken";
import { InternalServerError, UnauthorizedRequestError } from "../utils/errors";
import { logger } from "../utils/logging";
import RequestError from "../utils/requestError";
import RequestError, { mapToPinoLogLevel } from "../utils/requestError";
import { ForbiddenError } from "@casl/ability";
export const requestErrorHandler: ErrorRequestHandler = async (
error: RequestError | Error,
err: RequestError | Error,
req,
res,
next
) => {
if (res.headersSent) return next();
const logAndCaptureException = async (error: RequestError) => {
// TODO: tie pino error-handling to error types/levels
let error: RequestError;
// (await getLogger("backend-main")).log(
// (<RequestError>error).levelName.toLowerCase(),
// `${error.stack}\n${error.message}`
// );
logger.error(error.stack, error.message);
//* Set Sentry user identification if req.user is populated
if (req.user !== undefined && req.user !== null) {
Sentry.setUser({ email: (req.user as any).email });
}
Sentry.captureException(error);
};
if (error instanceof RequestError) {
if (error instanceof TokenExpiredError) {
error = UnauthorizedRequestError({ stack: error.stack, message: "Token expired" });
}
await logAndCaptureException((<RequestError>error));
} else {
if (error instanceof ForbiddenError) {
error = UnauthorizedRequestError({ context: { exception: error.message }, stack: error.stack })
} else {
error = InternalServerError({ context: { exception: error.message }, stack: error.stack });
}
await logAndCaptureException((<RequestError>error));
switch (true) {
case err instanceof TokenExpiredError:
error = UnauthorizedRequestError({ stack: err.stack, message: "Token expired" });
break;
case err instanceof ForbiddenError:
error = UnauthorizedRequestError({ context: { exception: err.message }, stack: err.stack })
break;
case err instanceof RequestError:
error = err as RequestError;
break;
default:
error = InternalServerError({ context: { exception: err.message }, stack: err.stack });
break;
}
logger[mapToPinoLogLevel(error.level)](error);
if (req.user) {
Sentry.setUser({ email: (req.user as any).email });
}
Sentry.captureException(error);
delete (<any>error).stacktrace // remove stack trace from being sent to client
res.status((<RequestError>error).statusCode).json(error);
res.status((<RequestError>error).statusCode).json(error); // revise json part here
next();
};