Structured Logging: Ghi Log Sao Cho Đỡ Đau Về Sau

Log Text — Đọc Được Nhưng Không Query Được
Hệ thống vừa gặp lỗi. Mở log ra thấy dòng này:
2026-05-15 07:23:01 ERROR Something went wrong with user 12345
Đọc được. Nhưng muốn filter tất cả error của user 12345 trong 24h qua? Grep rồi đếm tay. Muốn biết request nào có latency trên 2s? Không biết bắt đầu từ đâu. Muốn tạo dashboard cảnh báo? Không có field nào để group by.
Đó là vấn đề của log dạng plain text. Con người đọc được, máy tính thì không.
Structured logging giải quyết bài toán này: mỗi log entry là một object có schema cố định, sẵn sàng cho query, filter, aggregate.
Structured Logging Là Gì?
Thay vì ghi log dạng chuỗi text, structured logging ghi dưới dạng key-value pairs — thường là JSON. Mỗi entry có cùng một schema, giúp công cụ log (Elasticsearch, Loki, CloudWatch) index và query hiệu quả.
Plain text:
2026-05-15 07:23:01 ERROR [UserService] Failed to fetch user 12345: timeout after 3000ms
Structured:
{
"timestamp": "2026-05-15T07:23:01Z",
"level": "error",
"service": "UserService",
"message": "Failed to fetch user",
"userId": "12345",
"duration_ms": 3000,
"error": "timeout",
"requestId": "req-abc-123"
}
Cùng một thông tin. Nhưng phiên bản structured cho phép filter theo userId, group theo service, alert khi duration_ms > 2000.
Ba Nguyên Tắc Cốt Lõi
1. Schema cố định — mọi entry cùng format
Chọn một format JSON và giữ nguyên xuyên suốt hệ thống. Các field bắt buộc: timestamp, level, service, message. Thêm field business tuỳ context: userId, orderId, requestId.
2. Correlation ID — trace request qua các service
Mỗi request sinh một ID duy nhất (thường từ gateway). ID này đi xuyên suốt toàn bộ flow — qua middleware, service, database query. Khi cần debug, chỉ cần search theo correlation ID là thấy toàn bộ hành trình.
3. Log level — đúng lúc, đúng chỗ
debug: chi tiết kỹ thuật, chỉ bật khi cầninfo: sự kiện bình thường (user login, order created)warn: bất thường nhưng chưa lỗi (retry, fallback)error: sự cố cần can thiệp
Production chỉ log từ info trở lên. Bật debug khi cần trace.
Ví Dụ Nhanh Với NodeJS
Dùng pino — thư viện structured logging nhanh nhất cho NodeJS:
import pino from "pino";
const logger = pino({
level: process.env.LOG_LEVEL || "info",
formatters: {
level: (label) => ({ level: label }),
},
base: { service: "user-service" },
});
// Usage
logger.info({ userId: "12345", action: "login" }, "User logged in");
logger.error({ userId: "12345", err: timeoutError }, "Failed to fetch user");
Output mỗi dòng là một object JSON hoàn chỉnh. Pipe vào stdout, collect bằng Fluentd hoặc Vector, gửi lên Elasticsearch hoặc Loki.
Checklist Áp Dụng
- Chọn structured logging library (pino cho NodeJS, zerolog cho Go, structlog cho Python)
- Định nghĩa schema log chung cho toàn team
- Thêm correlation ID ở middleware đầu tiên
- Tạo dashboard cảnh báo dựa trên log level và latency
- Bật debug log qua environment variable, không hardcode
Đây là bài thứ 3 trong series DevOps Handbook. Bài trước: Platform Engineering & Internal Developer Platform. Bài tiếp theo: CI/CD Pipeline với GitHub Actions.