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. Hướng dẫn này trình bày logging trong Python với module logging chuẩn, 5 mức log của Python, cách xử lý lỗi trong Python và các loại lỗi Python thường gặp. Các phần cuối gửi chính các log và crash đó đến LogBrew bằng logbrew-sdk 0.1.29. Mọi ví dụ đều đã chạy trên Python 3.13, và mỗi khối kết quả là kết quả thật. Với ứng dụng Flask, dùng logging cho Flask thay cho trang này. Cách đó thêm trace của yêu cầu vào cùng cấu hình logging.

Ghi log Python đầu tiên

Lưu tệp này thành app.py. Gọi logging.basicConfig() một lần, tại điểm vào của chương trình. Trong mỗi module, lấy một logger có tên.
Chạy python3 app.py. Kết quả được ghi ra standard error.
Bản ghi debug không xuất hiện vì mức log là INFO. logger.exception() ghi log ở mức ERROR và thêm traceback. Chỉ gọi hàm này trong khối except. Truyền giá trị dưới dạng đối số, như trong "payment retry %d of %d", 2, 3. Python chỉ tạo thông điệp khi một handler chấp nhận bản ghi. Mẫu thông điệp giữ nguyên cho mọi lần thử lại, nên bạn có thể tìm kiếm theo mẫu đó.

Các mức log trong Python

Logger chỉ gửi bản ghi khi mức của bản ghi bằng hoặc cao hơn mức của logger. Handler có thể đặt thêm một mức thứ hai, cao hơn. Logger gốc bắt đầu ở mức WARNING. Logger mới có mức NOTSET (0) và dùng mức của logger cha. Đặt INFO trong production. Chỉ dùng DEBUG khi phát triển hoặc khi chẩn đoán trong thời gian ngắn.
Dòng đầu tiên hiện các bản ghi debug của một module. Dòng thứ hai bớt log nhiễu từ một thư viện.

Logger, handler và formatter

  • Logger nhận lời gọi. Dùng logging.getLogger(__name__) để tên logger đi theo đường dẫn module.
  • Handler gửi bản ghi đến một đích, ví dụ console, tệp hoặc LogBrew.
  • Formatter chuyển bản ghi thành văn bản.
Thư viện không được cấu hình logging. Thư viện chỉ thêm logging.NullHandler() vào logger của chính nó. Ứng dụng cấu hình handler và mức log một lần. Với cấu hình lớn, dùng logging.config.dictConfig().

Xử lý lỗi trong Python

Bắt ngoại lệ cụ thể nhất mà bạn xử lý được. Dùng else cho code chỉ chạy khi thành công và finally cho code luôn chạy. Dùng raise ... from error để giữ nguyên nhân gốc. Lưu tệp này thành orders.py.
Kết quả hiện cả hai ngoại lệ trong chuỗi ngoại lệ.
Áp dụng các quy tắc sau cho từng ngoại lệ.
  • Ghi log một ngoại lệ một lần, tại nơi bạn xử lý nó. Đừng ghi log rồi ném lại ở mỗi tầng, vì mỗi tầng sẽ thêm một bản ghi trùng lặp.
  • Đừng viết except Exception: pass. Nếu bỏ qua một lỗi, ghi log lỗi đó ở mức WARNING trở lên kèm lý do.
  • Bắt Exception, không bắt BaseException. BaseException còn bắt cả KeyboardInterrupt và SystemExit, vốn được dùng để chủ động dừng chương trình.
  • Định nghĩa lớp ngoại lệ riêng cho các lỗi mà bên gọi phải xử lý, như OrderError.

Báo nhiều lỗi cùng lúc

Python 3.11 trở lên có thể ném ExceptionGroup. Dùng nó khi một lần kiểm tra phát hiện nhiều lỗi. Xử lý từng loại bằng except*.

Các loại lỗi Python thường gặp

