Trong một dự án nói chung và một dự án NodeJS thì logger đóng một vai trò cực kỳ quan trọng để có thể lưu vết lại các thông tin của việc truy cập API và xử lý yêu cầu, phục vụ cho việc gỡ lỗi khi có vấn đề xảy ra. Trong bài này chúng ta sẽ cùng nhau tìm hiểu về cách kết hợp giữa hai thư viện winston và morgan để làm logger nhé.

Khởi tạo dự án

Chúng ta sẽ khởi tạo thư mục có tên log-example và một tập tin có tên main.js

Thư viện winston

Đây là một thư viện hỗ trợ chúng ta tạo đối tượng logger và sử dụng đối tượng logger này để ghi log ra console hoặc file, ví dụ:

const winston = require("winston");

const logger = winston.createLogger({
    level: "info",
    format: winston.format.combine(
      winston.format.timestamp(),
      winston.format.json()
    ),
    transports: [
      new winston.transports.Console(),
      new winston.transports.File({ filename: "logs/server.log" }),
    ]
  });

logger.info("start program");

Ở đây chúng ta tạo ra một đối tượng logger với:

  1. level là info (ngoài ra bạn cũng có thể chọn một trong các level khác như debug, warn, error).
  2. định dạng của 1 dòng log có thêm timestamp và thông điệp.
  3. log sẽ được ghi cả ra file và console.

Thư viện morgan

Đây là một thư viện dang middleware của express, nó cho phép log các thông tin của việc gọi API qua express kiểu thế này:

Mã nguồn ví dụ sử dụng morgan như sau:

const express = require('express');
const morgan = require('morgan');
const fs = require('fs');
const path = require('path');

const app = express();

const accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' });

app.use(morgan('combined', { stream: accessLogStream }));

app.get('/', (req, res) => {
  res.send('Hello, Morgan Logger with file!');
});

app.listen(3000, () => {
  console.log(`Server is running on port 3000`);
});

Ở đây chúng ta sẽ lưu thông tin log từ việc gọi API vào tập tin access.log.

Kết hợp hai thư viện winston và morgan

Như bạn thấy ở trên thì với thư viện winston chúng ta lưu log ra tập tin logs/server.log còn vơi morgan thì lại lưu ra tập tin access.log, như vậy rất bất tiện, vậy nên chúng ta có thể kết hợp sử dụng hai thư viện theo mô hình thế này:

Log sẽ được thư viện morgan ghi nhận, sau đó sẽ được thông qua winston để ghi vào file hoặc console với mã nguồn như sau:

const winston = require("winston");
const express = require('express');
const morgan = require('morgan');

const logger = winston.createLogger({
    level: "info",
    format: winston.format.combine(
      winston.format.timestamp(),
      winston.format.json()
    ),
    transports: [
      new winston.transports.Console(),
      new winston.transports.File({ filename: "logs/server.log" }),
    ]
  });

logger.info("start program");

const app = express();

app.use(morgan('combined', {
    stream: {
        write: (message) => logger.info(message.trim())
    }
}));

app.get('/', (req, res) => {
    res.send('Hello, World!');
});

app.listen(3000, () => {
    logger.info('Server running on port 3000');
});

Khởi chạy chương trình

Chúng ta có thể khởi chạy chương trình thông qua lệnh: node main.js, sau đó gọi API http://localhost:3000/ và chúng ta sẽ nhận được log được in ra cả ở console và file logs/server.log như sau:

{"level":"info","message":"start program","timestamp":"2024-08-29T04:07:44.388Z"}
{"level":"info","message":"Server running on port 3000","timestamp":"2024-08-29T04:07:44.403Z"}
{"level":"info","message":"::1 - - [29/Aug/2024:04:07:59 +0000] \"GET / HTTP/1.1\" 200 13 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36\"","timestamp":"2024-08-29T04:07:59.441Z"}
{"level":"info","message":"::1 - - [29/Aug/2024:04:07:59 +0000] \"GET /favicon.ico HTTP/1.1\" 404 150 \"http://localhost:3000/\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36\"","timestamp":"2024-08-29T04:07:59.766Z"}

Tổng kết

Như vậy chúng ta đã cùng nhau tạo tìm hiểu về 2 thư viện logger là winston và morgan.


Cám ơn bạn đã quan tâm đến bài viết|video này. Để nhận được thêm các kiến thức bổ ích bạn có thể:

  1. Đọc các bài viết của TechMaster trên facebook: https://www.facebook.com/techmastervn
  2. Xem các video của TechMaster qua Youtube: https://www.youtube.com/@TechMasterVietnam nếu bạn thấy video/bài viết hay bạn có thể theo dõi kênh của TechMaster để nhận được thông báo về các video mới nhất nhé.
  3. Chat với techmaster qua Discord: https://discord.gg/yQjRTFXb7a