Hầu hết mọi người chỉ nhận ra sự cần thiết của log khi họ cần nó nhất. Nhưng khi ứng dụng của bạn bị hỏng, khiếu nại của người dùng bắt đầu tràn vào, và bạn không có đâu để biết cách sửa chữa, thì đã quá muộn để thêm một số thông điệp log có thể đã giúp đỡ.
Log tốt trả giá cho chính nó gấp mười lần. Chúng làm cho việc chẩn đoán những bug khó dễ dàng như trở bàn tay, và nếu bạn làm log đúng cách, chúng thậm chí có thể cảnh báo cho bạn về sự cố trước cả khi người dùng nhận ra. Nhưng "làm log đúng cách" có nghĩa là gì?
Logging dễ bắt đầu nhưng khó thành thạo. Trong bài viết này, chúng ta sẽ đi sâu vào cách bạn có thể sử dụng log của ứng dụng Rails đến mức tận cùng.
Logging Trong Rails
Hãy nói về cơ bản trước. Khi bạn bắt đầu một ứng dụng Rails mới, logging đã được thiết lập sẵn cho bạn. Rails sẽ khởi tạo một instance mới của ActiveSupport::Logger mà bạn có thể sử dụng ở bất kỳ đâu trong ứng dụng.
Rails logger ghi ra standard output hoặc log/<environment>.log và sẽ tự động ghi log các yêu cầu đến hoặc các truy vấn được thực hiện ngoài các thông điệp log bạn viết rõ ràng.
Có nhiều cách để cấu hình log Rails, như được nêu rõ ràng trong tài liệu Rails.
Để tận dụng tối đa log của chúng ta, chúng ta đặc biệt quan tâm đến việc thiết lập log level (cấp độ log) cũng như log formatting (định dạng log).
Nhưng trước khi xử lý vấn đề đó, hãy nói về tại sao chúng ta nên viết log.
Logging Tốt, Logging Kém
Mục đích của log là thông báo cho bạn về các sự kiện hệ thống để bạn có thể phản ứng với chúng. Ví dụ, khi một lỗi xảy ra, thông điệp log nên nói cho bạn biết về nó theo một cách bạn có thể hiểu.
Mức độ bạn hiểu thông điệp log phụ thuộc vào mức độ mô tả và ngữ cảnh của nó. Một thông điệp log mô tả cung cấp thông tin liên quan về điều gì đã xảy ra. Một thông điệp log có ngữ cảnh bao gồm thông tin về trạng thái của hệ thống khi nó được ghi.
Hãy xem một ví dụ đơn giản để thấy tại sao chúng ta cần cả hai. Đây là một số mã gọi API bên ngoài và trả về phản hồi khi người dùng thực hiện yêu cầu.
Bây giờ hãy tưởng tượng một tình huống khách hàng báo cáo sự cố, và bạn nhìn vào log để tìm giúp đỡ. Đây là những gì bạn có thể thấy:
Các thông điệp log này cung cấp một số thông tin, nhưng không gần như đủ. Chúng ta không gần hơn việc tìm ra nguyên nhân gây ra lỗi khách hàng báo cáo. Các thông điệp log này thiếu tính mô tả và ngữ cảnh. Chúng chỉ là nhiễu. Làm thế nào để cải thiện chúng?
Log Levels Trong Rails
Default Rails logger cung cấp các log level DEBUG, INFO, WARN và ERROR. Sử dụng chúng, bạn có thể nhóm thông điệp log vào các danh mục liên quan khác nhau. Điều này không chỉ giúp bạn lọc thông điệp log, mà còn cung cấp một số ngữ cảnh.
Việc quyết định khi nào dùng log level nào có thể thách thức. Dưới đây là một số quy tắc ngón tay cái:
DEBUG: Dùng log level này cho thông tin chi tiết về các hành động xảy ra trong hệ thống. Bạn có thể dùng câu lệnh debug khi phương thức được vào hoặc thoát, hoặc bất cứ nơi nào bạn nghĩ nó có thể thêm giá trị trong quá trình debugging.INFO: Bất cứ khi nào hệ thống thay đổi trạng thái, hoặc sự kiện liên quan nào đó xảy ra, hãy dùng levelINFO. Ví dụ thông thường về info message trong bối cảnh Rails là yêu cầu nhận được, yêu cầu gửi đến API bên ngoài, hoặc job bắt đầu và kết thúc.WARN: Dùng log này để báo hiệu điều gì đó bất ngờ đã xảy ra. Nó chưa phải là vấn đề (vì ứng dụng của bạn có thể xử lý nó), nhưng nếu nó tiếp tục xảy ra, nó có thể đáng để bạn chú ý.ERROR: Dùng log level này khi lỗi xảy ra. Lỗi là trạng thái ứng dụng không hợp lệ mà bạn phải giải quyết càng sớm càng tốt.
Bạn có thể thay đổi loại thông điệp log ứng dụng ghi bằng cách sửa file môi trường tương ứng. Thông thường, Rails sẽ loại bỏ thông điệp DEBUG trong production, nhưng bạn có thể thay đổi điều đó.
Hãy áp dụng các gợi ý log level trên vào mẫu mã của chúng ta.
Khi debugging, chúng ta hiện có thể xác định nguyên nhân gốc rễ cho các sự cố bằng cách nhìn vào thông điệp WARN và ERROR. Thật tiếc, thông điệp log của chúng ta chưa trở nên mô tả hơn.
Thông Điệp Log Mô Tả
Thông điệp log mô tả không để chỗ cho sự diễn giải. Chúng cung cấp chi tiết cần thiết để đưa cho người đọc kiến thức tức thì về điều gì đã xảy ra.
Khi bạn đọc các thông điệp như 'Đã xảy ra lỗi', bạn thắc mắc lỗi đó là gì. Bạn muốn tránh sự nhầm lẫn này khi viết thông điệp log. Điều quan trọng nhất khi viết thông điệp log mô tả là đặt mình vào vị trí người đọc log. Họ có nhận được tất cả thông tin cần thiết khi đọc log của bạn không?
Hãy thay đổi thông điệp 'Đã xảy ra lỗi' thành chính lỗi đó, bao gồm thông điệp của nó.
Đó là một sự cải thiện. Hãy kiểm tra các thông điệp log khác trong ví dụ. 'Phương thức được gọi' không cho biết phương thức nào được gọi, 'Phản hồi thành công' bỏ qua phản hồi thực tế, và 'Phản hồi thất bại' không cung cấp thông tin về bản chất của sự thất bại. Hãy thay đổi điều đó.
Lưu ý: Bạn có thể đã nhận ra chúng ta sử dụng cú pháp block khi thực hiện nội suy chuỗi (string interpolation) với log. Việc dùng nó tránh tính toán không cần thiết khi log level của ứng dụng cao hơn level của thông điệp log. Ví dụ, log.debug("Some #{concatenation}") sẽ luôn thực hiện nối chuỗi, nhưng log.debug { "Some #{concatenation}" } chỉ làm vậy khi log level được đặt là debug.
Log của chúng ta đọc tốt hơn nhiều bây giờ. Ít nghi ngờ về ý nghĩa của từng thông điệp log.
Ngữ Cảnh Thêm Cho Thông Điệp Log
Các thông điệp log mới cung cấp bức tranh rõ ràng về điều gì đã xảy ra. Vì đây là ví dụ đơn giản, chúng ta cũng có hiểu biết tốt về tại sao điều gì xảy ra. Trong thực tế, thường không dễ dàng như vậy.
Việc cung cấp thông tin thêm về ngữ cảnh mà hệ thống ghi mỗi thông điệp có thể giúp đáng kể với debugging.
Ví dụ, khi ghi log yêu cầu hoặc phản hồi, có thể hữu ích để biết ai đã thực hiện yêu cầu. Đính kèm stack trace cho lỗi có thể hữu ích để thu thập thông tin thêm về tại sao lỗi xảy ra.
Lưu ý: Bạn có thể đã nhận ra việc tạo thông điệp log với thông tin ngữ cảnh có thể rườm rà khi bạn dùng default logger của Rails. May mắn thay, custom logger như Ougai hoặc MrLogaLoga làm cho việc này dễ dàng hơn nhiều.
Structured Logging (Logging Có Cấu Trúc)
Khi bạn đã làm cho log dễ đọc cho con người, bạn đã sẵn sàng đưa mọi thứ lên cấp độ tiếp theo. Bây giờ bạn cần làm cho log dễ đọc cho máy tính để có thể dùng chúng cho giám sát và phân tích dữ liệu.
Định dạng tôi thường dùng là JSON, nhưng tùy thuộc vào công cụ bạn dùng, bạn có thể thích các định dạng log khác như Logstash. Bạn có thể thay đổi định dạng thông điệp log bằng cách tạo custom log formatter.
Thay vì tự viết custom formatter, bạn có thể dùng một trong nhiều gem cung cấp custom log formatter. Tôi khuyến khích Lograge, nó không chỉ cung cấp định dạng sẵn có mà còn dọn dẹp định dạng request hơi fl của Rails để dễ đọc hơn nhiều.
Rails Logging Với AppSignal
Bây giờ log của bạn đẹp và dễ đọc, sẽ tốt nếu làm cho chúng dễ truy cập hơn.畢竟, bạn không muốn SSH vào máy nào đó và tail hoặc grep log ở đó, phải không?
May mắn thay, AppSignal vừa ra mắt tính năng logging ở bản beta! Điều này cho phép bạn kiểm tra và phân tích log Rails trực tiếp trong giao diện web AppSignal.
Bạn có thể truy cập logging beta qua tab 'Logging' ở menu bên trái:

