Jak logujesz błędy serwera w witrynach django

175

Tak więc, kiedy gra z rozwojem mogę po prostu ustawić settings.DEBUGsię Truei jeśli occures błędach widzę to ładnie sformatowany, z dobrym śladu stosu i informacji żądania.

Ale na czymś w rodzaju strony produkcyjnej wolałbym raczej użyć DEBUG=Falsei pokazać odwiedzającym jakąś standardową stronę błędu 500 z informacją, że pracuję nad naprawieniem tego błędu w tej chwili;)
Jednocześnie chciałbym mieć jakiś sposób na zalogowanie wszystkich te informacje (śledzenie stosu i informacje o żądaniach) do pliku na moim serwerze - więc mogę po prostu wyprowadzić je na moją konsolę i oglądać przewijanie błędów, e-mailem dziennik do mnie co godzinę lub coś w tym rodzaju.

Jakie rozwiązania do rejestrowania poleciłbyś dla witryny django, które spełniałyby te proste wymagania? Mam aplikację działającą jako fcgiserwer i używam serwera WWW Apache jako frontendu (chociaż myślę o przejściu na lighttpd).

kender
źródło
coś z pola bitwy: dlo.me/what-to-do-when-your-site-goes-viral
Cherian
2
Sentry, aby wyświetlić logi: readthedocs.org/docs/sentry/en/latest/index.html
Cherian
Link, który udostępnił Cherian, jest teraz martwy. Jeśli spróbujesz wyszukać Sentry, prawdopodobnie znajdziesz materiały dotyczące ich płatnej, oficjalnej instancji, ale tutaj jest link do skonfigurowania instancji hostowanej na własnym serwerze: docs.sentry.io/server Ponadto, oto obecnie utrzymywane repozytorium: github .com / getsentry / sentry
lehiester

Odpowiedzi:

103

Cóż, kiedy DEBUG = FalseDjango automatycznie wyśle ​​pełne śledzenie każdego błędu do każdej osoby wymienionej w ADMINSustawieniu, co dostaniesz powiadomienia prawie za darmo. Jeśli chcesz bardziej precyzyjnej kontroli, możesz napisać i dodać do swoich ustawień klasę oprogramowania pośredniego, która definiuje nazwaną metodę process_exception(), która będzie miała dostęp do zgłoszonego wyjątku:

http://docs.djangoproject.com/en/dev/topics/http/middleware/#process-exception

Twoja process_exception()metoda może następnie wykonać dowolny typ logowania: zapis do konsoli, zapis do pliku itp., Itd.

Edycja: chociaż jest to trochę mniej przydatne, możesz również nasłuchiwać got_request_exceptionsygnału, który zostanie wysłany, gdy wystąpi wyjątek podczas przetwarzania żądania:

http://docs.djangoproject.com/en/dev/ref/signals/#got-request-exception

Ten sposób nie daje dostęp do obiektu wyjątku, jednak, więc metoda middleware jest znacznie łatwiej pracować.

James Bennett
źródło
7
Zauważ, że używanie logging.exception('Some message')ze standardowym modułem rejestrowania w Pythonie działa dobrze w programie obsługi sginal got_request_exception, jeśli wszystko, co chcesz zrobić, to wylogować ślady stosu. Innymi słowy, śledzenie jest nadal dostępne w got_request_exception.
TM.
wyjątek przekazany do wyjątku_procesu nie wydaje się mieć śladu stosu, czy istnieje sposób, aby to uzyskać?
Nick BL
79

