Python Logging: Hướng dẫn chi tiết từ cơ bản đến nâng cao để gỡ lỗi và giám sát hiệu quả

1. Module logging của Python là gì?

Module logging của Python là một công cụ tiêu chuẩn để ghi lại trạng thái hoạt động và thông tin lỗi của chương trình, được sử dụng để gỡ lỗi (debug) và giám sát trong quá trình vận hành. Điểm khác biệt so với câu lệnh print là module logging có nhiều chức năng hơn, cho phép kiểm soát chi tiết mức độ log, đích xuất và định dạng. Điều này giúp nhà phát triển dễ dàng nắm bắt hiệu quả các bất thường và trạng thái của chương trình.

Các loại mức độ log và mục đích sử dụng

     

  • DEBUG: Thông tin gỡ lỗi chi tiết. Chủ yếu được sử dụng trong giai đoạn phát triển.
  •  

  • INFO: Thông tin hoạt động chung. Được sử dụng để xác nhận hoạt động bình thường.
  •  

  • WARNING: Các vấn đề nhỏ hoặc lưu ý. Không ảnh hưởng đến hoạt động của chương trình nhưng chỉ ra các vấn đề tiềm ẩn.
  •  

  • ERROR: Thông báo lỗi khi một phần chức năng không hoạt động bình thường. Chỉ ra tình huống gây cản trở việc thực thi chương trình.
  •  

  • CRITICAL: Lỗi nghiêm trọng. Chỉ ra vấn đề chết người khiến toàn bộ chương trình không thể tiếp tục thực thi.

Bằng cách sử dụng phù hợp từng mức độ log, bạn có thể cải thiện chất lượng thông tin nhận được từ log và thực hiện gỡ lỗi và giám sát hiệu quả.

2. Cách sử dụng logging cơ bản

Chúng ta hãy xem cách cơ bản để xuất log bằng cách sử dụng module logging.

import logging

# Cấu hình mức độ log và định dạng
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')

# Xuất log ở từng mức độ
logging.debug('Thông tin debug: Thông tin chẩn đoán chi tiết')
logging.info('Thông báo thông tin: Xác nhận hoạt động bình thường')
logging.warning('Thông báo cảnh báo: Trạng thái cần chú ý')
logging.error('Thông báo lỗi: Đã xảy ra vấn đề')
logging.critical('Thông báo cực kỳ quan trọng: Hệ thống dừng hoạt động')

Với logging.basicConfig(), bạn cấu hình đích xuất log (mặc định là standard output), mức độ log và định dạng. Trong ví dụ trên, do đã cấu hình level=logging.DEBUG, tất cả các log ở mức DEBUG trở lên sẽ được xuất ra.

侍エンジニア塾

3. Tùy chỉnh đích xuất và định dạng log

Bạn cũng có thể thay đổi đích xuất mặc định hoặc tùy chỉnh định dạng log. Ví dụ, để xuất log ra file, bạn sử dụng FileHandler.

Xuất ra file và định dạng

import logging

# Cấu hình file handler
file_handler = logging.FileHandler('app.log')
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)

# Cấu hình logger
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
logger.addHandler(file_handler)

# Xuất log
logger.debug('Thông tin debug ra file')
logger.info('Thông báo thông tin ra file')

Trong đoạn code trên, log được xuất ra file app.log bằng cách sử dụng FileHandler. Các thông báo log sẽ được ghi vào file dựa trên định dạng được chỉ định bởi Formatter.

4. Xoay vòng file log (Log file rotation)

Trong quá trình vận hành lâu dài, việc xoay vòng file log là quan trọng để đảm bảo file log không trở nên quá lớn. Bằng cách sử dụng RotatingFileHandler, bạn có thể kiểm soát kích thước và số lượng file log.

Ví dụ sử dụng RotatingFileHandler

import logging
from logging.handlers import RotatingFileHandler

# Cấu hình rotation handler
handler = RotatingFileHandler('app.log', maxBytes=5000, backupCount=3)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)

# Cấu hình logger
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)

# Xuất log
for i in range(100):
    logger.debug(f'Kiểm tra xoay vòng {i}')

Trong đoạn code này, maxBytes được đặt thành 5000 byte cho kích thước tối đa của file log và backupCount được đặt thành 3 cho số lượng file sao lưu. Khi file log vượt quá kích thước đã chỉ định, log sẽ được ghi vào một file mới và file cũ sẽ được sao lưu.

侍エンジニア塾

5. Xuất log theo mức độ ra từng file riêng

Bằng cách xuất log của từng mức độ ra các file khác nhau, bạn có thể cải thiện khả năng đọc và hiệu quả phân tích log. Điều này được thực hiện bằng cách sử dụng custom filter và nhiều FileHandler.

Ví dụ xuất log theo mức độ ra file riêng

import logging

class ErrorFilter(logging.Filter):
    def filter(self, record):
        return record.levelno == logging.ERROR

# Xuất log mức ERROR ra file riêng
error_handler = logging.FileHandler('error.log')
error_handler.setLevel(logging.ERROR)
error_handler.addFilter(ErrorFilter())
error_handler.setFormatter(formatter)

# Cấu hình logger
logger.addHandler(error_handler)

# Xuất log
logger.error('Log mức ERROR sẽ được xuất ra file')

Trong ví dụ này, chúng ta tạo lớp ErrorFilter để lọc chỉ các log ở mức ERROR và xuất chúng ra file error.log. Bằng cách này, bạn có thể tách riêng và ghi lại chỉ các log lỗi vào một file riêng.

6. Thực hành tốt nhất và lưu ý

Để sử dụng log một cách hiệu quả, cần xem xét các thực hành tốt nhất và lưu ý sau đây.

Sử dụng mức độ log phù hợp

     

  • Trong quá trình phát triển, sử dụng mức DEBUG để ghi lại thông tin chi tiết, và trong quá trình vận hành, chuyển sang mức INFO hoặc WARNING để chỉ ghi lại thông tin quan trọng.
  •  

  • Việc xuất log quá nhiều có thể gây suy giảm hiệu suất, vì vậy chỉ ghi lại thông tin cần thiết.

Bảo mật và quyền riêng tư của log

     

  • Cẩn thận không ghi lại thông tin cá nhân hoặc thông tin nhạy cảm vào log. Cần có biện pháp như che giấu dữ liệu khi cần thiết.
  •  

  • Thiết lập quyền phù hợp cho file log để ngăn chặn truy cập trái phép.

7. Tóm tắt

Module logging là công cụ rất hữu ích để ghi lại trạng thái hoạt động của chương trình một cách hiệu quả, giúp ích rất nhiều trong việc gỡ lỗi và vận hành. Bằng cách cấu hình phù hợp mức độ log, đích xuất, định dạng, xoay vòng file, v.v., và nắm bắt chi tiết tình hình vận hành chương trình, bạn có thể phát hiện và giải quyết vấn đề sớm. Hãy áp dụng các thực hành tốt nhất và thực hiện quản lý log phù hợp.

RUNTEQ(ランテック)|超実戦型エンジニア育成スクール