Log có cấu trúc vs log chuỗi
Log chuỗi: console.log(“User login failed”) — không biết user nào, lúc nào, ở service nào. Log có cấu trúc dùng JSON: mỗi field tìm kiếm được, lọc được, vẽ biểu đồ được.
// File: log.js
// ❌ Log chuỗi: khó tìm, khó lọc
console.log("Login failed for user " + email)
// ✅ Log có cấu trúc: JSON, tìm kiếm được
logger.warn({
event: "login_failed",
email: email,
ip: req.ip,
reason: "wrong_password",
timestamp: new Date().toISOString(),
requestId: req.id,
})
Công cụ tập trung log
| Công cụ | Vai trò | Free/Paid |
|---|---|---|
| ELK (Elasticsearch + Logstash + Kibana) | Self-hosted, mạnh nhất | Free (self-managed) |
| Loki + Grafana | Nhẹ hơn ELK, tích hợp Grafana | Free (self-managed) |
| Datadog | SaaS, dễ dùng, đắt | Paid |
| Pino (Node.js) | Library ghi JSON log nhanh | Free |
Correlation ID: truy vết xuyên service
Khi request đi qua nhiều service, mỗi service log riêng. Làm sao biết log nào thuộc cùng request? Gắn correlation ID (request ID) vào mỗi log — tìm theo ID này sẽ thấy toàn bộ hành trình.
// File: correlation.js
import { v4 as uuid } from 'uuid'
// Middleware tạo correlation ID cho mỗi request
function correlationMiddleware(req, res, next) {
req.correlationId = req.headers['x-correlation-id'] || uuid()
res.setHeader('x-correlation-id', req.correlationId)
next()
}
// Mọi log entry đều gắn correlationId
function logRequest(req, message, data = {}) {
logger.info({
correlationId: req.correlationId,
method: req.method,
path: req.path,
message,
...data,
})
}
TUYỆT ĐỐI không log: mật khẩu, token, số thẻ tín dụng, CMND. Dùng hàm mask trước khi log: email → t***@gmail.com, card → ****1234.
❓ Correlation ID giải quyết vấn đề gì?
- Viết log có cấu trúc JSON thay vì chuỗi
- Biết ít nhất 2 công cụ tập trung log
- Triển khai correlation ID middleware
- Không log dữ liệu nhạy cảm