2017-06-07 25 views
16

W jaki sposób Django może logować się przy użyciu niestandardowych atrybutów w formatyzatorze? Myślę na przykład o zalogowaniu zalogowanej nazwy użytkownika.Rejestrowanie niestandardowych atrybutów Django w formatorze

W skrypcie settings.py, zmienna jest zdefiniowana REJESTRACJI:

LOGGING = { 
    'version': 1, 
    'disable_existing_loggers': False, 
    'filters': { 
     'require_debug_false': { 
      '()': 'django.utils.log.RequireDebugFalse' 
     }, 
    }, 
    'formatters' : { 
     'info_format' : { 
      'format' : '%(asctime)s %(levelname)s - %(message)s', 
     }, 
    } 
} 

Chciałbym użyć formatu, coś jak:

'format' : '%(asctime).19s %(levelname)s - %(username)s: %(message)s' 

Jeżeli nazwa użytkownika będzie aktualnie zalogowanego użytkownika. Możliwe, że mogą tu zostać dodane inne zmienne sesji.

Rozwiązaniem jest tu użyć parametru extra na temat metod rejestratora, który odbiera słownika za pomocą klawiszy jak struny chcę użyć na ciąg formatu:

logger.info(message, extra={'username' : request.user.username}) 

Innym (brzydki) obejście gdyby tworzyły należy zbudować atrybut wiadomości, aby uwzględnić rzeczy, które nie są częścią domyślnych atrybutów, które mają formaty logowania.

message = request.user.username + " - " + message 
logger.info(message) 

Ale czy istnieje sposób na ustawienie ciągu formatu z określonymi atrybutami i sprawienie, aby Django automatycznie przekazywał je do interfejsu API rejestrowania? Jeśli na przykład% (nazwa użytkownika), request.user.username, z innych być może ...

+1

Proszę podać kod tego, co zostało zrobione. –

+1

@JohnPeters there you go! –

Odpowiedz

10

Możesz użyć filtra, aby dodać swój atrybut niestandardowy. Na przykład:

def add_my_custom_attribute(record): 
    record.myAttribute = 'myValue' 
    record.username = record.request.user.username 
    return True 

LOGGING = { 
    'version': 1, 
    'disable_existing_loggers': False, 
    'filters': { 
     ... 
     'add_my_custom_attribute': { 
      '()': 'django.utils.log.CallbackFilter', 
      'callback': add_my_custom_attribute, 
     } 
    }, 
    'handlers': { 
     ... 
     'django.server': { 
      'level': 'INFO', 
      'class': 'logging.StreamHandler', 
      'filters': ['add_my_custom_attribute'], 
      'formatter': 'django.server', 
     },    
    }, 
    ... 
} 

przez zainstalowanie filtra, można przetwarzać każdy rekord dziennika i zdecydować, czy powinien on być przekazywany z rejestratorem do obsługi.

Filtr otrzymuje rekord protokołu, który zawiera wszystkie szczegóły dziennika (tj. Czas, ważność, żądanie, kod statusu).

Atrybuty rekordu są używane przez formatter w celu sformatowania go w komunikat tekstowy. Jeśli dodasz do tego rekordu niestandardowe atrybuty, będą one również dostępne dla formatera.

+0

Czy mógłbyś wyjaśnić, w jaki sposób mogę użyć określonego niestandardowego atrybutu dodawanego przez filtr do łańcucha formatowania rejestrowania? –

+1

opracowano na temat filtrów. – napuzba

+1

Jedną z rzeczy, na które należy zwrócić uwagę, jest to, że logowanie może się również zdarzyć w miejscach, w których nie ma "żądania" (generycznego kodu Pythona lub "Models.py" na przykład). Tak więc wersja produkcyjna będzie prawdopodobnie wymagać nieco więcej kodu dla solidności. (Na przykład, wszystko jest w porządku, oczywiście! Nauczyłem się czegoś z tego, a ja spojrzę na filtry nieco więcej!) –

3

Słowo kluczowe extra nie jest rozwiązaniem tymczasowym. Jest to najbardziej wymowny sposób pisania niestandardowych formaterów, o ile nie pisze się w całości razem z custom logging.

format: '%(asctime).19s %(levelname)s - %(username)s: %(message)s' 
logging.basicConfig(format=format) 
logger.info(message, extra={'username' : request.user.username}) 

Niektóre notatki z dokumentacji (**kwars for Django logger):

Klucze w słowniku przeszedł w extra nie powinny kolidować z kluczy wykorzystywanych przez system rejestrowania.

Jeśli brakuje ciągów oczekiwanych przez formatter, wiadomość nie zostanie zarejestrowana.

Ta funkcja jest przeznaczona do użytku w szczególnych okolicznościach, ale nie zawsze.

+1

Używanie 'extra' działa, ale robi się nudne, jeśli chcesz/chcesz dodać go cały czas. Pierwotne pytanie dotyczy standardowego sposobu określania go tylko w jednym miejscu (a konkretnie w konfiguracji rejestrowania). –

1

podam jedną z wielu możliwych kompletnych odpowiedzi na to pytanie:

Jak Django korzystania rejestrowanie się zalogować przy użyciu niestandardowych atrybutów w formater? Myślę na przykład o zalogowaniu zalogowanej nazwy użytkownika.

Inne odpowiedzi dotyczyły sposobu dodania dodatkowych informacji kontekstowych za pomocą narzędzi do logowania Pythona. Sposób korzystania z filtrów, aby dołączyć dodatkowe informacje do rekordu dziennika jest idealna, a najlepiej opisane w docs:

https://docs.python.org/3/howto/logging-cookbook.html#using-filters-to-impart-contextual-information

To jeszcze nie mówi nam jak dostać się użytkownikowi od żądanie w uniwersalny sposób. Poniższy biblioteka robi to:

https://github.com/ninemoreminutes/django-crum

Zatem połączyć dwa, a będziesz mieć pełną odpowiedź na pytanie, które zostało zadane.

import logging 
from crum import get_current_user 

class ContextFilter(logging.Filter): 
    """ 
    This is a filter injects the Django user 
    """ 

    def filter(self, record): 

     record.user = get_current_user() 
     return True 

if __name__ == '__main__': 
    logging.basicConfig(level=logging.DEBUG, 
         format='User: %(user)-8s %(message)s') 
    a1 = logging.getLogger('a.b.c') 

    f = ContextFilter() 
    a1.addFilter(f) 
    a1.debug('A debug message') 

To musi się zdarzyć w ramach cyklu żądanie-odpowiedź Django z poprawnie zainstalowaną biblioteką CRUM.