diff --git a/src/databricks/labs/dqx/__init__.py b/src/databricks/labs/dqx/__init__.py index b300062a5..b1bc04f59 100644 --- a/src/databricks/labs/dqx/__init__.py +++ b/src/databricks/labs/dqx/__init__.py @@ -3,7 +3,6 @@ import warnings import databricks.sdk.useragent as ua -from databricks.labs.blueprint.logger import install_logger from databricks.labs.dqx.__about__ import __version__ # Suppress Databricks notebook LSP warning @@ -13,7 +12,9 @@ category=UserWarning, ) -install_logger() +# Do not reconfigure the root logger on import (issue #1136); a library should leave logging +# configuration to the application, so we attach a NullHandler to our own logger instead. +logging.getLogger("databricks.labs.dqx").addHandler(logging.NullHandler()) # Route Python warnings through logging for consistent formatting # (Some modules like check_funcs still use warnings.warn for backward compatibility) diff --git a/tests/unit/test_logging_setup.py b/tests/unit/test_logging_setup.py new file mode 100644 index 000000000..6bca70685 --- /dev/null +++ b/tests/unit/test_logging_setup.py @@ -0,0 +1,26 @@ +import importlib +import logging + +import databricks.labs.dqx + + +def test_importing_dqx_does_not_reconfigure_the_root_logger(): + # Regression test for issue #1136: re-running the import must leave the root logger untouched. + root = logging.getLogger() + app_handler = logging.StreamHandler() + original_level = root.level + root.addHandler(app_handler) + root.setLevel(logging.WARNING) + try: + importlib.reload(databricks.labs.dqx) + assert app_handler in root.handlers + assert root.level == logging.WARNING + finally: + root.removeHandler(app_handler) + root.setLevel(original_level) + + +def test_importing_dqx_attaches_a_null_handler_to_its_own_logger(): + importlib.reload(databricks.labs.dqx) + dqx_logger = logging.getLogger("databricks.labs.dqx") + assert any(isinstance(handler, logging.NullHandler) for handler in dqx_logger.handlers)