¿Cómo registra los errores del servidor en los sitios de Django?


175

Por lo tanto, cuando se juega con el desarrollo que sólo puede fijar settings.DEBUGa Truey si un error occures lo puedo ver con un formato agradable, con buena traza de pila y solicitar información.

Pero en el tipo de sitio de producción prefiero usar DEBUG=Falsey mostrar a los visitantes un error estándar de 500 páginas con información que estoy trabajando para solucionar este error en este momento;)
Al mismo tiempo, me gustaría tener alguna forma de registrar todo esa información (seguimiento de la pila e información de solicitud) a un archivo en mi servidor, por lo que puedo enviarla a mi consola y ver cómo se desplazan los errores, enviarme el registro por correo electrónico cada hora o algo así.

¿Qué soluciones de registro recomendaría para un sitio django que cumpla con esos requisitos simples? Tengo la aplicación ejecutándose como fcgiservidor y estoy usando un servidor web apache como interfaz (aunque estoy pensando en ir a lighttpd).


algo desde el campo de batalla: dlo.me/what-to-do-when-your-site-goes-viral
Cherian

2
Centinela para ver los registros: readthedocs.org/docs/sentry/en/latest/index.html
Cherian

El enlace que Cherian compartió ahora está muerto. Si intenta buscar Sentry, es probable que encuentre material para su instancia oficial paga, pero aquí está el enlace para configurar una instancia autohospedada : docs.sentry.io/server Además, aquí está el repositorio actualmente mantenido: github .com / getsentry / sentry
lehiester

Respuestas:


103

Bueno, cuando DEBUG = False, Django enviará automáticamente un seguimiento completo de cualquier error a cada persona enumerada en la ADMINSconfiguración, lo que le dará notificaciones de forma gratuita. Si desea un control más detallado, puede escribir y agregar a su configuración una clase de middleware que defina un método llamado process_exception(), que tendrá acceso a la excepción que se generó:

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

Su process_exception()método puede realizar cualquier tipo de registro que desee: escribir en la consola, escribir en un archivo, etc., etc.

Editar: aunque es un poco menos útil, también puede escuchar la got_request_exceptionseñal, que se enviará cada vez que se encuentre una excepción durante el procesamiento de la solicitud:

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

Sin embargo, esto no le da acceso al objeto de excepción, por lo que es mucho más fácil trabajar con el método de middleware.


77
Tenga en cuenta que el uso logging.exception('Some message')con el módulo de registro estándar de Python funciona bien en un controlador marginal para got_request_exception, si todo lo que está buscando hacer es cerrar sesión en los rastros de la pila. En otras palabras, el rastreo aún está disponible en got_request_exception.
TM.

la excepción pasada a process_exception no parece tener el seguimiento de la pila, ¿hay alguna forma de obtener eso?
Nick BL

79

Django Sentry es un buen camino a seguir, como ya se mencionó, pero hay un poco de trabajo involucrado en configurarlo correctamente (como un sitio web separado). Si solo desea registrar todo en un archivo de texto simple, aquí está la configuración de registro para poner en susettings.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
        },
    },
}

Estoy de acuerdo, me encanta Sentry! Quiero tener un puerto .Net (he estado trabajando en proyectos .Net últimamente).
Gromer

1
Un pequeño error tipográfico en caso de que alguien esté cortando y pegando: "propogate" en lugar de "propagate" al final.
user1228295

3
'include_html': True¡NO simplemente hace que los correos electrónicos sean "más agradables"! Incluye un rastreo completo, incluidos los valores de configuración y variables locales. Según los documentos, este es un problema de seguridad: docs.djangoproject.com/en/1.8/topics/logging/…
Thomas

1
Tengo curiosidad por saber si el controlador mail_admins (y el registrador django.request) es necesario ya que tiene 'disable_existing_loggers': falso y simplemente está replicando el registro predeterminado de django con este controlador (y registrador). Actualizaré cuando lo haya probado.
DylanYoung

Por favor actualice esta respuesta. Desde django1.9 change-log: la configuración de registro predeterminada de Django ya no define los registradores 'django.request' y 'django.security'.
narendra-choudhary



15

Ha pasado algún tiempo desde el envío de código más útil de EMP. Acabo de implementarlo, y mientras intentaba con alguna opción manage.py, para tratar de perseguir un error, recibí una advertencia de desaprobación en el sentido de que con mi versión actual de Django (1.5.?) Un filtro require_debug_false ahora es necesario para el manejador mail_admins.

Aquí está el código revisado:

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
        },
    },
}

Tengo curiosidad por saber si el controlador mail_admins (y el registrador django.request) es necesario ya que tiene 'disable_existing_loggers': falso y simplemente está replicando el registro predeterminado de django con este controlador (y registrador). Actualizaré cuando lo haya probado.
DylanYoung

1

Acabo de tener un problema molesto con mi fcgiscript. Ocurrió incluso antes de que django comenzara. La falta de registro es tan dolorosa. De todos modos, redirigir stderr a un archivo como lo primero ayudó mucho:

#!/home/user/env/bin/python
sys.stderr = open('/home/user/fcgi_errors', 'a')
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.