Skip to content

Commit

Permalink
Logger and erro rhandler updated
Browse files Browse the repository at this point in the history
  • Loading branch information
sinanptm committed Sep 15, 2024
1 parent 55d87c6 commit 524a50a
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 28 deletions.
20 changes: 16 additions & 4 deletions server/src/domain/entities/CustomError.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
import { StatusCode } from "../../types";

export default class CustomError extends Error {
public statusCode: StatusCode
constructor(message: string, statusCode: StatusCode) {
export default class AppError extends Error {
public statusCode: StatusCode;
public code?: string;
public details?: any;

constructor(message: string, statusCode: StatusCode, code?: string, details?: any) {
super(message);
this.statusCode = statusCode
this.statusCode = statusCode;
this.code = code;
this.details = details;
}
public toJSON() {
return {
message: this.message,
statusCode: this.statusCode,
code: this.code
};
}
}
58 changes: 39 additions & 19 deletions server/src/presentation/middlewares/ErrorHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,30 @@ import logger from "../../utils/logger";
import CustomError from "../../domain/entities/CustomError";

export default class ErrorHandler {
exec(err: any, req: Request, res: Response, next: NextFunction) {
logger.error(err.message, {
statusCode: err.statusCode || StatusCode.InternalServerError,
stack: err.stack,
path: req.path,
method: req.method,
ip: req.ip,
});

exec(error: any, req: Request, res: Response, next: NextFunction) {
const statusCode = error.statusCode || StatusCode.InternalServerError;
const message = error.message || "Internal Server Error";
const clientIp = req.ip || req.connection.remoteAddress;

const statusCode = err.statusCode || StatusCode.InternalServerError;
const message = err.message || "Internal Server Error";

if (err instanceof CustomError) {
if (error instanceof CustomError) {
logger.warn(`CustomError: ${message}`, {
statusCode,
method: req.method,
path: req.path,
clientIp,
});
return res.status(statusCode).json({ message });
}

if (err.code && err.code === 11000) {
logger.warn("Duplicate key error encountered.");
if (error.code && error.code === 11000) {
logger.warn("Resource Conflict (Duplicate Entry)", {
statusCode: StatusCode.Conflict,
method: req.method,
path: req.path,
clientIp,
requestHeaders: req.headers,
error: message,
});
return res.status(StatusCode.Conflict).json({
message: "The resource already exists.",
error: message,
Expand All @@ -33,15 +38,30 @@ export default class ErrorHandler {
message.includes("getaddrinfo ENOTFOUND smtp.gmail.com") ||
message.includes("queryA ETIMEOUT smtp.gmail.com")
) {
logger.error("Email service issue encountered.");
logger.error("Email Service Error", {
statusCode: StatusCode.InternalServerError,
method: req.method,
path: req.path,
clientIp,
requestHeaders: req.headers,
});
return res.status(StatusCode.InternalServerError).json({
message: "We are Having Issue with Email Service",
message: "We are having an issue with the Email Service.",
});
}
}

logger.error(`Unhandled Error: ${message}`, {
statusCode,
method: req.method,
path: req.path,
clientIp,
requestHeaders: req.headers,
stack: error.stack,
});

res.status(statusCode).json({
message,
...(process.env.NODE_ENV !== "production" && { stack: err.stack }),
...(process.env.NODE_ENV !== "production" && { stack: error.stack }),
});
}
}
18 changes: 13 additions & 5 deletions server/src/utils/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import "winston-daily-rotate-file";

const logDirectory = path.resolve(__dirname, "logs");

const customFormat = format.printf(({ timestamp, level, message, stack, url, data, ...meta }) => {
const consoleFormat = format.printf(({ timestamp, level, message, stack, url, data, ...meta }) => {
const logLevel = level.toUpperCase();
const urlInfo = url ? ` | URL: ${url}` : "";
const dataInfo = data ? ` | Data: ${JSON.stringify(data)}` : "";
return `${timestamp} [${logLevel}]: ${message}${stack ? ` | Stack: ${stack}` : ""}${urlInfo}${dataInfo}${Object.keys(meta).length ? ` | Meta: ${JSON.stringify(meta)}` : ""}`;
const metaInfo = Object.keys(meta).length ? ` | Meta: ${JSON.stringify(meta, null, 2)}` : "";

return `${timestamp} [${logLevel}]: ${message}${stack ? `\nStack: ${stack}` : ""}${urlInfo}${dataInfo}${metaInfo}`;
});

const logger = createLogger({
Expand All @@ -22,15 +24,15 @@ const logger = createLogger({
defaultMeta: { service: "service" },
transports: [
new transports.DailyRotateFile({
filename: path.join(logDirectory, "error-%DATE%.log"),
filename: path.join(logDirectory, "%DATE%-error.log"),
datePattern: "DD-MM-YYYY",
level: "error",
maxSize: "20m",
maxFiles: "14d",
zippedArchive: true,
}),
new transports.DailyRotateFile({
filename: path.join(logDirectory, "combined-%DATE%.log"),
filename: path.join(logDirectory, "%DATE%-combined.log"),
datePattern: "DD-MM-YYYY",
maxSize: "20m",
maxFiles: "14d",
Expand All @@ -42,9 +44,15 @@ const logger = createLogger({
if (process.env.NODE_ENV !== "production") {
logger.add(
new transports.Console({
format: format.combine(format.colorize(), customFormat),
level: "debug",
format: format.combine(
format.colorize({ all: true }),
format.timestamp({ format: "DD-MM-YYYY HH:mm:ss" }),
consoleFormat
),
})
);
}


export default logger;

1 comment on commit 524a50a

@vercel
Copy link

@vercel vercel bot commented on 524a50a Sep 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.