From a014ddfef2f606471f25c756d97b3b50fcbd9e91 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Mon, 24 Sep 2012 22:30:38 +0200 Subject: [PATCH] Combined Django DEFAULT_LOGGING with user LOGGING config Refs #18993. --- django/conf/__init__.py | 12 +++++++---- django/conf/global_settings.py | 29 ++----------------------- django/utils/log.py | 39 ++++++++++++++++++++++++++++------ docs/topics/logging.txt | 22 +++++++++++++++++++ 4 files changed, 65 insertions(+), 37 deletions(-) diff --git a/django/conf/__init__.py b/django/conf/__init__.py index d636ff0b6c..7452013671 100644 --- a/django/conf/__init__.py +++ b/django/conf/__init__.py @@ -55,16 +55,20 @@ class LazySettings(LazyObject): Setup logging from LOGGING_CONFIG and LOGGING settings. """ if self.LOGGING_CONFIG: + from django.utils.log import DEFAULT_LOGGING # First find the logging configuration function ... logging_config_path, logging_config_func_name = self.LOGGING_CONFIG.rsplit('.', 1) logging_config_module = importlib.import_module(logging_config_path) logging_config_func = getattr(logging_config_module, logging_config_func_name) - # Backwards-compatibility shim for #16288 fix - compat_patch_logging_config(self.LOGGING) + logging_config_func(DEFAULT_LOGGING) - # ... then invoke it with the logging settings - logging_config_func(self.LOGGING) + if self.LOGGING: + # Backwards-compatibility shim for #16288 fix + compat_patch_logging_config(self.LOGGING) + + # ... then invoke it with the logging settings + logging_config_func(self.LOGGING) def configure(self, default_settings=global_settings, **options): """ diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index 708e9c9f70..f1cbb22880 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -551,33 +551,8 @@ MESSAGE_STORAGE = 'django.contrib.messages.storage.fallback.FallbackStorage' # The callable to use to configure logging LOGGING_CONFIG = 'django.utils.log.dictConfig' -# The default logging configuration. This sends an email to -# the site admins on every HTTP 500 error. All other log -# records are sent to the bit bucket. - -LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'filters': { - 'require_debug_false': { - '()': 'django.utils.log.RequireDebugFalse', - } - }, - 'handlers': { - 'mail_admins': { - 'level': 'ERROR', - 'filters': ['require_debug_false'], - 'class': 'django.utils.log.AdminEmailHandler' - } - }, - 'loggers': { - 'django.request': { - 'handlers': ['mail_admins'], - 'level': 'ERROR', - 'propagate': True, - }, - } -} +# Custom logging configuration. +LOGGING = {} # Default exception reporter filter class used in case none has been # specifically assigned to the HttpRequest instance. diff --git a/django/utils/log.py b/django/utils/log.py index df2089f924..c111512fe8 100644 --- a/django/utils/log.py +++ b/django/utils/log.py @@ -5,6 +5,7 @@ from django.conf import settings from django.core import mail from django.views.debug import ExceptionReporter, get_exception_reporter_filter + # Make sure a NullHandler is available # This was added in Python 2.7/3.2 try: @@ -23,12 +24,38 @@ except ImportError: getLogger = logging.getLogger -# Ensure the creation of the Django logger -# with a null handler. This ensures we don't get any -# 'No handlers could be found for logger "django"' messages -logger = getLogger('django') -if not logger.handlers: - logger.addHandler(NullHandler()) +# Default logging for Django. This sends an email to +# the site admins on every HTTP 500 error. All other log +# records are sent to the bit bucket. +DEFAULT_LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'filters': { + 'require_debug_false': { + '()': 'django.utils.log.RequireDebugFalse', + } + }, + 'handlers': { + 'null': { + 'class': 'django.utils.log.NullHandler', + }, + 'mail_admins': { + 'level': 'ERROR', + 'filters': ['require_debug_false'], + 'class': 'django.utils.log.AdminEmailHandler' + } + }, + 'loggers': { + 'django': { + 'handlers': ['null'], + }, + 'django.request': { + 'handlers': ['mail_admins'], + 'level': 'ERROR', + 'propagate': True, + }, + } +} class AdminEmailHandler(logging.Handler): diff --git a/docs/topics/logging.txt b/docs/topics/logging.txt index a4aae0bc02..a7f0a14b5b 100644 --- a/docs/topics/logging.txt +++ b/docs/topics/logging.txt @@ -192,6 +192,8 @@ There are two other logging calls available: * ``logger.exception()``: Creates an ``ERROR`` level logging message wrapping the current exception stack frame. +.. _configuring-logging: + Configuring logging =================== @@ -216,6 +218,14 @@ handlers, filters and formatters that you want in your logging setup, and the log levels and other properties that you want those components to have. +Prior to Django 1.5, the :setting:`LOGGING` setting overwrote the :ref:`default +Django logging configuration `. From Django +1.5 forward, the project's logging configuration is merged with Django's +defaults, hence you can decide if you want to add to, or replace the existing +configuration. To completely override the default configuration, set the +``disable_existing_loggers`` key to True in the :setting:`LOGGING` +dictConfig. Alternatively you can redefine some or all of the loggers. + Logging is configured as soon as settings have been loaded (either manually using :func:`~django.conf.settings.configure` or when at least one setting is accessed). Since the loading of settings is one of the first @@ -535,3 +545,15 @@ logging module. 'class': 'django.utils.log.AdminEmailHandler' } }, + +.. _default-logging-configuration: + +Django's default logging configuration +====================================== + +By default, Django configures the ``django.request`` logger so that all messages +with ``ERROR`` or ``CRITICAL`` level are sent to :class:`AdminEmailHandler`, as +long as the :setting:`DEBUG` setting is set to ``False``. + +All messages reaching the ``django`` catch-all logger are discarded +(sent to ``NullHandler``).