Ghi Log vào File trong Node.js với LogLayer
Ghi log vào file là một phần quan trọng trong việc giám sát và debug ứng dụng trong môi trường production. Trong bài viết này, chúng ta sẽ tìm hiểu cách quản lý log trong ứng dụng Node.js một cách hiệu quả bằng cách sử dụng LogLayer cùng với Log File Rotation Transport, một thư viện logging mạnh mẽ và linh hoạt.
LogLayer là gì?
LogLayer là một thư viện logging hiện đại, được thiết kế ưu tiên cho TypeScript, cung cấp một API rõ ràng và trực quan để ghi log có cấu trúc. Nó hoạt động như một lớp trung gian trên các thư viện logging phổ biến như winston hoặc pino.
Tại sao nên sử dụng LogLayer để ghi log vào file?
- Tự động xoay vòng log theo dung lượng hoặc thời gian để tránh log file quá lớn.
- Hỗ trợ nén log để tiết kiệm dung lượng lưu trữ.
- Cơ chế batching giúp cải thiện hiệu suất ghi log.
- Định dạng log linh hoạt, dễ đọc và phân tích.
- Tự động dọn dẹp log cũ, giúp duy trì hệ thống logging sạch sẽ và tối ưu.
Để bắt đầu
Đầu tiên, cài đặt các gói cần thiết:
npm install loglayer @loglayer/transport-log-file-rotation serialize-error
Thiết lập ghi tệp Log cơ bản
Sau đây là một ví dụ cơ bản về cách thiết lập ghi tệp Log:
import { LogLayer } from "loglayer";
import { LogFileRotationTransport } from "@loglayer/transport-log-file-rotation";
import { serializeError } from "serialize-error";
const logger = new LogLayer({
errorSerializer: serializeError,
transport: [
new LogFileRotationTransport({
filename: "./logs/app.log"
}),
],
});
// Start logging!
logger.withMetadata({
port: 3000,
}).info("Application started");
logger
.withError(new Error("Something went wrong"))
.error("An error occurred");
Thêm ngữ cảnh và siêu dữ liệu
LogLayer cung cấp một số cách để làm phong phú thêm thông tin cho nhật ký của bạn:
1. Sử dụng ngữ cảnh
Bối cảnh là dữ liệu liên tục áp dụng cho tất cả các mục nhật ký tiếp theo:
import { hostname } from "node:os";
const logger = new LogLayer({
transport: [
new LogFileRotationTransport({
filename: "./logs/app.log"
}),
],
});
// Add context that will be included in all subsequent logs
const contextLogger = logger.withContext({
hostname: hostname(),
environment: process.env.NODE_ENV,
version: process.env.npm_package_version
});
contextLogger.info("Server starting"); // Will include context
contextLogger.error("Connection failed"); // Will include same context
2. Sử dụng siêu dữ liệu
Siêu dữ liệu là dữ liệu một lần chỉ áp dụng cho mục nhật ký hiện tại:
// Add metadata for a single log entry
logger.withMetadata({
requestId: "123",
duration: 45,
statusCode: 200
}).info("Request processed");
// Different metadata for different log entries
logger.withMetadata({
userId: "user-456",
action: "login"
}).info("User logged in");
// Combine context and metadata
const userLogger = logger.withContext({ service: "user-service" });
userLogger.withMetadata({
duration: 123,
status: "success"
}).info("Operation completed");
3. Dữ liệu tĩnh trong vận chuyển
Bạn cũng có thể cấu hình dữ liệu tĩnh ở cấp độ truyền tải:
const logger = new LogLayer({
transport: [
new LogFileRotationTransport({
filename: "./logs/app.log",
staticData: {
hostname: hostname(),
environment: process.env.NODE_ENV,
version: process.env.npm_package_version
}
}),
],
});
Điều này sẽ tạo ra các bản ghi như sau:
{
"level": "info",
"message": "Request processed",
"timestamp": "2024-01-17T12:34:56.789Z",
"hostname": "prod-server-1",
"environment": "production",
"version": "1.0.0",
"requestId": "123",
"duration": 45,
"statusCode": 200
}
Cấu hình nâng cao
1. Nhật ký luân phiên hàng ngày
Đối với các ứng dụng cần xoay vòng nhật ký hàng ngày:
const logger = new LogLayer({
transport: [
new LogFileRotationTransport({
filename: "./logs/app-%DATE%.log",
frequency: "daily",
dateFormat: "YMD",
compressOnRotate: true,
maxLogs: "7d" // Keep logs for 7 days
}),
],
});
2. Xoay dựa trên kích thước
Đối với các ứng dụng có khối lượng lớn, xoay vòng dựa trên kích thước tệp:
const logger = new LogLayer({
transport: [
new LogFileRotationTransport({
filename: "./logs/app.log",
size: "10M", // Rotate when file reaches 10 MB
maxLogs: 5, // Keep last 5 log files
compressOnRotate: true
}),
],
});
3. Tối ưu hóa hiệu suất với việc xử lý hàng loạt
Đối với các ứng dụng có thông lượng cao, hãy bật chế độ xử lý theo đợt để giảm I/O đĩa:
const logger = new LogLayer({
transport: [
new LogFileRotationTransport({
filename: "./logs/app.log",
batch: {
size: 1000, // Write after 1000 logs are queued
timeout: 5000 // Or after 5 seconds, whichever comes first
}
}),
],
});
Best pratice tốt nhất
1. Sử dụng tính năng xoay vòng
Luôn cấu hình xoay vòng nhật ký để tránh các vấn đề về dung lượng đĩa:
new LogFileRotationTransport({
filename: "./logs/app-%DATE%.log",
frequency: "daily",
maxLogs: "30d",
compressOnRotate: true
})
2. Bật tính năng xử lý theo lô cho khối lượng lớn
Đối với các ứng dụng có khối lượng nhật ký lớn:
new LogFileRotationTransport({
filename: "./logs/app.log",
batch: {
size: 1000,
timeout: 5000
}
})
3. Phân tách các bản ghi theo mối quan tâm
Sử dụng các phương thức vận chuyển khác nhau cho các loại bản ghi khác nhau:
const logger = new LogLayer({
transport: [
new LogFileRotationTransport({
filename: "./logs/app.log"
}),
new LogFileRotationTransport({
filename: "./logs/errors.log",
levelMap: {
error: "ERROR",
fatal: "FATAL"
}
})
],
});
4. Sử dụng ngữ cảnh và siêu dữ liệu một cách thích hợp
// Use context for values that remain constant
const serviceLogger = logger.withContext({
service: "user-service",
version: "1.0.0"
});
// Use metadata for request-specific information
serviceLogger.withMetadata({
requestId: "req-123",
duration: 45,
statusCode: 200
}).info("Request completed");
Xử lý lỗi
Việc tuần tự hóa lỗi đúng cách rất quan trọng khi gỡ lỗi:
import { serializeError } from "serialize-error";
const logger = new LogLayer({
errorSerializer: serializeError,
transport: [
new LogFileRotationTransport({
filename: "./logs/app.log"
}),
],
});
try {
throw new Error("Something went wrong");
} catch (error) {
logger.withError(error).error("Operation failed");
}
Kết luận
LogLayer cung cấp giải pháp mạnh mẽ và linh hoạt cho việc ghi nhật ký dựa trên tệp trong các ứng dụng Node.js. Với các tính năng như tự động xoay, nén và xử lý hàng loạt, giải pháp này giúp bạn duy trì nhật ký sạch và hiệu quả đồng thời đảm bảo bạn không bỏ lỡ thông tin quan trọng để gỡ lỗi và giám sát.
Hy vọng các bạn thấy thông tin trong bài hữu ích!
All rights reserved