diff --git a/doc/Makefile b/doc/Makefile index fb4c7fa76936..b60cf1ffe4c4 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -58,12 +58,12 @@ clean: rm -rf ./source/rllib/package_ref/doc* html: - SKIP_LOG_RESET=True $(SPHINXBUILD) -W --keep-going -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + $(SPHINXBUILD) -W --keep-going -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." develop: - SKIP_LOG_RESET=True FAST=True $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + FAST=True $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @echo "View the documentation by opening a browser and going to $(BUILDDIR)/html/index.html." diff --git a/doc/source/conf.py b/doc/source/conf.py index 45e1ee21277c..caadf6bebed5 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -62,6 +62,7 @@ "sphinx_tabs.tabs", "sphinx_remove_toctrees", "sphinx_design", + "sphinx.ext.intersphinx", ] # Prune deep toc-trees on demand for smaller html and faster builds. @@ -107,6 +108,9 @@ "replacements", ] +intersphinx_mapping = { + "sklearn": ("https://scikit-learn.org/stable/", None), +} # Cache notebook outputs in _build/.jupyter_cache # To prevent notebook execution, set this to "off". To force re-execution, set this to "force". diff --git a/python/ray/__init__.py b/python/ray/__init__.py index e547bfd49ddc..1d69d76b134f 100644 --- a/python/ray/__init__.py +++ b/python/ray/__init__.py @@ -4,11 +4,7 @@ import os import sys -# For cases like docs builds, we want the default logging config. -skip_reset = os.environ.get("SKIP_LOG_RESET", False) -if not skip_reset: - log.generate_logging_config() - +log.generate_logging_config() logger = logging.getLogger(__name__) diff --git a/python/ray/_private/log.py b/python/ray/_private/log.py index 609baa2d2f9d..bafc7444cbf7 100644 --- a/python/ray/_private/log.py +++ b/python/ray/_private/log.py @@ -2,6 +2,30 @@ import re from logging.config import dictConfig import threading +from typing import Union + + +def _print_loggers(): + """Print a formatted list of loggers and their handlers for debugging.""" + loggers = {logging.root.name: logging.root} + loggers.update(dict(sorted(logging.root.manager.loggerDict.items()))) + for name, logger in loggers.items(): + if isinstance(logger, logging.Logger): + print(f" {name}: disabled={logger.disabled}, propagate={logger.propagate}") + for handler in logger.handlers: + print(f" {handler}") + + +def clear_logger(logger: Union[str, logging.Logger]): + """Reset a logger, clearing its handlers and enabling propagation. + + Args: + logger: Logger to be cleared + """ + if isinstance(logger, str): + logger = logging.getLogger(logger) + logger.propagate = True + logger.handlers.clear() class ContextFilter(logging.Filter): @@ -134,5 +158,6 @@ def generate_logging_config(): "filters": filters, "handlers": handlers, "loggers": loggers, + "disable_existing_loggers": False, } ) diff --git a/python/ray/_private/ray_logging.py b/python/ray/_private/ray_logging.py index 79280cfcefce..ef28b9acca0b 100644 --- a/python/ray/_private/ray_logging.py +++ b/python/ray/_private/ray_logging.py @@ -68,9 +68,7 @@ def setup_component_logger( Returns: the created or modified logger. """ - ray_logger = logging.getLogger("ray") - ray_logger.propagate = True - ray_logger.handlers.clear() + ray._private.log.clear_logger("ray") logger = logging.getLogger(logger_name) if type(logging_level) is str: diff --git a/python/ray/tests/test_logging.py b/python/ray/tests/test_logging.py index 33b0674c2e89..54de56b63759 100644 --- a/python/ray/tests/test_logging.py +++ b/python/ray/tests/test_logging.py @@ -942,6 +942,15 @@ def test_log_level_settings( assert len(caplog.records) == 0, "Log message found where none are expected." +def test_log_with_import(): + + logger = logging.getLogger(__name__) + assert not logger.disabled + ray.log.logger_initialized = False + ray.log.generate_logging_config() + assert not logger.disabled + + if __name__ == "__main__": import sys