Mọi lỗi dựng sẵn mà chương trình xử lý được đều kế thừa từ Exception. Bảng này liệt kê các lỗi Python hay gặp nhất và điều cần kiểm tra đầu tiên cho mỗi lỗi. KeyboardInterrupt và SystemExit kế thừa từ BaseException, không phải Exception. Đây không phải lỗi trong code của bạn.

Gửi log Python đến LogBrew

LogBrewLoggingHandler là một logging handler chuẩn. Handler này gửi mỗi bản ghi mà nó chấp nhận đến LogBrew. Handler của console vẫn giữ nguyên.
1

Tạo khóa dự án

Đăng nhập bằng CLI. Tạo một dự án và lưu khóa gửi dữ liệu của dự án vào một tệp mà chỉ chủ sở hữu đọc được.
CLI không in khóa ra. Trong production, dùng trình quản lý secret của nền tảng bạn dùng.
2

Cài đặt SDK

Kích hoạt môi trường ảo của ứng dụng. Sau đó cài gói. Gói này cần Python 3.10 trở lên.
3

Đặt khóa và danh tính triển khai

Client thêm dịch vụ, môi trường và bản phát hành vào mỗi sự kiện.
4

Thêm handler

Lưu tệp này thành worker.py. Gọi logging.basicConfig() trước khi tạo client. Client thêm một handler vào logger gốc, và basicConfig() không làm gì khi logger gốc đã có handler.
HttpTransport() gửi sự kiện ở chế độ nền, 1 giây sau sự kiện đầu tiên hoặc khi đủ 50 sự kiện. client.shutdown() gửi các sự kiện còn lại và đóng client.
5

Chạy chương trình

Kết quả trên console không đổi. LogBrew nhận 1 sự kiện log cho mỗi bản ghi. Đây là sự kiện đầu tiên, đã bỏ phần ngữ cảnh runtime dùng chung.
Các giá trị nguyên thủy trong extra={...} trở thành metadata. Sự kiện thứ hai có exceptionName là KeyError và exceptionMessage là 'seats'. Để gửi toàn bộ nội dung traceback, tạo handler với include_exception_text=True.
6

Đọc lại log

Kết quả đọc khớp cho thấy LogBrew đã lưu log. Để đọc từ CI hoặc agent lập trình, dùng khóa đọc dữ liệu của dự án. Xem Kiểm tra thiết lập.

Chọn bản ghi gửi đến LogBrew

Đặt mức riêng cho handler để gửi ít bản ghi hơn. Console vẫn nhận các bản ghi từ INFO trở lên.
Mức log Python được chuyển thành mức log LogBrew. Tên và số của mức gốc vẫn nằm trong metadata.

Báo crash Python thành vấn đề

install_process_error_capture(client) báo các ngoại lệ chưa được bắt trong script, worker, code khởi động và thread. Mỗi crash trở thành 1 vấn đề, gồm loại ngoại lệ, thông điệp, các khung ngăn xếp (stack frame) và các nguyên nhân trong chuỗi ngoại lệ. Python vẫn in traceback và thoát như trước. Lưu tệp này thành startup.py rồi chạy.
LogBrew nhận một vấn đề có tiêu đề FileNotFoundError, mức critical và cơ chế python.excepthook. Các khung ngăn xếp của vấn đề chứa tên tệp, dòng và hàm, nhưng không chứa đường dẫn đầy đủ. Crash trong một thread có mức error. Trước khi Python thoát, SDK chờ tối đa 2 giây để gửi xong.
Vấn đề có chứa thông điệp của ngoại lệ. Đừng đưa thông tin xác thực hoặc dữ liệu cá nhân vào thông điệp ngoại lệ hay thông điệp log. Xem Che dữ liệu log.

Khắc phục sự cố

Với ứng dụng web, xem logging cho Flask. Để chọn định dạng log, xem Structured logging. Với các runtime khác, xem Tích hợp SDK.