- vừa được xem lúc

Xây dựng hệ thống xử lí lỗi bằng NodeJS

0 0 7

Người đăng: tuananhhedspibk

Theo Viblo Asia

Dịch từ nguồn

Xử lí lỗi không chỉ đơn thuần là giảm thời gian tìm bug cho dev mà còn là xây dựng một codebase với quy mô tương xứng với hệ thống của bạn

Các loại lỗi trong NodeJS

Trong Node.js có 2 loại errors chính:

  • Operational errors: runtime error, một số ví dụ: "Out of memory", "An invalid input for an API endpoint"
  • Programmer errors: unexpected bugs, bản thân code có những vấn đề cần phải giải quyết. Ví dụ tiêu biểu: đọc property của "undefined" object. Các bug này thường do dev tạo nên chứ không liên quan đến operation.

Xử lí lỗi

Với các lỗi đã được định nghĩa sẵn bởi Node.js, ta sẽ dễ dàng theo dõi thông tin xung quanh nó nhờ Stacktrace → từ đó ta có thể tìm ra nguyên nhân gốc rễ của lỗi.

Ngoài ra việc extends từ Error class cũng như bổ sung các thuộc tính khác như HTTP status code cũng sẽ giúp cho thông tin về lỗi trở nên chi tiết hơn

class BaseError extends Error { public readonly name: string; public readonly httpCode: HttpStatusCode; public readonly isOperational: boolean; constructor( name: string, httpCode: HttpStatusCode, description: string, isOperational: boolean, ) { super(description); Object.setPrototypeOf(this, new.target.prototype); this.name = name; this.httpCode = httpCode; this.isOperational = isOperational; Error.captureStackTrace(this); }
} // free to extend from BaseError
class APIError extends BaseError { constructor(name, httpCode = HttpStatusCode.INTERNAL_SERVER, isOperational = true, description = 'Internal Server Error') { super(name, httpCode, isOperational, descritpion); }
}

Một vài httpStatusCode cơ bản có thể thêm ở đây:

export enum HttpStatusCode { OK = 200, BAD_REQUEST = 400, NOT_FOUND = 404, INTERNAL_SERVER = 500,
}

Cách sử dụng như sau:

const user = await User.getById(1); if (!user) { throw new APIError( 'NOT FOUND', HttpStatusCode.NOT_FOUND, true, 'detailed explanation' );
}

Xử lí lỗi bằng NodeJS một cách tập trung

Việc xây dụng một component với chức năng để xử lí lỗi sẽ giúp giảm thiểu đi việc trùng lặp code xử lí lỗi trong project. Component này chịu trách nhiệm cho việc giúp cho lỗi bắt được trở nên dễ hiểu hơn ví dụ như:

  • Gửi thông báo đến system admin
  • Chuyển event error đến monitoring service như Sentry.io và log chúng ra

File_000

Trước khi được gửi đến error-handling centralized thì lỗi sẽ được gửi đến error-handling middleware để tiến hành phân biệt giữa các error types.

try { userSerivce.addNewUser(req.body).then((newUser: User) => { res.status(200).json(newUser); }).catch ((error: Error) => { next(error); });
}

Và Error-handling centralized sẽ trông như sau:

export class ErrorHandler { public async handleError(err: Error): Promise<void> { await logger.error( 'Error message from the centralized error-handling component', err, ); await sendToSlack(); await sendEventsToSentry(); } public isTrustedError(error: Error) { if (error instanceOf BaseError) { return error.isOperational; } return false; }
}

Để dev có thể theo dõi bug một cách dễ dàng hơn, hãy tiến hành log error ra theo một format dễ nhìn nhất.

Một vài logger formatter tiêu biểu như:

Hai thư viện này sẽ giúp cung cấp log ở các format level khác nhau tuỳ theo level của error.

Với các Programmer errors, cách giải quyết tốt nhất đó là B1. Crash app ngay lập tức B2. Restart lại app với các tool như pm2

Nguyên nhân là bởi Programmer errors thường sẽ làm cho app kết thúc với một state không như mong muốn.

process.on('uncaughtException', (error: Error) => { errorHandler.handleError(error); if (!errorHandler.isTrustedError(error)) { process.exit(1); }
});

Với promies rejection ta có thể làm như sau:

// get the unhandled rejection and throw it to another fallback handler we already have.
process.on('unhandledRejection', (reason: Error, promise: Promise<any>) => { throw reason;
}); process.on('uncaughtException', (error: Error) => { errorHandler.handleError(error); if (!errorHandler.isTrustedError(error)) { process.exit(1); }
});

Bình luận

Bài viết tương tự

- vừa được xem lúc

Cách Mình Viết Một NPM Module - Phần I: Lên Ý Tưởng Và Code

Mình thì thi thoảng mình cũng viết vài module trên npm để phục vụ cho công việc của riêng mình, và khi đẩy lên npmjs cũng là một cách gì đó để mình giúp đỡ cộng đồng lập trình viên khỏi phải làm lại c

0 0 23

- vừa được xem lúc

Tối ưu Docker Image cho NextJS

Docker image của NextJS thông thường size sẽ rất lớn. Bài viết này mình sẽ.

0 0 12

- vừa được xem lúc

Handling Error trong Golang

Go không có phương thức try/catch như thông thường để xử lý lỗi, thay vào đó lỗi sẽ được trả về như một giá trị. error được tích hợp sẵn trong Go với giá trị mặc định là nil.

0 0 22

- vừa được xem lúc

errors and how to fix them

fcking semicolon error http request. some backend handle http header differently, in this example charset for content-type header is invalid then the whole content-type header is not working.

0 0 23

- vừa được xem lúc

[Zabbix] - Incorrect characterset for Zabbix database "latin1" instead "UTF8, UTF8MB3"

NGUYÊN NHÂN. Lỗi này thường gặp kết nối với Database sau khi tải xong Zabbix.

0 0 15