Como você registra erros do servidor em sites django

175

Portanto, ao jogar com o desenvolvimento, posso simplesmente definir settings.DEBUGcomo Truee se ocorrer um erro, posso vê-lo bem formatado, com bom rastreamento de pilha e informações de solicitação.

Mas, no tipo de site de produção, prefiro usar DEBUG=Falsee mostrar aos visitantes uma página de erro 500 padrão com informações nas quais estou trabalhando para corrigir esse bug no momento;)
Ao mesmo tempo, gostaria de ter alguma maneira de registrar tudo essas informações (rastreamento de pilha e informações de solicitação) em um arquivo no meu servidor - para que eu possa simplesmente enviá-las para o console e observar os erros rolarem, enviar o log para mim a cada hora ou algo assim.

Quais soluções de registro você recomendaria para um site django que atendesse a esses requisitos simples? Eu tenho o aplicativo rodando como fcgiservidor e estou usando o servidor web apache como front-end (embora pensando em ir para o lighttpd).

kender
fonte
algo do campo de batalha: dlo.me/what-to-do-when-your-site-goes-viral
Cherian
2
Sentry para ver logs: readthedocs.org/docs/sentry/en/latest/index.html
Cherian
O link que Cherian compartilhou agora está morto. Se você tentar pesquisar pelo Sentry, provavelmente encontrará material para a instância oficial paga, mas aqui está o link para configurar uma instância auto-hospedada: docs.sentry.io/server Além disso, aqui está o repositório atualmente mantido: github .com / getsentry / sentry
lehiester

Respostas:

103

Bem, quando DEBUG = False, o Django enviará automaticamente um rastreamento completo de qualquer erro para cada pessoa listada na ADMINSconfiguração, o que recebe notificações praticamente de graça. Se desejar um controle mais refinado, você pode escrever e adicionar às suas configurações uma classe de middleware que defina um método chamado process_exception(), que terá acesso à exceção que foi gerada:

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

Seu process_exception()método pode executar o tipo de registro que você deseja: gravar no console, gravar em um arquivo etc., etc.

Editar: embora seja um pouco menos útil, você também pode ouvir o got_request_exceptionsinal, que será enviado sempre que uma exceção for encontrada durante o processamento da solicitação:

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

No entanto, como você não acessa o objeto de exceção, é muito mais fácil trabalhar com o método middleware.

James Bennett
fonte
7
Observe que o uso logging.exception('Some message')com o módulo de log padrão do python funciona bem em um manipulador sginal got_request_exception, se tudo o que você deseja fazer é desconectar rastreamentos de pilha. Em outras palavras, o rastreamento ainda está disponível em got_request_exception.
TM.
a exceção transmitida em process_exception não parece ter o rastreamento de pilha, existe uma maneira de obtê-lo?
Nick BL
79

O Django Sentry é um bom caminho a percorrer, como já mencionado, mas há um pouco de trabalho envolvido na configuração adequada (como um site separado). Se você quiser apenas registrar tudo em um arquivo de texto simples, aqui está a configuração de log para colocar em seusettings.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
fonte
Eu concordo, eu amo Sentry! Eu quero ter uma porta .Net (tenho trabalhado em projetos. Net ultimamente).
Gromer
1
Um pequeno erro de digitação no caso de alguém estar cortando e colando: "propagar" em vez de "propagar" no final.
User1228295
3
'include_html': Truesimplesmente não torna os e-mails "mais agradáveis"! Ele inclui um rastreamento completo, incluindo os valores das configurações e variáveis ​​locais. De acordo com os documentos, esta é uma preocupação de segurança: docs.djangoproject.com/en/1.8/topics/logging/…
Thomas
1
Estou curioso para saber se o manipulador mail_admins (e o django.request logger) é necessário, pois você tem 'disable_existing_loggers': False e está simplesmente replicando o log django padrão com esse manipulador (e logger). Vou atualizar quando eu testei.
DylanYoung
Atualize esta resposta. No django1.9 change-log: a configuração de registro padrão do Django não define mais os registradores 'django.request' e 'django.security'.
Narendra-choudhary 10/09/16
30

Obviamente, James está correto, mas se você deseja registrar exceções em um armazenamento de dados, já existem algumas soluções de código aberto disponíveis:

1) O CrashLog é uma boa opção: http://code.google.com/p/django-crashlog/

2) O Db-Log também é uma boa opção: http://code.google.com/p/django-db-log/

Qual é a diferença entre os dois? Quase nada que eu possa ver, então qualquer um será suficiente.

Eu usei os dois e eles funcionam bem.

montylounge
fonte
15

Algum tempo se passou desde o envio do código mais útil do EMP. Acabei de implementá-lo e, enquanto estou pesquisando com alguma opção manage.py, para tentar encontrar um bug, recebi um aviso de reprovação no sentido de que, com a minha versão atual do Django (1.5.?), Um filtro require_debug_false está agora necessário para o manipulador mail_admins.

Aqui está o 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
        },
    },
}
Mike O'Connor
fonte
Estou curioso para saber se o manipulador mail_admins (e o django.request logger) é necessário, pois você tem 'disable_existing_loggers': False e está simplesmente replicando o log django padrão com esse manipulador (e logger). Vou atualizar quando eu testei.
DylanYoung
1

Eu apenas tive um problema irritante com o meu fcgiscript. Isso ocorreu antes do django começar. A falta de registro é muito dolorosa. Enfim, redirecionar o stderr para um arquivo como a primeira coisa ajudou muito:

#!/home/user/env/bin/python
sys.stderr = open('/home/user/fcgi_errors', 'a')
jozxyqk
fonte