Eu sei que esta é uma resposta já resolvida, mas de acordo com django> = 1.3 há uma nova configuração de registro.
Mudar do antigo para o novo não é automático, então pensei em escrever aqui.
E, claro, verifique o doc django para mais alguns.
Esta é a configuração básica, criada por padrão com django-admin createproject v1.3 - a milhagem pode mudar com as últimas versões do django:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
}
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
}
}
}
Essa estrutura é baseada no dictConfig de registro padrão do Python , que dita os seguintes blocos:
Normalmente faço pelo menos isto:
- adicionar um arquivo .log
- configurar meus aplicativos para escrever neste log
O que se traduz em:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
},
'simple': {
'format': '%(levelname)s %(message)s'
},
},
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'handlers': {
'null': {
'level':'DEBUG',
'class':'django.utils.log.NullHandler',
},
'console':{
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'simple'
},
# I always add this handler to facilitate separating loggings
'log_file':{
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(VAR_ROOT, 'logs/django.log'),
'maxBytes': '16777216', # 16megabytes
'formatter': 'verbose'
},
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler',
'include_html': True,
}
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
'apps': { # I keep all my of apps under 'apps' folder, but you can also add them one by one, and this depends on how your virtualenv/paths are set
'handlers': ['log_file'],
'level': 'INFO',
'propagate': True,
},
},
# you can also shortcut 'loggers' and just configure logging for EVERYTHING at once
'root': {
'handlers': ['console', 'mail_admins'],
'level': 'INFO'
},
}
editar
Veja as exceções de solicitação agora sempre registradas e o tíquete nº 16288 :
Eu atualizei o exemplo de configuração acima para incluir explicitamente o filtro correto para mail_admins para que, por padrão, os e-mails não sejam enviados quando a depuração for True.
Você deve adicionar um filtro:
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
e aplique-o ao manipulador mail_admins:
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler',
'include_html': True,
}
Caso contrário, o django.core.handers.base.handle_uncaught_exception
não passa erros para o registrador 'django.request' se settings.DEBUG for True.
Se você não fizer isso no Django 1.5, você obterá um
Aviso de descontinuação: Você não tem filtros definidos no gerenciador de registro 'mail_admins': adicionando filtro implícito debug-false-only
mas as coisas ainda funcionarão corretamente AMBOS no Django 1.4 e no Django 1.5.
** fim da edição **
Esse conf é fortemente inspirado pelo conf de amostra no doc django, mas adicionando a parte do arquivo de log.
Freqüentemente também faço o seguinte:
LOG_LEVEL = 'DEBUG' if DEBUG else 'INFO'
...
'level': LOG_LEVEL
...
Então, em meu código python, sempre adiciono um NullHandler no caso de nenhuma configuração de registro ser definida. Isso evita avisos para nenhum Handler especificado. Especialmente útil para libs que não são necessariamente chamados apenas no Django ( ref )
import logging
# Get an instance of a logger
logger = logging.getLogger(__name__)
class NullHandler(logging.Handler): #exists in python 3.1
def emit(self, record):
pass
nullhandler = logger.addHandler(NullHandler())
# here you can also add some local logger should you want: to stdout with streamhandler, or to a local file...
[...]
logger.warning('etc.etc.')
Espero que isto ajude!