2013-04-25 13 views
19

Powiedzmy chcę zalogować się ten ciąg znaków formatowania:rejestracja danych django kontekst globalnie na żądanie?

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

można to zrobić za pomocą tego rodzaju polecenia rejestrowania:

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

Spowoduje to dodanie aktualnego identyfikatora do rejestrowania komunikatów dla aktualne żądanie.

Ale dodatkowy dyktant musi zostać dodany do każdego połączenia rejestracyjnego.

Czy istnieje dobry sposób dodania tego kontekstu do wspólnej funkcji w django (np. Oprogramowanie pośrednie lub funkcja indeksu widoku), aby ustawić dodatkowy słownik z identyfikatorem użytkownika, a wszystkie dalsze połączenia rejestrowania w bieżącym Żądaj również zalogowania bieżącego użytkownika.

+1

Dlaczego odpowiedź 'mawimawi' jest nie do zaakceptowania? Czy to z powodu użycia wątku lokalnego, czy też czegoś innego? –

+0

Vinay Sajip, niektóre punkty rep umrą w spokoju. Tak to działa tutaj na stackoverflow. – mawimawi

+0

@VinaySajip, tak, próbując uniknąć użycia wątku lokalnego i dodatkowego oprogramowania pośredniego. Jeśli jest jakiś sposób, rozszerzając klasę rejestrowania, byłoby świetnie. – DhruvPathak

Odpowiedz

8

Istnieje oprogramowanie pośrednie ThreadLocal pod numerem https://github.com/jedie/django-tools/blob/master/django_tools/middlewares/ThreadLocal.py, które pomaga rozwiązać problem polegający na udostępnianiu bieżącego żądania wszędzie.

Więc co trzeba zrobić, to dodać middleware z ustawieniami MIDDLEWARE_CLASSES i utworzyć funkcję gdzieś tak:

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

Oto możliwe podejście bez mieszkańców nici lub pośredniej: W views.py, powiedzmy, mają odwzorowanie DICT wątków żądań i blokadę do serialise dostęp do niego:

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

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

utworzyć następujący filtr i przywiązują do ładowarki, które wymagają wyjścia żądanie konkretnych informacji:

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 

Następnie, jako pierwszego sprawozdania z każdego widoku, ustaw wniosek na mapie:

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

Z tej konfiguracji, należy dowiedzieć się, że wyjście dziennika zawiera stosowny wniosek konkretnych informacji.

1

Myślę, że szukasz custom log formatter. W połączeniu z odpowiedzią mawimawiego zawierającą informacje o wątku globalnym, metoda formatu może automatycznie pobierać informacje i dodawać je do każdej zalogowanej wiadomości.

Jest kilka rzeczy do przemyślenia: Po pierwsze, zmienne wątkowe mogą być niebezpieczne i, co gorsza, informacje o wycieku, jeśli wdrożysz w sposób, który używa wątku. Po drugie, musisz zachować ostrożność podczas pisania swojego formatera, na wypadek gdyby został wywołany w kontekście, który nie zawiera informacji o wątku.

Powiązane problemy