Nếu bạn làm theo các bước trong tài liệu Ruby logging của chúng tôi, bạn có thể cấu hình Rails Logger để dùng lớp AppSignal::Logger bằng cách đặt mã dưới đây vào file config/environment.rb trước initialization:
Bạn cũng có thể ingest (nạp) log có cấu trúc ở định dạng JSON hoặc với Lograge.
Khi bạn đã thiết lập xong, bạn sẽ thấy log Rails của bạn xuất hiện trên AppSignal!

Logging & Báo Cáo Lỗi
Bạn đang đọc đây trên blog AppSignal, nên bạn có thể thắc mắc: tại sao tôi phải quan tâm logging nếu đã dùng một nền tảng báo cáo lỗi đẹp?
Đó là câu hỏi tốt. Công cụ theo dõi lỗi cung cấp thông tin chi tiết về lỗi ứng dụng. Chúng bắt full stack trace của bất kỳ lỗi ứng dụng nào và cung cấp nhiều thông tin ngữ cảnh ngay lập tức.
Tuy nhiên, dù hầu hết công cụ cho phép bạn bắt sự kiện khác ngoài lỗi, gửi cho các công cụ này một lượng tùy ý thông điệp thường không khả thi. Bạn sẽ không thể thay thế thông tin lịch sử chi tiết mà log viết tốt cung cấp.
Trong thực tế, log viết tốt bổ sung và hỗ trợ công cụ theo dõi lỗi. Bạn nên dùng cả hai.
Kết Luận
Trong bài viết này, chúng ta đã xem cách bạn có thể tận dụng tối đa log. Chúng ta thấy việc bắt đầu logging trong Rails dễ dàng, nhưng viết log hữu ích có thể thách thức.
Log thiếu tính mô tả hoặc ngữ cảnh sẽ chỉ lấp đầy ổ cứng mà cung cấp giá trị nhỏ. Tuy nhiên, log sử dụng đúng log level và cung cấp cho người đọc thông tin họ cần là tài sản lớn.
Khi bạn đã thành thạo viết thông điệp log tuyệt vời, bạn có thể đưa mọi thứ xa hơn và định dạng chúng theo cách cho phép phân tích log và lọc dễ dàng.
Chúng ta cũng khám phá cách dùng tính năng logging mới của AppSignal để truy cập log dễ dàng. Cuối cùng, chúng ta chạm đến việc log nên bổ sung cho công cụ theo dõi lỗi thay vì thay thế chúng.
Chúc bạn logging vui vẻ!
P.S. Nếu bạn muốn đọc các bài Ruby Magic ngay khi chúng xuất bản, hãy đăng ký bản tin Ruby Magic của chúng tôi và không bao giờ bỏ lỡ bất kỳ bài viết nào!
Hans-Jörg Schnedlitz
Tác giả khách Hans là kỹ sư Rails từ Vienna, Áo. Anh dành hầu hết thời gian coding hoặc đọc về coding, và đôi khi viết về nó trên blog cá nhân! Khi không ngồi trước màn hình, bạn có thể tìm thấy anh ngoài trời, leo núi.
Tất cả bài viết của Hans-Jörg Schnedlitz