From 7e30d42fae864fa2cdd0ea72495d658b589ee2a4 Mon Sep 17 00:00:00 2001 From: Dillon Niederhut Date: Mon, 12 Aug 2019 21:28:41 -0500 Subject: [PATCH 1/2] BUG: allows logging config under distributed key The logging documentation specifies a configuration path to logging info like config['distributed']['logging'], but the config module looks in config['logging']. This commit allows both by looking first in config['distributed'], then falling back to config. Closes https://github.com/dask/distributed/issues/2937 --- distributed/config.py | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/distributed/config.py b/distributed/config.py index 7e6075125fd..69899533e99 100644 --- a/distributed/config.py +++ b/distributed/config.py @@ -80,7 +80,8 @@ def _initialize_logging_old_style(config): "tornado": "critical", "tornado.application": "error", } - loggers.update(config.get("logging", {})) + base_config = _find_logging_config(config) + loggers.update(base_config.get("logging", {})) handler = logging.StreamHandler(sys.stderr) handler.setFormatter( @@ -103,7 +104,8 @@ def _initialize_logging_new_style(config): Initialize logging using logging's "Configuration dictionary schema". (ref.: https://docs.python.org/3/library/logging.config.html#configuration-dictionary-schema) """ - logging.config.dictConfig(config.get("logging")) + base_config = _find_logging_config(config) + logging.config.dictConfig(base_config.get("logging")) def _initialize_logging_file_config(config): @@ -111,20 +113,34 @@ def _initialize_logging_file_config(config): Initialize logging using logging's "Configuration file format". (ref.: https://docs.python.org/3/howto/logging.html#configuring-logging) """ + base_config = _find_logging_config(config) logging.config.fileConfig( - config.get("logging-file-config"), disable_existing_loggers=False + base_config.get("logging-file-config"), disable_existing_loggers=False ) +def _find_logging_config(config): + """ + Look for the dictionary containing logging-specific configurations, + starting in the 'distributed' dictionary and then trying the top-level + """ + logging_keys = {"logging-file-config", "logging"} + if logging_keys & config.get("distributed", {}).keys(): + return config["distributed"] + else: + return config + + def initialize_logging(config): - if "logging-file-config" in config: - if "logging" in config: + base_config = _find_logging_config(config) + if "logging-file-config" in base_config: + if "logging" in base_config: raise RuntimeError( "Config options 'logging-file-config' and 'logging' are mutually exclusive." ) _initialize_logging_file_config(config) else: - log_config = config.get("logging", {}) + log_config = base_config.get("logging", {}) if "version" in log_config: # logging module mandates version to be an int log_config["version"] = int(log_config["version"]) From 397fc5a558e56c904d254b1c059b71ed54f52020 Mon Sep 17 00:00:00 2001 From: Dillon Niederhut Date: Sat, 28 Sep 2019 19:07:27 -0500 Subject: [PATCH 2/2] TST: logger finds config under 'distributed' --- distributed/tests/test_config.py | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/distributed/tests/test_config.py b/distributed/tests/test_config.py index 2017bb239f7..83ac3d55fe3 100644 --- a/distributed/tests/test_config.py +++ b/distributed/tests/test_config.py @@ -108,6 +108,45 @@ def test_logging_empty_simple(): test_logging_default() +def test_logging_simple_under_distributed(): + """ + Test simple ("old-style") logging configuration under the distributed key. + """ + c = { + "distributed": { + "logging": {"distributed.foo": "info", "distributed.foo.bar": "error"} + } + } + # Must test using a subprocess to avoid wrecking pre-existing configuration + with new_config_file(c): + code = """if 1: + import logging + import dask + + from distributed.utils_test import captured_handler + + d = logging.getLogger('distributed') + assert len(d.handlers) == 1 + assert isinstance(d.handlers[0], logging.StreamHandler) + df = logging.getLogger('distributed.foo') + dfb = logging.getLogger('distributed.foo.bar') + + with captured_handler(d.handlers[0]) as distributed_log: + df.info("1: info") + dfb.warning("2: warning") + dfb.error("3: error") + + distributed_log = distributed_log.getvalue().splitlines() + + assert distributed_log == [ + "distributed.foo - INFO - 1: info", + "distributed.foo.bar - ERROR - 3: error", + ], (dask.config.config, distributed_log) + """ + + subprocess.check_call([sys.executable, "-c", code]) + + def test_logging_simple(): """ Test simple ("old-style") logging configuration.