From e6de1a07b4d11d617b4b980e2c1a3f69f0e59010 Mon Sep 17 00:00:00 2001 From: Mat Moore Date: Thu, 3 Sep 2015 16:02:00 +0100 Subject: [PATCH 1/5] Issue 1087: support dictConfig logging configuration --- gunicorn/config.py | 13 +++++++++++++ gunicorn/glogging.py | 8 ++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/gunicorn/config.py b/gunicorn/config.py index c36d0403c..8b6a23424 100644 --- a/gunicorn/config.py +++ b/gunicorn/config.py @@ -1309,6 +1309,19 @@ class LogConfig(Setting): """ +class LogConfigDict(Setting): + name = "logconfig_dict" + section = "Logging" + validator = validate_dict + default = {} + desc = """\ + The log config dictionary to use, using the standard Python logging + module's dictConfig format. + If specified, this takes precedence over logconfig, which uses the older + fileConfig format. + """ + + class SyslogTo(Setting): name = "syslog_addr" section = "Logging" diff --git a/gunicorn/glogging.py b/gunicorn/glogging.py index 571fda727..5cfe014e6 100644 --- a/gunicorn/glogging.py +++ b/gunicorn/glogging.py @@ -8,7 +8,7 @@ import time import logging logging.Logger.manager.emittedNoHandlerWarning = 1 -from logging.config import fileConfig +from logging.config import fileConfig, dictConfig import os import socket import sys @@ -226,7 +226,11 @@ def setup(self, cfg): self.access_log, cfg, self.syslog_fmt, "access" ) - if cfg.logconfig: + if cfg.logconfig_dict: + config = CONFIG_DEFAULTS.copy() + config.update(cfg.logconfig_dict) + dictConfig(config) + elif cfg.logconfig: if os.path.exists(cfg.logconfig): defaults = CONFIG_DEFAULTS.copy() defaults['__file__'] = cfg.logconfig From 9d7c857521d0a242ee2fd9d3becd50b8312caf1e Mon Sep 17 00:00:00 2001 From: Mat Moore Date: Sat, 5 Sep 2015 16:16:20 +0100 Subject: [PATCH 2/5] The logconfig_dict setting is not available on 2.6 --- gunicorn/config.py | 4 ++-- gunicorn/glogging.py | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/gunicorn/config.py b/gunicorn/config.py index 8b6a23424..2d229cae1 100644 --- a/gunicorn/config.py +++ b/gunicorn/config.py @@ -1316,8 +1316,8 @@ class LogConfigDict(Setting): default = {} desc = """\ The log config dictionary to use, using the standard Python logging - module's dictConfig format. - If specified, this takes precedence over logconfig, which uses the older + module's dictConfig format added in python 2.7. + If available, this takes precedence over logconfig, which uses the older fileConfig format. """ diff --git a/gunicorn/glogging.py b/gunicorn/glogging.py index 5cfe014e6..bac945b17 100644 --- a/gunicorn/glogging.py +++ b/gunicorn/glogging.py @@ -8,7 +8,12 @@ import time import logging logging.Logger.manager.emittedNoHandlerWarning = 1 -from logging.config import fileConfig, dictConfig +from logging.config import fileConfig +try: + from logging.config import dictConfig +except ImportError: + # python 2.6 + dictConfig = None import os import socket import sys @@ -226,7 +231,7 @@ def setup(self, cfg): self.access_log, cfg, self.syslog_fmt, "access" ) - if cfg.logconfig_dict: + if dictConfig and cfg.logconfig_dict: config = CONFIG_DEFAULTS.copy() config.update(cfg.logconfig_dict) dictConfig(config) From c5ae962dfa3c9a84dfef3af386c7b4f282d02e6e Mon Sep 17 00:00:00 2001 From: Randall Leeds Date: Sun, 29 Oct 2017 21:43:26 -0700 Subject: [PATCH 3/5] Add CLI option for dictionary log config --- gunicorn/config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gunicorn/config.py b/gunicorn/config.py index 2d229cae1..fa1b8ab5b 100644 --- a/gunicorn/config.py +++ b/gunicorn/config.py @@ -1312,6 +1312,7 @@ class LogConfig(Setting): class LogConfigDict(Setting): name = "logconfig_dict" section = "Logging" + cli = ["--log-config-dict"] validator = validate_dict default = {} desc = """\ From a7d4491a71632e85da042f9a486529ee7f6da89e Mon Sep 17 00:00:00 2001 From: Randall Leeds Date: Sun, 29 Oct 2017 21:43:41 -0700 Subject: [PATCH 4/5] Fix up documentation for dictConfig --- gunicorn/config.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/gunicorn/config.py b/gunicorn/config.py index fa1b8ab5b..c127c6578 100644 --- a/gunicorn/config.py +++ b/gunicorn/config.py @@ -1316,10 +1316,14 @@ class LogConfigDict(Setting): validator = validate_dict default = {} desc = """\ - The log config dictionary to use, using the standard Python logging - module's dictConfig format added in python 2.7. - If available, this takes precedence over logconfig, which uses the older - fileConfig format. + The log config dictionary to use, using the standard Python + logging module's dictionary configuration format. This option + takes precedence over the :ref:`logconfig` option, which uses the + older file configuration format. + + Format: https://docs.python.org/3/library/logging.config.html#logging.config.dictConfig + + .. versionadded:: 19.8 """ From 783c9bee3e761d9ecf5a820c3d9cce3ebb09a085 Mon Sep 17 00:00:00 2001 From: Randall Leeds Date: Sun, 29 Oct 2017 21:44:10 -0700 Subject: [PATCH 5/5] Warn on Python < 2.7 for dictConfig --- gunicorn/glogging.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/gunicorn/glogging.py b/gunicorn/glogging.py index bac945b17..f5d4cfd0d 100644 --- a/gunicorn/glogging.py +++ b/gunicorn/glogging.py @@ -231,10 +231,22 @@ def setup(self, cfg): self.access_log, cfg, self.syslog_fmt, "access" ) + if dictConfig is None and cfg.logconfig_dict: + util.warn("Dictionary-based log configuration requires " + "Python 2.7 or above.") + if dictConfig and cfg.logconfig_dict: config = CONFIG_DEFAULTS.copy() config.update(cfg.logconfig_dict) - dictConfig(config) + try: + dictConfig(config) + except ( + AttributeError, + ImportError, + ValueError, + TypeError + ) as exc: + raise RuntimeError(str(exc)) elif cfg.logconfig: if os.path.exists(cfg.logconfig): defaults = CONFIG_DEFAULTS.copy()