Chuyển đến nội dung chính
LogBrew là nền tảng observability (khả năng quan sát) cho lập trình viên và agent lập trình, có gói miễn phí rộng rãi và không cần thẻ thanh toán. Structured logging ghi mỗi bản ghi log thành các trường có tên, không phải một dòng văn bản tự do. Nhờ đó, chương trình, con người hoặc agent lập trình có thể lọc bản ghi theo trường, đếm chúng và liên kết chúng với trace của một yêu cầu.

Log dạng văn bản và log có cấu trúc

Log dạng văn bản này có cùng thông tin với log có cấu trúc bên dưới.
Để tìm mọi lần thanh toán thất bại của 1 đơn hàng trong log văn bản, bạn phải viết một mẫu cho từng biến thể thông điệp. Trong log có cấu trúc, bạn lọc theo message và order_id. Thông điệp giữ nguyên cho mọi đơn hàng, nên bạn cũng đếm được nó.

Chọn định dạng log

Dùng JSON, mỗi dòng 1 đối tượng. Dùng cùng tên trường trong mọi dịch vụ. Bảng này liệt kê các trường cơ bản và tên tương ứng trong mô hình dữ liệu log của OpenTelemetry và trong LogBrew. Số mức độ nghiêm trọng của OpenTelemetry đi từ 1 đến 24. INFO bắt đầu ở 9, WARN ở 13, ERROR ở 17 và FATAL ở 21. LogBrew nhận trực tiếp log OTLP. Xem Gửi dữ liệu OpenTelemetry.

Best practice cho logging

Giữ thông điệp cố định

Viết "payment failed" và đặt mã đơn hàng vào một trường. Thông điệp cố định giúp bạn nhóm, đếm và đặt alert cho 1 loại sự kiện.

Dùng 1 tên cho mỗi trường

Chọn order_id hoặc orderId một lần và dùng nó trong mọi dịch vụ. Với các trường phổ biến, dùng tên theo semantic convention của OpenTelemetry, ví dụ http.response.status_code.

Chọn mức log theo việc cần làm

error nghĩa là một thao tác đã thất bại. warning nghĩa là chương trình đã phục hồi. info xác nhận công việc diễn ra bình thường. Chỉ dùng debug khi bạn đang tìm lỗi.

Ghi thời gian theo UTC

Dùng RFC 3339 có mili giây và độ lệch múi giờ, ví dụ 2026-11-07T14:21:19.773+00:00. Nếu thiếu UTC và mili giây, các bản ghi từ những múi giờ khác nhau, hoặc các bản ghi trong cùng một giây, sẽ bị sắp xếp sai thứ tự.

Thêm trace ID và span ID

Với các ID này, bạn đọc được mọi log của 1 yêu cầu qua nhiều dịch vụ.

Đặt dịch vụ, môi trường và bản phát hành một lần

Cấu hình chúng khi khởi động, không cấu hình trong từng lời gọi. Nếu thiếu bản phát hành, bạn không biết lần triển khai nào gây ra thay đổi.

Ghi log một lỗi một lần, tại nơi xử lý nó

Thêm loại lỗi và thông điệp lỗi. Đừng ghi log lại cùng một lỗi ở mỗi tầng.

Không ghi secret và dữ liệu cá nhân

Đừng ghi log mật khẩu, token, cookie, body của yêu cầu, hoặc URL đầy đủ có query string. Dùng tính năng che dữ liệu của logger. Xem Che dữ liệu log.

Dùng tên trường cố định

Đừng dùng giá trị làm tên trường, ví dụ {"ord_1001": "failed"}. Khi đó, mỗi giá trị mới lại thêm một trường mới, và 1 bộ lọc không thể tìm hết các đơn hàng.

Ghi JSON ra standard output trong production

Chỉ dùng định dạng dễ đọc khi phát triển.

Structured logging trong Python

Module logging chuẩn không có formatter JSON. Formatter này ghi các trường cơ bản và các giá trị từ extra={"fields": {...}}.
Để gửi cùng các bản ghi đó đến LogBrew, thêm LogBrewLoggingHandler. Handler này gửi thông điệp, mức log và logger dưới dạng trường, và gửi các giá trị nguyên thủy trong extra dưới dạng metadata. Xem Logging trong Python.

Structured logging trong Node.js

Mặc định, Pino ghi 1 dòng JSON cho mỗi bản ghi. Winston ghi JSON với winston.format.json(). Cả hai đều giữ các trường từ lời gọi và từ logger con. Xem Logging trong Node.js để biết cách thiết lập cả hai và cách đưa trace ID vào log Express.

Tìm kiếm log có cấu trúc trong LogBrew

LogBrew lưu mỗi log cùng thông điệp, mức, logger, metadata và trace của log đó. Lọc theo các trường này từ CLI.
API cũng lọc được theo giá trị metadata có kiểu, ví dụ một số từ 500 trở lên. Xem Bộ lọc truy vấn.