Django Sentry to dobry sposób, jak już wspomniano, ale wymaga trochę pracy, aby go poprawnie skonfigurować (jako oddzielną stronę internetową). Jeśli chcesz tylko rejestrować wszystko w prostym pliku tekstowym, oto konfiguracja logowania, którą należy umieścić w plikusettings.py

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        # Include the default Django email handler for errors
        # This is what you'd get without configuring logging at all.
        'mail_admins': {
            'class': 'django.utils.log.AdminEmailHandler',
            'level': 'ERROR',
             # But the emails are plain text by default - HTML is nicer
            'include_html': True,
        },
        # Log to a text file that can be rotated by logrotate
        'logfile': {
            'class': 'logging.handlers.WatchedFileHandler',
            'filename': '/var/log/django/myapp.log'
        },
    },
    'loggers': {
        # Again, default Django configuration to email unhandled exceptions
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
        # Might as well log any errors anywhere else in Django
        'django': {
            'handlers': ['logfile'],
            'level': 'ERROR',
            'propagate': False,
        },
        # Your own app - this assumes all your logger names start with "myapp."
        'myapp': {
            'handlers': ['logfile'],
            'level': 'WARNING', # Or maybe INFO or DEBUG
            'propagate': False
        },
    },
}
EMP
źródło
Zgadzam się, kocham Sentry! Chcę mieć port .Net (ostatnio pracowałem nad projektami .Net).
Gromer
1
Mała literówka na wypadek, gdyby ktoś wycinał i wklejał: na końcu „propaguj” zamiast „propaguj”.
user1228295
3
'include_html': TrueNIE sprawia, że ​​e-maile są po prostu „milsze”! Zawiera pełne śledzenie, w tym wartości ustawień i zmiennych lokalnych. Zgodnie z dokumentacją jest to kwestia
Thomas
1
Jestem ciekawy, czy program obsługi mail_admins (i rejestrator django.request) jest potrzebny, ponieważ masz opcję „disable_existing_loggers”: Fałsz i po prostu replikujesz domyślne logowanie django za pomocą tego modułu obsługi (i rejestratora). Zaktualizuję, kiedy przetestuję.
DylanYoung
Zaktualizuj tę odpowiedź. Z django1.9 change-log: Domyślna konfiguracja logowania w Django nie definiuje już rejestratorów „django.request” i „django.security”.
narendra-choudhary
30

Oczywiście James ma rację, ale jeśli chcesz rejestrować wyjątki w magazynie danych, jest już dostępnych kilka rozwiązań typu open source:

1) CrashLog to dobry wybór: http://code.google.com/p/django-crashlog/

2) Db-Log to również dobry wybór: http://code.google.com/p/django-db-log/

Jaka jest różnica między nimi? Prawie nic, co widzę, więc wystarczy jeden.

Użyłem obu i działają dobrze.

montylounge
źródło
15

Minęło trochę czasu od przesłania najbardziej pomocnego kodu przez EMP. Właśnie go zaimplementowałem i podczas miotania się z jakąś opcją manage.py, aby spróbować ścigać błąd, otrzymałem ostrzeżenie o wycofaniu, że w mojej obecnej wersji Django (1.5.?) Filtr require_debug_false jest teraz potrzebne dla programu obsługi mail_admins.

Oto poprawiony kod:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
         'require_debug_false': {
             '()': 'django.utils.log.RequireDebugFalse'
         }
     },
    'handlers': {
        # Include the default Django email handler for errors
        # This is what you'd get without configuring logging at all.
        'mail_admins': {
            'class': 'django.utils.log.AdminEmailHandler',
            'level': 'ERROR',
            'filters': ['require_debug_false'],
             # But the emails are plain text by default - HTML is nicer
            'include_html': True,
        },
        # Log to a text file that can be rotated by logrotate
        'logfile': {
            'class': 'logging.handlers.WatchedFileHandler',
            'filename': '/home/username/public_html/djangoprojectname/logfilename.log'
        },
    },
    'loggers': {
        # Again, default Django configuration to email unhandled exceptions
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
        # Might as well log any errors anywhere else in Django
        'django': {
            'handlers': ['logfile'],
            'level': 'ERROR',
            'propagate': False,
        },
        # Your own app - this assumes all your logger names start with "myapp."
        'myapp': {
            'handlers': ['logfile'],
            'level': 'DEBUG', # Or maybe INFO or WARNING
            'propagate': False
        },
    },
}
Mike O'Connor
źródło
Jestem ciekawy, czy program obsługi mail_admins (i rejestrator django.request) jest potrzebny, ponieważ masz opcję „disable_existing_loggers”: Fałsz i po prostu replikujesz domyślne logowanie django za pomocą tego modułu obsługi (i rejestratora). Zaktualizuję, kiedy przetestuję.
DylanYoung
1

Właśnie miałem irytujący problem z moim fcgiskryptem. Zdarzyło się to jeszcze zanim django się zaczęło. Brak logowania jest bardzo bolesny. W każdym razie, przekierowanie stderr do pliku jako pierwsza bardzo pomogło:

#!/home/user/env/bin/python
sys.stderr = open('/home/user/fcgi_errors', 'a')
jozxyqk
źródło