I know this is already a resolved answer, but according to django> = 1.3 there is a new logging setting.
The transition from the old to the new is not automatic, so I decided to record it here.
And of course also django doc .
This is the base conf created by default using django-admin createproject v1.3 - mileage can be changed using the latest django versions:
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, } } }
This structure is based on the standard Python logging dictConfig , which dictates the following blocks:
formatters - the corresponding value will be a dict, in which each key is a formatting identifier, and each value is a dict that describes how to configure the corresponding Formatter instance.filters - the corresponding value will be a dict, in which each key is a filter identifier, and each value is a dict that describes how to configure the corresponding filter instance.handlers - the corresponding value will be a dict, in which each key is the identifier of the handler, and each value is a dict that describes how to configure the corresponding Handler instance. Each handler has the following keys:
class (required). This is the fully qualified name of the handler class.level (optional). Handler level.formatter (optional). The formatting identifier for this handler.filters (optional). A list of filter identifiers for this handler.
I usually do this at least:
- add .log file
- configure my applications to write to this log
It means:
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' }, }
change
See exception requests are now always logged and Ticket # 16288 :
I updated the above conf example to explicitly enable the correct filter for mail_admins so that by default emails are not sent when debug is True.
You must add a filter:
'filters': { 'require_debug_false': { '()': 'django.utils.log.RequireDebugFalse' } },
and apply it to the mail_admins handler:
'mail_admins': { 'level': 'ERROR', 'filters': ['require_debug_false'], 'class': 'django.utils.log.AdminEmailHandler', 'include_html': True, }
Otherwise, django.core.handers.base.handle_uncaught_exception does not send errors to the django.request log if the .DEBUG parameters are True.
If you do not do this in Django 1.5, you will get
DeprecationWarning: you have no filters defined in the mail_admins log handler: adding an implicit filter debug-false-only
but everything will work correctly BOTH in django 1.4 and django 1.5.
** end edit **
This conf is heavily inspired by the conf pattern in the django doc, but adds a portion of the log file.
I also often do the following:
LOG_LEVEL = 'DEBUG' if DEBUG else 'INFO' ... 'level': LOG_LEVEL ...
Then in my Python code I always add NullHandler in case no logging protocol is defined. This avoids warnings that a handler is not specified. Especially useful for libraries that are not necessarily called only in Django ( ref )
import logging
[...]
logger.warning('etc.etc.')
Hope this helps!