diff --git a/gunicorn/config.py b/gunicorn/config.py index c36d0403..c127c657 100644 --- a/gunicorn/config.py +++ b/gunicorn/config.py @@ -1309,6 +1309,24 @@ class LogConfig(Setting): """ +class LogConfigDict(Setting): + name = "logconfig_dict" + section = "Logging" + cli = ["--log-config-dict"] + validator = validate_dict + default = {} + desc = """\ + 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 + """ + + class SyslogTo(Setting): name = "syslog_addr" section = "Logging" diff --git a/gunicorn/glogging.py b/gunicorn/glogging.py index 571fda72..f5d4cfd0 100644 --- a/gunicorn/glogging.py +++ b/gunicorn/glogging.py @@ -9,6 +9,11 @@ import time import logging logging.Logger.manager.emittedNoHandlerWarning = 1 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,23 @@ class Logger(object): self.access_log, cfg, self.syslog_fmt, "access" ) - if cfg.logconfig: + 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) + 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() defaults['__file__'] = cfg.logconfig