Logging và observability trong web/app: ghi đủ để hiểu hệ thống, nhưng đừng biến log thành bãi rác

39 lượt xem · 4 trả lời

1. 10:33 06/08/2026
Khi ứng dụng còn nhỏ, nhiều đội chỉ cần mở console hoặc xem vài dòng log là đoán được lỗi. Nhưng khi hệ thống có nhiều API, worker, database, cache, dịch vụ bên thứ ba và người dùng thật, câu hỏi “vì sao tính năng này chậm/lỗi?” sẽ khó trả lời hơn rất nhiều. Đây là lúc logging và observability trở thành một phần quan trọng của phát triển web/app, không chỉ là việc “in lỗi ra màn hình”. Logging là gì? Logging là việc ghi lại các sự kiện xảy ra trong hệ thống: request đi vào, thao tác quan trọng, lỗi, thời gian xử lý, trạng thái thanh toán, kết quả gọi API bên ngoài... Log tốt giúp lập trình viên điều tra sự cố nhanh hơn, hiểu hành vi thật của hệ thống và phát hiện vấn đề trước khi người dùng phàn nàn quá nhiều. Ví dụ thực tế: người dùng báo “tôi bấm thanh toán nhưng không thấy đơn hàng”. Nếu hệ thống có log tốt, bạn có thể lần theo: - Request tạo đơn hàng có tới server không? - User ID và order ID liên quan là gì? - Cổng thanh toán trả về thành công, thất bại hay timeout? - Worker xử lý xác nhận thanh toán có chạy không? - Email/thông báo đã được gửi chưa? Nếu không có log, việc điều tra thường biến thành đoán mò. Đừng chỉ log lỗi, hãy log cả ngữ cảnh Một dòng log kiểu “Payment failed” thường chưa đủ hữu ích. Nên có thêm ngữ cảnh để truy vết, ví dụ: - request_id hoặc correlation_id để nối các log của cùng một request - user_id nếu phù hợp - order_id, payment_id hoặc mã nghiệp vụ liên quan - tên hành động đang xử lý - trạng thái trả về từ dịch vụ bên ngoài - thời gian xử lý Ví dụ nội dung log tốt hơn: “payment_failed request_id=abc123 user_id=42 order_id=981 gateway_status=timeout duration_ms=3200”. Khi đọc dòng này, bạn đã có hướng điều tra rõ hơn nhiều. Các mức log nên dùng có chủ đích Một lỗi phổ biến là log gì cũng để error, hoặc ngược lại chỉ log khi hệ thống đã hỏng nặng. Có thể phân biệt đơn giản: - debug: thông tin chi tiết khi phát triển hoặc điều tra sâu, không nên bật tràn lan ở production - info: sự kiện bình thường nhưng quan trọng, như tạo đơn hàng thành công, user đăng nhập, job hoàn tất - warn: dấu hiệu bất thường nhưng chưa làm hỏng luồng chính, ví dụ API bên ngoài chậm hoặc retry lần đầu - error: lỗi làm thao tác thất bại, cần được theo dõi - fatal/critical: sự cố nghiêm trọng khiến dịch vụ không thể tiếp tục hoạt động bình thường Dùng đúng mức log giúp đội vận hành lọc thông tin dễ hơn và tránh bị “chai lì” trước quá nhiều cảnh báo không quan trọng. Cẩn thận với dữ liệu nhạy cảm Log rất hữu ích nhưng cũng có thể trở thành rủi ro bảo mật nếu ghi bừa bãi. Không nên log mật khẩu, access token, refresh token, số thẻ, mã OTP, cookie phiên đăng nhập hoặc dữ liệu cá nhân không cần thiết. Với email, số điện thoại, địa chỉ, hãy cân nhắc che một phần hoặc chỉ log ID nội bộ. Một nguyên tắc thực tế: trước khi thêm log, hãy tự hỏi “nếu dòng này bị lộ hoặc được nhiều người nội bộ đọc, có gây rủi ro cho người dùng không?”. Observability rộng hơn logging Logging chỉ là một phần. Observability thường gồm ba mảng chính: - Logs: chuyện gì đã xảy ra? - Metrics: hệ thống đang hoạt động ra sao theo thời gian? Ví dụ số request, tỷ lệ lỗi, độ trễ, CPU, RAM, số job đang chờ. - Traces: một request đi qua những dịch vụ nào, mất bao lâu ở từng bước? Với ứng dụng đơn giản, log có thể đủ. Nhưng khi có nhiều service, trace giúp thấy rõ request bị chậm ở database, cache, service thanh toán hay đoạn xử lý nội bộ. Lời khuyên có thể áp dụng ngay 1. Thêm request_id cho mỗi request Mỗi request nên có một ID duy nhất. Khi backend gọi sang service khác hoặc đẩy job vào hàng đợi, hãy truyền ID này đi cùng nếu có thể. Nhờ vậy, bạn có thể tìm toàn bộ log liên quan đến một thao tác của người dùng. 2. Log các điểm nghiệp vụ quan trọng Không cần log từng dòng code. Hãy log ở các mốc có ý nghĩa: tạo đơn hàng, xác nhận thanh toán, gửi email, đổi trạng thái tài khoản, cập nhật gói dịch vụ, đồng bộ dữ liệu. 3. Đo thời gian xử lý Với API hoặc job quan trọng, nên ghi duration. Một lỗi “không xảy ra” nhưng xử lý mất 10 giây vẫn là vấn đề trải nghiệm. 4. Chuẩn hóa cấu trúc log Nếu có thể, dùng log dạng có cấu trúc với các trường rõ ràng như level, timestamp, request_id, user_id, action, message. Log có cấu trúc dễ tìm kiếm và phân tích hơn log văn bản tự do. 5. Thiết lập cảnh báo dựa trên tín hiệu quan trọng Đừng gửi cảnh báo cho mọi dòng error nhỏ. Hãy cảnh báo khi tỷ lệ lỗi tăng, API quá chậm, queue tồn đọng lâu, số lần thanh toán thất bại tăng bất thường hoặc service quan trọng không phản hồi. Kết luận Logging và observability không phải phần “trang trí” sau khi code xong. Chúng là công cụ giúp đội phát triển hiểu hệ thống trong môi trường thật. Một hệ thống có log tốt sẽ tiết kiệm rất nhiều thời gian khi debug, giảm thời gian xử lý sự cố và giúp ra quyết định kỹ thuật tự tin hơn. Hãy bắt đầu từ những việc nhỏ: thêm request_id, log các hành động nghiệp vụ quan trọng, tránh ghi dữ liệu nhạy cảm và đo thời gian xử lý ở các luồng chính.
0 Facebook
2. 23:42 09/10/2026
Trả lời Quản Trị Viên Khi ứng dụng còn nhỏ, nhiều đội chỉ cần mở console hoặc xem vài dòng log là đoán được lỗi. Nhưng khi hệ thống có nhiều A…
Tôi hoàn toàn đồng ý rằng logging chỉ trở nên hữu ích khi có ngữ cảnh phù hợp. Việc thêm request_id duy nhất cho mỗi yêu cầu và truyền nó qua các service giúp việc truy vết trở nên liền mạch hơn nhiều so với việc chỉ dựa vào timestamp. Tôi cũng đã thấy hiệu quả khi sử dụng các level log có mục đích: info cho các hành động kinh doanh thành công như tạo đơn hàng, warn cho các retry API bên ngoài lần đầu, và error chỉ cho các lỗi thực sự làm gián đoạn luồng xử lý. Điều mà nhiều đội bỏ qua là việc chuẩn hóa cấu trúc log – một đối tượng JSON với các trường như request_id, user_id, action, duration_ms, và gateway_status giúp việc phân tích sau này trở nên dễ dàng hơn rất nhiều so với các dòng văn bản tự do. Cuối cùng, chúng tôi đã áp dụng quy tắc “không log dữ liệu nhạy cảm”: bất kỳ log nào chứa password, token, hoặc số thẻ tín dụng đều bị loại bỏ trước khi ghi vào hệ thống. Bạn đã áp dụng request_id trong hệ thống của mình chưa, và bạn gặp khó khăn gì khi triển khai logging có cấu trúc?
0
3. 14:49 11/10/2026
Trả lời Quản Trị Viên Khi ứng dụng còn nhỏ, nhiều đội chỉ cần mở console hoặc xem vài dòng log là đoán được lỗi. Nhưng khi hệ thống có nhiều A…
Bài viết đã chỉ ra rất đúng rằng log chỉ thực sự có giá trị khi đi kèm ngữ cảnh – tôi đặc biệt đánh giá cao ví dụ “payment_failed request_id=abc123 …” vì nó giúp việc điều tra trở nên nhanh chóng. Một mẹo nhỏ mà nhóm của tôi đã áp dụng là sử dụng JSON có cấu trúc cho hầu hết log nghiệp vụ, điều này giúp chúng tôi dễ dàng lọc request_id, user_id hoặc order_id mà không cần phân tích chuỗi. Ngoài ra, chúng tôi chỉ định cấu hình logging ở mức độ phù hợp trong môi trường production (ví dụ: info cho các thao tác thành công, warn cho các retry) và bật debug theo yêu cầu thay vì ghi lại mọi thứ. Bạn đã bao giờ gặp tình huống thiếu dấu vết rõ ràng giữa các microservice chưa? Bạn đã thử sử dụng correlation_id trên toàn bộ hệ thống chưa?
0
4. 20:48 13/10/2026
Trả lời Hoàng Sơn Bài viết đã chỉ ra rất đúng rằng log chỉ thực sự có giá trị khi đi kèm ngữ cảnh – tôi đặc biệt đánh giá cao ví dụ “payme…
JSON có cấu trúc thực sự giúp team mình truy vết lỗi nhanh hơn rất nhiều, đặc biệt khi gắn correlation_id xuyên suốt các service. Chúng tôi thường sinh một request_id duy nhất ngay tại gateway, sau đó truyền nó qua header (x‑request‑id) cho mọi downstream service; mỗi service chỉ cần log thêm trường đó vào entry JSON. Khi cần điều tra, chỉ cần filter theo request_id trên ELK/Loki là thấy toàn bộ chuỗi gọi. Về level log, production chỉ bật info cho thành công, warn cho retry/timeout, debug chỉ bật tạm thời qua feature flag khi incident. Một lưu ý nhỏ: tránh log toàn bộ payload nhạy cảm (token, PII) – hãy mask hoặc chỉ log hash. Bạn đã thử triển khai OpenTelemetry để tự động propagate trace‑id thay vì tự viết middleware chưa?
0
5. 20:45 25/10/2026
Trả lời Hoàng Tuấn Tôi hoàn toàn đồng ý rằng logging chỉ trở nên hữu ích khi có ngữ cảnh phù hợp. Việc thêm request_id duy nhất cho mỗi yêu…
Trong hệ thống của mình, request_id được sinh ở gateway rồi truyền qua header X-Request-ID, service nào nhận cũng đọc lại và gắn vào context. Cái khó nhất không nằm ở request đồng bộ mà ở công việc chạy nền: job queue, cron, consumer message thường mất context nên log ra toàn ID rỗng. Mình xử lý bằng cách nhét request_id vào payload message và khôi phục ở đầu consumer, đồng thời đặt mặc định một giá trị như
0
Vui lòng đăng nhập để tham gia trả lời chủ đề này.
Điều hướng nhanh

Bạn muốn khám phá điều gì?

Tìm chủ đề, bài viết hoặc đi thẳng đến một khu vực của cộng đồng.

Esc để đóng Ctrl K để mở lại