2013-04-25 35 views
19

phép nói rằng tôi muốn đăng nhập như chuỗi định dạng này:django logging đặt bối cảnh trên toàn cầu theo yêu cầu?

%(levelname)s %(asctime)s %(module)s %(funcName)s %(message)s %(user_id) 

Nó có thể được thực hiện bằng loại lệnh đăng nhập:

logging.error('Error fetching information', extra = { 'user_id': 22 })

này sẽ thêm userid hiện tại để đăng tin nhắn cho yêu cầu hiện tại.

Nhưng thêm dict cần phải được thêm vào mỗi cuộc gọi đăng nhập.

Có cách nào tốt để thêm ngữ cảnh này vào một chức năng chung trong django (ví dụ phần mềm trung gian hoặc chức năng chỉ mục của chế độ xem), để từ điển bổ sung có id người dùng được đặt và tất cả các cuộc gọi đăng nhập khác trong hiện tại yêu cầu cũng đăng nhập người dùng hiện tại.

+1

Tại sao câu trả lời của 'mawimawi' không được chấp nhận? Có phải vì sử dụng thread-local hay cái gì khác? –

+0

Vinay Sajip, một số điểm đại diện sẽ chết một mình. Đó là cách nó hoạt động ở đây trên stackoverflow. – mawimawi

+0

@VinaySajip, vâng, cố gắng tránh việc sử dụng luồng địa phương và phần mềm trung gian bổ sung. Nếu có một cách có thể bằng cách mở rộng lớp khai thác gỗ, điều đó sẽ rất tuyệt. – DhruvPathak

Trả lời

8

Có một phần mềm trung gian ThreadLocal trên https://github.com/jedie/django-tools/blob/master/django_tools/middlewares/ThreadLocal.py giúp bạn giải quyết vấn đề trong việc đưa ra yêu cầu hiện tại ở mọi nơi.

Vì vậy, những gì bạn cần làm là thêm các trung gian để thiết lập MIDDLEWARE_CLASSES của bạn, và tạo một hàm ở đâu đó như thế này:

from django_tools.middlewares import ThreadLocal 
def log_something(levelname, module, funcname, message): 
    user = ThreadLocal.get_current_user() 
    # do your logging here. "user" is the user object and the user id is in user.pk 
2

Dưới đây là một cách tiếp cận tốt mà không người dân địa phương chủ đề hoặc middleware: trong views.py của bạn, nói, có một đề lập bản đồ dict các yêu cầu, và một khóa để serialise truy cập vào nó:

from threading import RLock 
shared_data_lock = RLock() 
request_map = {} 

def set_request(request): 
    with shared_data_lock: 
     request_map[threading.current_thread()] = request 

Tạo bộ lọc sau và đính kèm với bộ xử lý mà cần phải ra thông tin theo yêu cầu cụ thể:

import logging 
class RequestFilter(logging.Filter): 
    def filter(self, record): 
     with shared_data_lock: 
      request = request_map.get(threading.current_thread()) 
     if request: 
      # Set data from the request into the record, e.g. 
      record.user_id = request.user.id 
     return True 

Sau đó, khi báo cáo kết quả đầu tiên của mỗi cái nhìn, thiết lập các yêu cầu trong bản đồ:

def my_view(request, ...): 
    set_request(request) 
    # do your other view stuff here 

Với thiết lập này, bạn sẽ thấy rằng dữ liệu ghi nhận của bạn có chứa các thông tin theo yêu cầu cụ thể có liên quan.

1

Tôi nghĩ bạn đang tìm kiếm custom log formatter. Kết hợp với câu trả lời của mawimawi để bao gồm thông tin chủ đề, phương pháp định dạng của bạn có thể tự động lấy thông tin và thêm nó vào mỗi thông điệp đã đăng nhập.

Có một vài điều cần suy nghĩ: Đầu tiên, các biến chủ đề có thể nguy hiểm và tệ hơn, thông tin bị rò rỉ, nếu bạn triển khai theo cách sử dụng một luồng. Thứ hai, bạn cần phải thận trọng cách bạn viết trình định dạng của bạn trong trường hợp nó được gọi trong ngữ cảnh không có thông tin chủ đề.

Các vấn đề liên quan